X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=fs%2Fsysfs%2Fdir.c;h=4948d9bc405dfbdb23f30dcd5ad47d103f4e5514;hb=4faa8496650f9417189dacce8f933e8ec61dc032;hp=fc615eed67dcfa1a9f04ddb554a336c75964189a;hpb=181b2e4be1603ce3ccace8322047a548f29f4b20;p=~andy%2Flinux diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index fc615eed67d..4948d9bc405 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -1,5 +1,13 @@ /* - * dir.c - Operations for sysfs directories. + * fs/sysfs/dir.c - sysfs core and dir operation implementation + * + * Copyright (c) 2001-3 Patrick Mochel + * Copyright (c) 2007 SUSE Linux Products GmbH + * Copyright (c) 2007 Tejun Heo + * + * This file is released under the GPLv2. + * + * Please see Documentation/filesystems/sysfs.txt for more information. */ #undef DEBUG @@ -16,9 +24,9 @@ DEFINE_MUTEX(sysfs_mutex); DEFINE_MUTEX(sysfs_rename_mutex); -spinlock_t sysfs_assoc_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(sysfs_assoc_lock); -static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(sysfs_ino_lock); static DEFINE_IDA(sysfs_ino_ida); /** @@ -26,7 +34,7 @@ static DEFINE_IDA(sysfs_ino_ida); * @sd: sysfs_dirent of interest * * Link @sd into its sibling list which starts from - * sd->s_parent->s_children. + * sd->s_parent->s_dir.children. * * Locking: * mutex_lock(sysfs_mutex) @@ -40,9 +48,9 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd) /* Store directory entries in order by ino. This allows * readdir to properly restart without having to add a - * cursor into the s_children list. + * cursor into the s_dir.children list. */ - for (pos = &parent_sd->s_children; *pos; pos = &(*pos)->s_sibling) { + for (pos = &parent_sd->s_dir.children; *pos; pos = &(*pos)->s_sibling) { if (sd->s_ino < (*pos)->s_ino) break; } @@ -55,7 +63,7 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd) * @sd: sysfs_dirent of interest * * Unlink @sd from its sibling list which starts from - * sd->s_parent->s_children. + * sd->s_parent->s_dir.children. * * Locking: * mutex_lock(sysfs_mutex) @@ -64,7 +72,8 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) { struct sysfs_dirent **pos; - for (pos = &sd->s_parent->s_children; *pos; pos = &(*pos)->s_sibling) { + for (pos = &sd->s_parent->s_dir.children; *pos; + pos = &(*pos)->s_sibling) { if (*pos == sd) { *pos = sd->s_sibling; sd->s_sibling = NULL; @@ -103,8 +112,7 @@ struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd) /* look it up */ parent = dentry; mutex_lock(&parent->d_inode->i_mutex); - dentry = lookup_one_len_kern(cur->s_name, parent, - strlen(cur->s_name)); + dentry = lookup_one_noperm(cur->s_name, parent); mutex_unlock(&parent->d_inode->i_mutex); dput(parent); @@ -124,7 +132,7 @@ struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd) * RETURNS: * Pointer to @sd on success, NULL on failure. */ -struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) +static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) { if (unlikely(!sd)) return NULL; @@ -153,7 +161,7 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) * Put an active reference to @sd. This function is noop if @sd * is NULL. */ -void sysfs_put_active(struct sysfs_dirent *sd) +static void sysfs_put_active(struct sysfs_dirent *sd) { struct completion *cmpl; int v; @@ -273,7 +281,7 @@ void release_sysfs_dirent(struct sysfs_dirent * sd) parent_sd = sd->s_parent; if (sysfs_type(sd) == SYSFS_KOBJ_LINK) - sysfs_put(sd->s_elem.symlink.target_sd); + sysfs_put(sd->s_symlink.target_sd); if (sysfs_type(sd) & SYSFS_COPY_NAME) kfree(sd->s_name); kfree(sd->s_iattr); @@ -317,7 +325,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) atomic_set(&sd->s_count, 1); atomic_set(&sd->s_active, 0); - atomic_set(&sd->s_event, 1); sd->s_name = name; sd->s_mode = mode; @@ -332,21 +339,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) return NULL; } -/** - * sysfs_attach_dentry - associate sysfs_dirent with dentry - * @sd: target sysfs_dirent - * @dentry: dentry to associate - * - * LOCKING: - * mutex_lock(sysfs_mutex) - */ -static void sysfs_attach_dentry(struct sysfs_dirent *sd, struct dentry *dentry) -{ - dentry->d_op = &sysfs_dentry_ops; - dentry->d_fsdata = sysfs_get(sd); - d_rehash(dentry); -} - static int sysfs_ilookup_test(struct inode *inode, void *arg) { struct sysfs_dirent *sd = arg; @@ -448,7 +440,7 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) /** * sysfs_remove_one - remove sysfs_dirent from parent * @acxt: addrm context to use - * @sd: sysfs_dirent to be added + * @sd: sysfs_dirent to be removed * * Mark @sd removed and drop nlink of parent inode if @sd is a * directory. @sd is unlinked from the children list. @@ -585,7 +577,7 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, { struct sysfs_dirent *sd; - for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) + for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) if (!strcmp(sd->s_name, name)) return sd; return NULL; @@ -630,7 +622,7 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, sd = sysfs_new_dirent(name, mode, SYSFS_DIR); if (!sd) return -ENOMEM; - sd->s_elem.dir.kobj = kobj; + sd->s_dir.kobj = kobj; /* link in */ sysfs_addrm_start(&acxt, parent_sd); @@ -686,8 +678,10 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, sd = sysfs_find_dirent(parent_sd, dentry->d_name.name); /* no such entry */ - if (!sd) + if (!sd) { + ret = ERR_PTR(-ENOENT); goto out_unlock; + } /* attach dentry and inode */ inode = sysfs_get_inode(sd); @@ -696,8 +690,11 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, goto out_unlock; } + /* instantiate and hash dentry */ + dentry->d_op = &sysfs_dentry_ops; + dentry->d_fsdata = sysfs_get(sd); d_instantiate(dentry, inode); - sysfs_attach_dentry(sd, dentry); + d_rehash(dentry); out_unlock: mutex_unlock(&sysfs_mutex); @@ -734,7 +731,7 @@ static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); sysfs_addrm_start(&acxt, dir_sd); - pos = &dir_sd->s_children; + pos = &dir_sd->s_dir.children; while (*pos) { struct sysfs_dirent *sd = *pos; @@ -786,6 +783,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) old_dentry = sysfs_get_dentry(sd); if (IS_ERR(old_dentry)) { error = PTR_ERR(old_dentry); + old_dentry = NULL; goto out; } @@ -853,6 +851,7 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) old_dentry = sysfs_get_dentry(sd); if (IS_ERR(old_dentry)) { error = PTR_ERR(old_dentry); + old_dentry = NULL; goto out; } old_parent = old_dentry->d_parent; @@ -860,6 +859,7 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) new_parent = sysfs_get_dentry(new_parent_sd); if (IS_ERR(new_parent)) { error = PTR_ERR(new_parent); + new_parent = NULL; goto out; } @@ -883,7 +883,6 @@ again: error = 0; d_add(new_dentry, NULL); d_move(old_dentry, new_dentry); - dput(new_dentry); /* Remove from old parent's list and insert into new parent's list. */ sysfs_unlink_sibling(sd); @@ -934,7 +933,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) mutex_lock(&sysfs_mutex); /* Skip the dentries we have already reported */ - pos = parent_sd->s_children; + pos = parent_sd->s_dir.children; while (pos && (filp->f_pos > pos->s_ino)) pos = pos->s_sibling;