Messages in this thread Patch in this message | | | Subject | [PATCH 04/22] sysfs: make SYSFS_COPY_NAME a flag | Date | Thu, 20 Sep 2007 17:05:39 +0900 | From | Tejun Heo <> |
| |
Currently name is implicitly copied for directory and symlink nodes. Make the behavior flexible by making it a flag. If SYSFS_COPY_NAME bit is specified in @mode when calling sysfs_new_dirent(), the name is copied.
SYSFS_COPY_NAME is defined as S_IFMT so that it can be specified with @mode bits.
Signed-off-by: Tejun Heo <htejun@gmail.com> --- fs/sysfs/dir.c | 21 +++++++++++++++------ fs/sysfs/symlink.c | 3 ++- fs/sysfs/sysfs.h | 2 +- include/linux/sysfs.h | 10 ++++++++++ 4 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 02918d3..584f17c 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -14,6 +14,11 @@ #include <linux/mutex.h> #include "sysfs.h" +/* verify all mode flags are inside S_IFMT */ +#if (SYSFS_MODE_FLAGS & ~S_IFMT) +#error SYSFS mode flags out of S_IFMT +#endif + DEFINE_MUTEX(sysfs_mutex); DEFINE_MUTEX(sysfs_rename_mutex); spinlock_t sysfs_assoc_lock = SPIN_LOCK_UNLOCKED; @@ -275,7 +280,7 @@ void release_sysfs_dirent(struct sysfs_dirent * sd) if (sysfs_type(sd) == SYSFS_KOBJ_LINK) sysfs_put(sd->s_symlink.target_sd); - if (sysfs_type(sd) & SYSFS_COPY_NAME) + if (sd->s_flags & SYSFS_FLAG_NAME_COPIED) kfree(sd->s_name); kfree(sd->s_iattr); sysfs_free_ino(sd->s_ino); @@ -301,11 +306,12 @@ static struct dentry_operations sysfs_dentry_ops = { /** * sysfs_new_dirent - allocate and initialize sysfs_dirent * @name: name for the new sysfs_dirent - * @mode: mask of bits from S_IRWXUGO + * @mode: mask of bits from S_IRWXUGO | SYSFS_COPY_NAME * @type: one of SYSFS_{DIR|FILE|BIN|LINK} * * Allocate and initialize a sysfs_dirent with the specified - * parameters. + * parameters. If SYSFS_COPY_NAME is specified in @mode, @name + * is duplicated. * * LOCKING: * Kernel thread context (may sleep). @@ -316,14 +322,17 @@ static struct dentry_operations sysfs_dentry_ops = { */ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) { + unsigned int flags = type; char *dup_name = NULL; struct sysfs_dirent *sd; /* need to copy name? */ - if (type & SYSFS_COPY_NAME) { + if (mode & SYSFS_COPY_NAME) { name = dup_name = kstrdup(name, GFP_KERNEL); if (!name) return NULL; + + flags |= SYSFS_FLAG_NAME_COPIED; } /* normalize mode */ @@ -355,7 +364,7 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) sd->s_name = name; sd->s_mode = mode; - sd->s_flags = type; + sd->s_flags = flags; return sd; @@ -647,7 +656,7 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, int rc; /* allocate */ - sd = sysfs_new_dirent(name, mode, SYSFS_DIR); + sd = sysfs_new_dirent(name, mode | SYSFS_COPY_NAME, SYSFS_DIR); if (!sd) return -ENOMEM; sd->s_dir.kobj = kobj; diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index bf96bcd..982085c 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -82,7 +82,8 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char goto out_put; error = -ENOMEM; - sd = sysfs_new_dirent(name, S_IRWXUGO, SYSFS_KOBJ_LINK); + sd = sysfs_new_dirent(name, S_IRWXUGO | SYSFS_COPY_NAME, + SYSFS_KOBJ_LINK); if (!sd) goto out_put; diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 9180e2c..db1a433 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -55,10 +55,10 @@ struct sysfs_dirent { #define SYSFS_KOBJ_ATTR 0x0002 #define SYSFS_KOBJ_BIN_ATTR 0x0004 #define SYSFS_KOBJ_LINK 0x0008 -#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) #define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK #define SYSFS_FLAG_REMOVED 0x0200 +#define SYSFS_FLAG_NAME_COPIED 0x0400 static inline unsigned int sysfs_type(struct sysfs_dirent *sd) { diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 38b73f9..5646e56 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -20,6 +20,16 @@ struct vm_area_struct; +/* + * @mode bits for sysfs_add_*() functions. Only S_IALLUGO bits are + * valid as real mode bits. Bits in S_IFMT are used to set sysfs + * specific flags. + */ +#define SYSFS_COPY_NAME 010000 /* copy passed @name */ + +/* collection of all flags for verification */ +#define SYSFS_MODE_FLAGS SYSFS_COPY_NAME + #ifdef CONFIG_SYSFS int __must_check sysfs_init(void); -- 1.5.0.3
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |