aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs')
-rw-r--r--fs/sysfs/bin.c2
-rw-r--r--fs/sysfs/dir.c39
-rw-r--r--fs/sysfs/file.c11
-rw-r--r--fs/sysfs/inode.c9
-rw-r--r--fs/sysfs/symlink.c6
-rw-r--r--fs/sysfs/sysfs.h7
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
166struct file_operations bin_fops = { 166const 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 */
60int 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
53int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry, 79int 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
307int sysfs_rename_dir(struct kobject * kobj, const char *new_name) 338int 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
475struct file_operations sysfs_dir_operations = { 506const 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
483EXPORT_SYMBOL_GPL(sysfs_create_dir);
484EXPORT_SYMBOL_GPL(sysfs_remove_dir);
485EXPORT_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
352struct file_operations sysfs_file_operations = { 351const 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)
227void sysfs_hash_and_remove(struct dentry * dir, const char * name) 226void 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);
70exit2: 71exit2:
71 kfree(sl); 72 kfree(sl);
@@ -82,12 +83,13 @@ exit1:
82int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name) 83int 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;
5extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *); 5extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
6extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); 6extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
7 7
8extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);
8extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, 9extern 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
21extern struct rw_semaphore sysfs_rename_sem; 22extern struct rw_semaphore sysfs_rename_sem;
22extern struct super_block * sysfs_sb; 23extern struct super_block * sysfs_sb;
23extern struct file_operations sysfs_dir_operations; 24extern const struct file_operations sysfs_dir_operations;
24extern struct file_operations sysfs_file_operations; 25extern const struct file_operations sysfs_file_operations;
25extern struct file_operations bin_fops; 26extern const struct file_operations bin_fops;
26extern struct inode_operations sysfs_dir_inode_operations; 27extern struct inode_operations sysfs_dir_inode_operations;
27extern struct inode_operations sysfs_symlink_inode_operations; 28extern struct inode_operations sysfs_symlink_inode_operations;
28 29