diff options
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/bin.c | 2 | ||||
-rw-r--r-- | fs/sysfs/dir.c | 39 | ||||
-rw-r--r-- | fs/sysfs/file.c | 11 | ||||
-rw-r--r-- | fs/sysfs/inode.c | 9 | ||||
-rw-r--r-- | fs/sysfs/symlink.c | 6 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 7 |
6 files changed, 54 insertions, 20 deletions
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 78899eeab974..c16a93c353c0 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c | |||
@@ -163,7 +163,7 @@ static int release(struct inode * inode, struct file * file) | |||
163 | return 0; | 163 | return 0; |
164 | } | 164 | } |
165 | 165 | ||
166 | struct file_operations bin_fops = { | 166 | const struct file_operations bin_fops = { |
167 | .read = read, | 167 | .read = read, |
168 | .write = write, | 168 | .write = write, |
169 | .mmap = mmap, | 169 | .mmap = mmap, |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 49bd219275db..f26880a4785e 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -50,6 +50,32 @@ static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd, | |||
50 | return sd; | 50 | return sd; |
51 | } | 51 | } |
52 | 52 | ||
53 | /** | ||
54 | * | ||
55 | * Return -EEXIST if there is already a sysfs element with the same name for | ||
56 | * the same parent. | ||
57 | * | ||
58 | * called with parent inode's i_mutex held | ||
59 | */ | ||
60 | int sysfs_dirent_exist(struct sysfs_dirent *parent_sd, | ||
61 | const unsigned char *new) | ||
62 | { | ||
63 | struct sysfs_dirent * sd; | ||
64 | |||
65 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { | ||
66 | if (sd->s_element) { | ||
67 | const unsigned char *existing = sysfs_get_name(sd); | ||
68 | if (strcmp(existing, new)) | ||
69 | continue; | ||
70 | else | ||
71 | return -EEXIST; | ||
72 | } | ||
73 | } | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | |||
53 | int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry, | 79 | int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry, |
54 | void * element, umode_t mode, int type) | 80 | void * element, umode_t mode, int type) |
55 | { | 81 | { |
@@ -102,7 +128,11 @@ static int create_dir(struct kobject * k, struct dentry * p, | |||
102 | mutex_lock(&p->d_inode->i_mutex); | 128 | mutex_lock(&p->d_inode->i_mutex); |
103 | *d = lookup_one_len(n, p, strlen(n)); | 129 | *d = lookup_one_len(n, p, strlen(n)); |
104 | if (!IS_ERR(*d)) { | 130 | if (!IS_ERR(*d)) { |
105 | error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, SYSFS_DIR); | 131 | if (sysfs_dirent_exist(p->d_fsdata, n)) |
132 | error = -EEXIST; | ||
133 | else | ||
134 | error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, | ||
135 | SYSFS_DIR); | ||
106 | if (!error) { | 136 | if (!error) { |
107 | error = sysfs_create(*d, mode, init_dir); | 137 | error = sysfs_create(*d, mode, init_dir); |
108 | if (!error) { | 138 | if (!error) { |
@@ -302,6 +332,7 @@ void sysfs_remove_dir(struct kobject * kobj) | |||
302 | * Drop reference from dget() on entrance. | 332 | * Drop reference from dget() on entrance. |
303 | */ | 333 | */ |
304 | dput(dentry); | 334 | dput(dentry); |
335 | kobj->dentry = NULL; | ||
305 | } | 336 | } |
306 | 337 | ||
307 | int sysfs_rename_dir(struct kobject * kobj, const char *new_name) | 338 | int sysfs_rename_dir(struct kobject * kobj, const char *new_name) |
@@ -472,14 +503,10 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) | |||
472 | return offset; | 503 | return offset; |
473 | } | 504 | } |
474 | 505 | ||
475 | struct file_operations sysfs_dir_operations = { | 506 | const struct file_operations sysfs_dir_operations = { |
476 | .open = sysfs_dir_open, | 507 | .open = sysfs_dir_open, |
477 | .release = sysfs_dir_close, | 508 | .release = sysfs_dir_close, |
478 | .llseek = sysfs_dir_lseek, | 509 | .llseek = sysfs_dir_lseek, |
479 | .read = generic_read_dir, | 510 | .read = generic_read_dir, |
480 | .readdir = sysfs_readdir, | 511 | .readdir = sysfs_readdir, |
481 | }; | 512 | }; |
482 | |||
483 | EXPORT_SYMBOL_GPL(sysfs_create_dir); | ||
484 | EXPORT_SYMBOL_GPL(sysfs_remove_dir); | ||
485 | EXPORT_SYMBOL_GPL(sysfs_rename_dir); | ||
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index d0e3d8495165..830f76fa098c 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -301,9 +301,8 @@ static int check_perm(struct inode * inode, struct file * file) | |||
301 | /* No error? Great, allocate a buffer for the file, and store it | 301 | /* No error? Great, allocate a buffer for the file, and store it |
302 | * it in file->private_data for easy access. | 302 | * it in file->private_data for easy access. |
303 | */ | 303 | */ |
304 | buffer = kmalloc(sizeof(struct sysfs_buffer),GFP_KERNEL); | 304 | buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL); |
305 | if (buffer) { | 305 | if (buffer) { |
306 | memset(buffer,0,sizeof(struct sysfs_buffer)); | ||
307 | init_MUTEX(&buffer->sem); | 306 | init_MUTEX(&buffer->sem); |
308 | buffer->needs_read_fill = 1; | 307 | buffer->needs_read_fill = 1; |
309 | buffer->ops = ops; | 308 | buffer->ops = ops; |
@@ -349,7 +348,7 @@ static int sysfs_release(struct inode * inode, struct file * filp) | |||
349 | return 0; | 348 | return 0; |
350 | } | 349 | } |
351 | 350 | ||
352 | struct file_operations sysfs_file_operations = { | 351 | const struct file_operations sysfs_file_operations = { |
353 | .read = sysfs_read_file, | 352 | .read = sysfs_read_file, |
354 | .write = sysfs_write_file, | 353 | .write = sysfs_write_file, |
355 | .llseek = generic_file_llseek, | 354 | .llseek = generic_file_llseek, |
@@ -362,10 +361,12 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type) | |||
362 | { | 361 | { |
363 | struct sysfs_dirent * parent_sd = dir->d_fsdata; | 362 | struct sysfs_dirent * parent_sd = dir->d_fsdata; |
364 | umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; | 363 | umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; |
365 | int error = 0; | 364 | int error = -EEXIST; |
366 | 365 | ||
367 | mutex_lock(&dir->d_inode->i_mutex); | 366 | mutex_lock(&dir->d_inode->i_mutex); |
368 | error = sysfs_make_dirent(parent_sd, NULL, (void *) attr, mode, type); | 367 | if (!sysfs_dirent_exist(parent_sd, attr->name)) |
368 | error = sysfs_make_dirent(parent_sd, NULL, (void *)attr, | ||
369 | mode, type); | ||
369 | mutex_unlock(&dir->d_inode->i_mutex); | 370 | mutex_unlock(&dir->d_inode->i_mutex); |
370 | 371 | ||
371 | return error; | 372 | return error; |
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 689f7bcfaf30..4c29ac41ac3e 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -54,11 +54,10 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) | |||
54 | 54 | ||
55 | if (!sd_iattr) { | 55 | if (!sd_iattr) { |
56 | /* setting attributes for the first time, allocate now */ | 56 | /* setting attributes for the first time, allocate now */ |
57 | sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL); | 57 | sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL); |
58 | if (!sd_iattr) | 58 | if (!sd_iattr) |
59 | return -ENOMEM; | 59 | return -ENOMEM; |
60 | /* assign default attributes */ | 60 | /* assign default attributes */ |
61 | memset(sd_iattr, 0, sizeof(struct iattr)); | ||
62 | sd_iattr->ia_mode = sd->s_mode; | 61 | sd_iattr->ia_mode = sd->s_mode; |
63 | sd_iattr->ia_uid = 0; | 62 | sd_iattr->ia_uid = 0; |
64 | sd_iattr->ia_gid = 0; | 63 | sd_iattr->ia_gid = 0; |
@@ -227,12 +226,16 @@ void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) | |||
227 | void sysfs_hash_and_remove(struct dentry * dir, const char * name) | 226 | void sysfs_hash_and_remove(struct dentry * dir, const char * name) |
228 | { | 227 | { |
229 | struct sysfs_dirent * sd; | 228 | struct sysfs_dirent * sd; |
230 | struct sysfs_dirent * parent_sd = dir->d_fsdata; | 229 | struct sysfs_dirent * parent_sd; |
230 | |||
231 | if (!dir) | ||
232 | return; | ||
231 | 233 | ||
232 | if (dir->d_inode == NULL) | 234 | if (dir->d_inode == NULL) |
233 | /* no inode means this hasn't been made visible yet */ | 235 | /* no inode means this hasn't been made visible yet */ |
234 | return; | 236 | return; |
235 | 237 | ||
238 | parent_sd = dir->d_fsdata; | ||
236 | mutex_lock(&dir->d_inode->i_mutex); | 239 | mutex_lock(&dir->d_inode->i_mutex); |
237 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { | 240 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { |
238 | if (!sd->s_element) | 241 | if (!sd->s_element) |
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index e38d6338a20d..d2eac3ceed5f 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
@@ -66,6 +66,7 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj | |||
66 | if (!error) | 66 | if (!error) |
67 | return 0; | 67 | return 0; |
68 | 68 | ||
69 | kobject_put(target); | ||
69 | kfree(sl->link_name); | 70 | kfree(sl->link_name); |
70 | exit2: | 71 | exit2: |
71 | kfree(sl); | 72 | kfree(sl); |
@@ -82,12 +83,13 @@ exit1: | |||
82 | int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name) | 83 | int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name) |
83 | { | 84 | { |
84 | struct dentry * dentry = kobj->dentry; | 85 | struct dentry * dentry = kobj->dentry; |
85 | int error = 0; | 86 | int error = -EEXIST; |
86 | 87 | ||
87 | BUG_ON(!kobj || !kobj->dentry || !name); | 88 | BUG_ON(!kobj || !kobj->dentry || !name); |
88 | 89 | ||
89 | mutex_lock(&dentry->d_inode->i_mutex); | 90 | mutex_lock(&dentry->d_inode->i_mutex); |
90 | error = sysfs_add_link(dentry, name, target); | 91 | if (!sysfs_dirent_exist(dentry->d_fsdata, name)) |
92 | error = sysfs_add_link(dentry, name, target); | ||
91 | mutex_unlock(&dentry->d_inode->i_mutex); | 93 | mutex_unlock(&dentry->d_inode->i_mutex); |
92 | return error; | 94 | return error; |
93 | } | 95 | } |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 3f8953e0e5d0..32958a7c50e9 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -5,6 +5,7 @@ extern kmem_cache_t *sysfs_dir_cachep; | |||
5 | extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *); | 5 | extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *); |
6 | extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); | 6 | extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); |
7 | 7 | ||
8 | extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); | ||
8 | extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, | 9 | extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, |
9 | umode_t, int); | 10 | umode_t, int); |
10 | 11 | ||
@@ -20,9 +21,9 @@ extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); | |||
20 | 21 | ||
21 | extern struct rw_semaphore sysfs_rename_sem; | 22 | extern struct rw_semaphore sysfs_rename_sem; |
22 | extern struct super_block * sysfs_sb; | 23 | extern struct super_block * sysfs_sb; |
23 | extern struct file_operations sysfs_dir_operations; | 24 | extern const struct file_operations sysfs_dir_operations; |
24 | extern struct file_operations sysfs_file_operations; | 25 | extern const struct file_operations sysfs_file_operations; |
25 | extern struct file_operations bin_fops; | 26 | extern const struct file_operations bin_fops; |
26 | extern struct inode_operations sysfs_dir_inode_operations; | 27 | extern struct inode_operations sysfs_dir_inode_operations; |
27 | extern struct inode_operations sysfs_symlink_inode_operations; | 28 | extern struct inode_operations sysfs_symlink_inode_operations; |
28 | 29 | ||