mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
Merge branch 'for-4.14/block' of git://git.kernel.dk/linux-block
Pull block layer updates from Jens Axboe:
"This is the first pull request for 4.14, containing most of the code
changes. It's a quiet series this round, which I think we needed after
the churn of the last few series. This contains:
- Fix for a registration race in loop, from Anton Volkov.
- Overflow complaint fix from Arnd for DAC960.
- Series of drbd changes from the usual suspects.
- Conversion of the stec/skd driver to blk-mq. From Bart.
- A few BFQ improvements/fixes from Paolo.
- CFQ improvement from Ritesh, allowing idling for group idle.
- A few fixes found by Dan's smatch, courtesy of Dan.
- A warning fixup for a race between changing the IO scheduler and
device remova. From David Jeffery.
- A few nbd fixes from Josef.
- Support for cgroup info in blktrace, from Shaohua.
- Also from Shaohua, new features in the null_blk driver to allow it
to actually hold data, among other things.
- Various corner cases and error handling fixes from Weiping Zhang.
- Improvements to the IO stats tracking for blk-mq from me. Can
drastically improve performance for fast devices and/or big
machines.
- Series from Christoph removing bi_bdev as being needed for IO
submission, in preparation for nvme multipathing code.
- Series from Bart, including various cleanups and fixes for switch
fall through case complaints"
* 'for-4.14/block' of git://git.kernel.dk/linux-block: (162 commits)
kernfs: checking for IS_ERR() instead of NULL
drbd: remove BIOSET_NEED_RESCUER flag from drbd_{md_,}io_bio_set
drbd: Fix allyesconfig build, fix recent commit
drbd: switch from kmalloc() to kmalloc_array()
drbd: abort drbd_start_resync if there is no connection
drbd: move global variables to drbd namespace and make some static
drbd: rename "usermode_helper" to "drbd_usermode_helper"
drbd: fix race between handshake and admin disconnect/down
drbd: fix potential deadlock when trying to detach during handshake
drbd: A single dot should be put into a sequence.
drbd: fix rmmod cleanup, remove _all_ debugfs entries
drbd: Use setup_timer() instead of init_timer() to simplify the code.
drbd: fix potential get_ldev/put_ldev refcount imbalance during attach
drbd: new disk-option disable-write-same
drbd: Fix resource role for newly created resources in events2
drbd: mark symbols static where possible
drbd: Send P_NEG_ACK upon write error in protocol != C
drbd: add explicit plugging when submitting batches
drbd: change list_for_each_safe to while(list_first_entry_or_null)
drbd: introduce drbd_recv_header_maybe_unplug
...
This commit is contained in:
commit
a0725ab0c7
160 changed files with 3684 additions and 3486 deletions
111
fs/kernfs/dir.c
111
fs/kernfs/dir.c
|
|
@ -21,6 +21,7 @@
|
|||
DEFINE_MUTEX(kernfs_mutex);
|
||||
static DEFINE_SPINLOCK(kernfs_rename_lock); /* kn->parent and ->name */
|
||||
static char kernfs_pr_cont_buf[PATH_MAX]; /* protected by rename_lock */
|
||||
static DEFINE_SPINLOCK(kernfs_idr_lock); /* root->ino_idr */
|
||||
|
||||
#define rb_to_kn(X) rb_entry((X), struct kernfs_node, rb)
|
||||
|
||||
|
|
@ -507,6 +508,10 @@ void kernfs_put(struct kernfs_node *kn)
|
|||
struct kernfs_node *parent;
|
||||
struct kernfs_root *root;
|
||||
|
||||
/*
|
||||
* kernfs_node is freed with ->count 0, kernfs_find_and_get_node_by_ino
|
||||
* depends on this to filter reused stale node
|
||||
*/
|
||||
if (!kn || !atomic_dec_and_test(&kn->count))
|
||||
return;
|
||||
root = kernfs_root(kn);
|
||||
|
|
@ -533,7 +538,9 @@ void kernfs_put(struct kernfs_node *kn)
|
|||
simple_xattrs_free(&kn->iattr->xattrs);
|
||||
}
|
||||
kfree(kn->iattr);
|
||||
ida_simple_remove(&root->ino_ida, kn->ino);
|
||||
spin_lock(&kernfs_idr_lock);
|
||||
idr_remove(&root->ino_idr, kn->id.ino);
|
||||
spin_unlock(&kernfs_idr_lock);
|
||||
kmem_cache_free(kernfs_node_cache, kn);
|
||||
|
||||
kn = parent;
|
||||
|
|
@ -542,7 +549,7 @@ void kernfs_put(struct kernfs_node *kn)
|
|||
goto repeat;
|
||||
} else {
|
||||
/* just released the root kn, free @root too */
|
||||
ida_destroy(&root->ino_ida);
|
||||
idr_destroy(&root->ino_idr);
|
||||
kfree(root);
|
||||
}
|
||||
}
|
||||
|
|
@ -559,7 +566,7 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
|
|||
if (d_really_is_negative(dentry))
|
||||
goto out_bad_unlocked;
|
||||
|
||||
kn = dentry->d_fsdata;
|
||||
kn = kernfs_dentry_node(dentry);
|
||||
mutex_lock(&kernfs_mutex);
|
||||
|
||||
/* The kernfs node has been deactivated */
|
||||
|
|
@ -567,7 +574,7 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
|
|||
goto out_bad;
|
||||
|
||||
/* The kernfs node has been moved? */
|
||||
if (dentry->d_parent->d_fsdata != kn->parent)
|
||||
if (kernfs_dentry_node(dentry->d_parent) != kn->parent)
|
||||
goto out_bad;
|
||||
|
||||
/* The kernfs node has been renamed */
|
||||
|
|
@ -587,14 +594,8 @@ out_bad_unlocked:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void kernfs_dop_release(struct dentry *dentry)
|
||||
{
|
||||
kernfs_put(dentry->d_fsdata);
|
||||
}
|
||||
|
||||
const struct dentry_operations kernfs_dops = {
|
||||
.d_revalidate = kernfs_dop_revalidate,
|
||||
.d_release = kernfs_dop_release,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -610,8 +611,9 @@ const struct dentry_operations kernfs_dops = {
|
|||
*/
|
||||
struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry)
|
||||
{
|
||||
if (dentry->d_sb->s_op == &kernfs_sops)
|
||||
return dentry->d_fsdata;
|
||||
if (dentry->d_sb->s_op == &kernfs_sops &&
|
||||
!d_really_is_negative(dentry))
|
||||
return kernfs_dentry_node(dentry);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -620,6 +622,8 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
|
|||
unsigned flags)
|
||||
{
|
||||
struct kernfs_node *kn;
|
||||
u32 gen;
|
||||
int cursor;
|
||||
int ret;
|
||||
|
||||
name = kstrdup_const(name, GFP_KERNEL);
|
||||
|
|
@ -630,11 +634,25 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
|
|||
if (!kn)
|
||||
goto err_out1;
|
||||
|
||||
ret = ida_simple_get(&root->ino_ida, 1, 0, GFP_KERNEL);
|
||||
idr_preload(GFP_KERNEL);
|
||||
spin_lock(&kernfs_idr_lock);
|
||||
cursor = idr_get_cursor(&root->ino_idr);
|
||||
ret = idr_alloc_cyclic(&root->ino_idr, kn, 1, 0, GFP_ATOMIC);
|
||||
if (ret >= 0 && ret < cursor)
|
||||
root->next_generation++;
|
||||
gen = root->next_generation;
|
||||
spin_unlock(&kernfs_idr_lock);
|
||||
idr_preload_end();
|
||||
if (ret < 0)
|
||||
goto err_out2;
|
||||
kn->ino = ret;
|
||||
kn->id.ino = ret;
|
||||
kn->id.generation = gen;
|
||||
|
||||
/*
|
||||
* set ino first. This barrier is paired with atomic_inc_not_zero in
|
||||
* kernfs_find_and_get_node_by_ino
|
||||
*/
|
||||
smp_mb__before_atomic();
|
||||
atomic_set(&kn->count, 1);
|
||||
atomic_set(&kn->active, KN_DEACTIVATED_BIAS);
|
||||
RB_CLEAR_NODE(&kn->rb);
|
||||
|
|
@ -666,6 +684,54 @@ struct kernfs_node *kernfs_new_node(struct kernfs_node *parent,
|
|||
return kn;
|
||||
}
|
||||
|
||||
/*
|
||||
* kernfs_find_and_get_node_by_ino - get kernfs_node from inode number
|
||||
* @root: the kernfs root
|
||||
* @ino: inode number
|
||||
*
|
||||
* RETURNS:
|
||||
* NULL on failure. Return a kernfs node with reference counter incremented
|
||||
*/
|
||||
struct kernfs_node *kernfs_find_and_get_node_by_ino(struct kernfs_root *root,
|
||||
unsigned int ino)
|
||||
{
|
||||
struct kernfs_node *kn;
|
||||
|
||||
rcu_read_lock();
|
||||
kn = idr_find(&root->ino_idr, ino);
|
||||
if (!kn)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Since kernfs_node is freed in RCU, it's possible an old node for ino
|
||||
* is freed, but reused before RCU grace period. But a freed node (see
|
||||
* kernfs_put) or an incompletedly initialized node (see
|
||||
* __kernfs_new_node) should have 'count' 0. We can use this fact to
|
||||
* filter out such node.
|
||||
*/
|
||||
if (!atomic_inc_not_zero(&kn->count)) {
|
||||
kn = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* The node could be a new node or a reused node. If it's a new node,
|
||||
* we are ok. If it's reused because of RCU (because of
|
||||
* SLAB_TYPESAFE_BY_RCU), the __kernfs_new_node always sets its 'ino'
|
||||
* before 'count'. So if 'count' is uptodate, 'ino' should be uptodate,
|
||||
* hence we can use 'ino' to filter stale node.
|
||||
*/
|
||||
if (kn->id.ino != ino)
|
||||
goto out;
|
||||
rcu_read_unlock();
|
||||
|
||||
return kn;
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
kernfs_put(kn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* kernfs_add_one - add kernfs_node to parent without warning
|
||||
* @kn: kernfs_node to be added
|
||||
|
|
@ -875,13 +941,14 @@ struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
|
|||
if (!root)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ida_init(&root->ino_ida);
|
||||
idr_init(&root->ino_idr);
|
||||
INIT_LIST_HEAD(&root->supers);
|
||||
root->next_generation = 1;
|
||||
|
||||
kn = __kernfs_new_node(root, "", S_IFDIR | S_IRUGO | S_IXUGO,
|
||||
KERNFS_DIR);
|
||||
if (!kn) {
|
||||
ida_destroy(&root->ino_ida);
|
||||
idr_destroy(&root->ino_idr);
|
||||
kfree(root);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
|
@ -984,7 +1051,7 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir,
|
|||
unsigned int flags)
|
||||
{
|
||||
struct dentry *ret;
|
||||
struct kernfs_node *parent = dentry->d_parent->d_fsdata;
|
||||
struct kernfs_node *parent = dir->i_private;
|
||||
struct kernfs_node *kn;
|
||||
struct inode *inode;
|
||||
const void *ns = NULL;
|
||||
|
|
@ -1001,8 +1068,6 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir,
|
|||
ret = NULL;
|
||||
goto out_unlock;
|
||||
}
|
||||
kernfs_get(kn);
|
||||
dentry->d_fsdata = kn;
|
||||
|
||||
/* attach dentry and inode */
|
||||
inode = kernfs_get_inode(dir->i_sb, kn);
|
||||
|
|
@ -1039,7 +1104,7 @@ static int kernfs_iop_mkdir(struct inode *dir, struct dentry *dentry,
|
|||
|
||||
static int kernfs_iop_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
{
|
||||
struct kernfs_node *kn = dentry->d_fsdata;
|
||||
struct kernfs_node *kn = kernfs_dentry_node(dentry);
|
||||
struct kernfs_syscall_ops *scops = kernfs_root(kn)->syscall_ops;
|
||||
int ret;
|
||||
|
||||
|
|
@ -1059,7 +1124,7 @@ static int kernfs_iop_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
struct inode *new_dir, struct dentry *new_dentry,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct kernfs_node *kn = old_dentry->d_fsdata;
|
||||
struct kernfs_node *kn = kernfs_dentry_node(old_dentry);
|
||||
struct kernfs_node *new_parent = new_dir->i_private;
|
||||
struct kernfs_syscall_ops *scops = kernfs_root(kn)->syscall_ops;
|
||||
int ret;
|
||||
|
|
@ -1572,7 +1637,7 @@ static struct kernfs_node *kernfs_dir_next_pos(const void *ns,
|
|||
static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx)
|
||||
{
|
||||
struct dentry *dentry = file->f_path.dentry;
|
||||
struct kernfs_node *parent = dentry->d_fsdata;
|
||||
struct kernfs_node *parent = kernfs_dentry_node(dentry);
|
||||
struct kernfs_node *pos = file->private_data;
|
||||
const void *ns = NULL;
|
||||
|
||||
|
|
@ -1589,7 +1654,7 @@ static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx)
|
|||
const char *name = pos->name;
|
||||
unsigned int type = dt_type(pos);
|
||||
int len = strlen(name);
|
||||
ino_t ino = pos->ino;
|
||||
ino_t ino = pos->id.ino;
|
||||
|
||||
ctx->pos = pos->hash;
|
||||
file->private_data = pos;
|
||||
|
|
|
|||
|
|
@ -616,7 +616,7 @@ static void kernfs_put_open_node(struct kernfs_node *kn,
|
|||
|
||||
static int kernfs_fop_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct kernfs_node *kn = file->f_path.dentry->d_fsdata;
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
struct kernfs_root *root = kernfs_root(kn);
|
||||
const struct kernfs_ops *ops;
|
||||
struct kernfs_open_file *of;
|
||||
|
|
@ -768,7 +768,7 @@ static void kernfs_release_file(struct kernfs_node *kn,
|
|||
|
||||
static int kernfs_fop_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct kernfs_node *kn = filp->f_path.dentry->d_fsdata;
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
struct kernfs_open_file *of = kernfs_of(filp);
|
||||
|
||||
if (kn->flags & KERNFS_HAS_RELEASE) {
|
||||
|
|
@ -835,7 +835,7 @@ void kernfs_drain_open_files(struct kernfs_node *kn)
|
|||
static unsigned int kernfs_fop_poll(struct file *filp, poll_table *wait)
|
||||
{
|
||||
struct kernfs_open_file *of = kernfs_of(filp);
|
||||
struct kernfs_node *kn = filp->f_path.dentry->d_fsdata;
|
||||
struct kernfs_node *kn = kernfs_dentry_node(filp->f_path.dentry);
|
||||
struct kernfs_open_node *on = kn->attr.open;
|
||||
|
||||
if (!kernfs_get_active(kn))
|
||||
|
|
@ -895,7 +895,7 @@ repeat:
|
|||
* have the matching @file available. Look up the inodes
|
||||
* and generate the events manually.
|
||||
*/
|
||||
inode = ilookup(info->sb, kn->ino);
|
||||
inode = ilookup(info->sb, kn->id.ino);
|
||||
if (!inode)
|
||||
continue;
|
||||
|
||||
|
|
@ -903,7 +903,7 @@ repeat:
|
|||
if (parent) {
|
||||
struct inode *p_inode;
|
||||
|
||||
p_inode = ilookup(info->sb, parent->ino);
|
||||
p_inode = ilookup(info->sb, parent->id.ino);
|
||||
if (p_inode) {
|
||||
fsnotify(p_inode, FS_MODIFY | FS_EVENT_ON_CHILD,
|
||||
inode, FSNOTIFY_EVENT_INODE, kn->name, 0);
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ int kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr)
|
|||
int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
struct kernfs_node *kn = dentry->d_fsdata;
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
int error;
|
||||
|
||||
if (!kn)
|
||||
|
|
@ -154,7 +154,7 @@ static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata,
|
|||
|
||||
ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
|
||||
{
|
||||
struct kernfs_node *kn = dentry->d_fsdata;
|
||||
struct kernfs_node *kn = kernfs_dentry_node(dentry);
|
||||
struct kernfs_iattrs *attrs;
|
||||
|
||||
attrs = kernfs_iattrs(kn);
|
||||
|
|
@ -203,8 +203,8 @@ static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode)
|
|||
int kernfs_iop_getattr(const struct path *path, struct kstat *stat,
|
||||
u32 request_mask, unsigned int query_flags)
|
||||
{
|
||||
struct kernfs_node *kn = path->dentry->d_fsdata;
|
||||
struct inode *inode = d_inode(path->dentry);
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
|
||||
mutex_lock(&kernfs_mutex);
|
||||
kernfs_refresh_inode(kn, inode);
|
||||
|
|
@ -220,6 +220,7 @@ static void kernfs_init_inode(struct kernfs_node *kn, struct inode *inode)
|
|||
inode->i_private = kn;
|
||||
inode->i_mapping->a_ops = &kernfs_aops;
|
||||
inode->i_op = &kernfs_iops;
|
||||
inode->i_generation = kn->id.generation;
|
||||
|
||||
set_default_inode_attr(inode, kn->mode);
|
||||
kernfs_refresh_inode(kn, inode);
|
||||
|
|
@ -265,7 +266,7 @@ struct inode *kernfs_get_inode(struct super_block *sb, struct kernfs_node *kn)
|
|||
{
|
||||
struct inode *inode;
|
||||
|
||||
inode = iget_locked(sb, kn->ino);
|
||||
inode = iget_locked(sb, kn->id.ino);
|
||||
if (inode && (inode->i_state & I_NEW))
|
||||
kernfs_init_inode(kn, inode);
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,13 @@ struct kernfs_super_info {
|
|||
};
|
||||
#define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info))
|
||||
|
||||
static inline struct kernfs_node *kernfs_dentry_node(struct dentry *dentry)
|
||||
{
|
||||
if (d_really_is_negative(dentry))
|
||||
return NULL;
|
||||
return d_inode(dentry)->i_private;
|
||||
}
|
||||
|
||||
extern const struct super_operations kernfs_sops;
|
||||
extern struct kmem_cache *kernfs_node_cache;
|
||||
|
||||
|
|
@ -98,6 +105,8 @@ int kernfs_add_one(struct kernfs_node *kn);
|
|||
struct kernfs_node *kernfs_new_node(struct kernfs_node *parent,
|
||||
const char *name, umode_t mode,
|
||||
unsigned flags);
|
||||
struct kernfs_node *kernfs_find_and_get_node_by_ino(struct kernfs_root *root,
|
||||
unsigned int ino);
|
||||
|
||||
/*
|
||||
* file.c
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/pagemap.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/exportfs.h>
|
||||
|
||||
#include "kernfs-internal.h"
|
||||
|
||||
|
|
@ -33,7 +34,7 @@ static int kernfs_sop_remount_fs(struct super_block *sb, int *flags, char *data)
|
|||
|
||||
static int kernfs_sop_show_options(struct seq_file *sf, struct dentry *dentry)
|
||||
{
|
||||
struct kernfs_root *root = kernfs_root(dentry->d_fsdata);
|
||||
struct kernfs_root *root = kernfs_root(kernfs_dentry_node(dentry));
|
||||
struct kernfs_syscall_ops *scops = root->syscall_ops;
|
||||
|
||||
if (scops && scops->show_options)
|
||||
|
|
@ -43,7 +44,7 @@ static int kernfs_sop_show_options(struct seq_file *sf, struct dentry *dentry)
|
|||
|
||||
static int kernfs_sop_show_path(struct seq_file *sf, struct dentry *dentry)
|
||||
{
|
||||
struct kernfs_node *node = dentry->d_fsdata;
|
||||
struct kernfs_node *node = kernfs_dentry_node(dentry);
|
||||
struct kernfs_root *root = kernfs_root(node);
|
||||
struct kernfs_syscall_ops *scops = root->syscall_ops;
|
||||
|
||||
|
|
@ -64,6 +65,78 @@ const struct super_operations kernfs_sops = {
|
|||
.show_path = kernfs_sop_show_path,
|
||||
};
|
||||
|
||||
/*
|
||||
* Similar to kernfs_fh_get_inode, this one gets kernfs node from inode
|
||||
* number and generation
|
||||
*/
|
||||
struct kernfs_node *kernfs_get_node_by_id(struct kernfs_root *root,
|
||||
const union kernfs_node_id *id)
|
||||
{
|
||||
struct kernfs_node *kn;
|
||||
|
||||
kn = kernfs_find_and_get_node_by_ino(root, id->ino);
|
||||
if (!kn)
|
||||
return NULL;
|
||||
if (kn->id.generation != id->generation) {
|
||||
kernfs_put(kn);
|
||||
return NULL;
|
||||
}
|
||||
return kn;
|
||||
}
|
||||
|
||||
static struct inode *kernfs_fh_get_inode(struct super_block *sb,
|
||||
u64 ino, u32 generation)
|
||||
{
|
||||
struct kernfs_super_info *info = kernfs_info(sb);
|
||||
struct inode *inode;
|
||||
struct kernfs_node *kn;
|
||||
|
||||
if (ino == 0)
|
||||
return ERR_PTR(-ESTALE);
|
||||
|
||||
kn = kernfs_find_and_get_node_by_ino(info->root, ino);
|
||||
if (!kn)
|
||||
return ERR_PTR(-ESTALE);
|
||||
inode = kernfs_get_inode(sb, kn);
|
||||
kernfs_put(kn);
|
||||
if (!inode)
|
||||
return ERR_PTR(-ESTALE);
|
||||
|
||||
if (generation && inode->i_generation != generation) {
|
||||
/* we didn't find the right inode.. */
|
||||
iput(inode);
|
||||
return ERR_PTR(-ESTALE);
|
||||
}
|
||||
return inode;
|
||||
}
|
||||
|
||||
static struct dentry *kernfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
|
||||
int fh_len, int fh_type)
|
||||
{
|
||||
return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
|
||||
kernfs_fh_get_inode);
|
||||
}
|
||||
|
||||
static struct dentry *kernfs_fh_to_parent(struct super_block *sb, struct fid *fid,
|
||||
int fh_len, int fh_type)
|
||||
{
|
||||
return generic_fh_to_parent(sb, fid, fh_len, fh_type,
|
||||
kernfs_fh_get_inode);
|
||||
}
|
||||
|
||||
static struct dentry *kernfs_get_parent_dentry(struct dentry *child)
|
||||
{
|
||||
struct kernfs_node *kn = kernfs_dentry_node(child);
|
||||
|
||||
return d_obtain_alias(kernfs_get_inode(child->d_sb, kn->parent));
|
||||
}
|
||||
|
||||
static const struct export_operations kernfs_export_ops = {
|
||||
.fh_to_dentry = kernfs_fh_to_dentry,
|
||||
.fh_to_parent = kernfs_fh_to_parent,
|
||||
.get_parent = kernfs_get_parent_dentry,
|
||||
};
|
||||
|
||||
/**
|
||||
* kernfs_root_from_sb - determine kernfs_root associated with a super_block
|
||||
* @sb: the super_block in question
|
||||
|
|
@ -159,6 +232,8 @@ static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
|
|||
sb->s_magic = magic;
|
||||
sb->s_op = &kernfs_sops;
|
||||
sb->s_xattr = kernfs_xattr_handlers;
|
||||
if (info->root->flags & KERNFS_ROOT_SUPPORT_EXPORTOP)
|
||||
sb->s_export_op = &kernfs_export_ops;
|
||||
sb->s_time_gran = 1;
|
||||
|
||||
/* get root inode, initialize and unlock it */
|
||||
|
|
@ -176,8 +251,6 @@ static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
|
|||
pr_debug("%s: could not get root dentry!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
kernfs_get(info->root->kn);
|
||||
root->d_fsdata = info->root->kn;
|
||||
sb->s_root = root;
|
||||
sb->s_d_op = &kernfs_dops;
|
||||
return 0;
|
||||
|
|
@ -283,7 +356,6 @@ struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
|
|||
void kernfs_kill_sb(struct super_block *sb)
|
||||
{
|
||||
struct kernfs_super_info *info = kernfs_info(sb);
|
||||
struct kernfs_node *root_kn = sb->s_root->d_fsdata;
|
||||
|
||||
mutex_lock(&kernfs_mutex);
|
||||
list_del(&info->node);
|
||||
|
|
@ -295,7 +367,6 @@ void kernfs_kill_sb(struct super_block *sb)
|
|||
*/
|
||||
kill_anon_super(sb);
|
||||
kfree(info);
|
||||
kernfs_put(root_kn);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -330,7 +401,16 @@ struct super_block *kernfs_pin_sb(struct kernfs_root *root, const void *ns)
|
|||
|
||||
void __init kernfs_init(void)
|
||||
{
|
||||
|
||||
/*
|
||||
* the slab is freed in RCU context, so kernfs_find_and_get_node_by_ino
|
||||
* can access the slab lock free. This could introduce stale nodes,
|
||||
* please see how kernfs_find_and_get_node_by_ino filters out stale
|
||||
* nodes.
|
||||
*/
|
||||
kernfs_node_cache = kmem_cache_create("kernfs_node_cache",
|
||||
sizeof(struct kernfs_node),
|
||||
0, SLAB_PANIC, NULL);
|
||||
0,
|
||||
SLAB_PANIC | SLAB_TYPESAFE_BY_RCU,
|
||||
NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,9 +98,9 @@ static int kernfs_get_target_path(struct kernfs_node *parent,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kernfs_getlink(struct dentry *dentry, char *path)
|
||||
static int kernfs_getlink(struct inode *inode, char *path)
|
||||
{
|
||||
struct kernfs_node *kn = dentry->d_fsdata;
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
struct kernfs_node *parent = kn->parent;
|
||||
struct kernfs_node *target = kn->symlink.target_kn;
|
||||
int error;
|
||||
|
|
@ -124,7 +124,7 @@ static const char *kernfs_iop_get_link(struct dentry *dentry,
|
|||
body = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!body)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
error = kernfs_getlink(dentry, body);
|
||||
error = kernfs_getlink(inode, body);
|
||||
if (unlikely(error < 0)) {
|
||||
kfree(body);
|
||||
return ERR_PTR(error);
|
||||
|
|
|
|||
Loading…
Reference in a new issue