aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2009-11-20 19:08:50 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 14:24:53 -0500
commit35df63c46c8605d00140ec4833d2104e2e9f1acc (patch)
tree1f02d75ab4589d3c8878e38e9d45360a0c0667d4
parent4be3df28beec5605c77a18aa2a4f987b5648f9ce (diff)
sysfs: Fix locking and factor out sysfs_sd_setattr
Cleanly separate the work that is specific to setting the attributes of a sysfs_dirent from what is needed to update the attributes of a vfs inode. Additionally grab the sysfs_mutex to keep any nasties from surprising us when updating the sysfs_dirent. Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--fs/sysfs/inode.c51
-rw-r--r--fs/sysfs/sysfs.h1
2 files changed, 32 insertions, 20 deletions
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 86fb230de432..76e977c300f7 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -65,30 +65,14 @@ static struct sysfs_inode_attrs *sysfs_init_inode_attrs(struct sysfs_dirent *sd)
65 return attrs; 65 return attrs;
66} 66}
67 67
68int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) 68int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr * iattr)
69{ 69{
70 struct inode * inode = dentry->d_inode;
71 struct sysfs_dirent * sd = dentry->d_fsdata;
72 struct sysfs_inode_attrs *sd_attrs; 70 struct sysfs_inode_attrs *sd_attrs;
73 struct iattr *iattrs; 71 struct iattr *iattrs;
74 unsigned int ia_valid = iattr->ia_valid; 72 unsigned int ia_valid = iattr->ia_valid;
75 int error;
76
77 if (!sd)
78 return -EINVAL;
79 73
80 sd_attrs = sd->s_iattr; 74 sd_attrs = sd->s_iattr;
81 75
82 error = inode_change_ok(inode, iattr);
83 if (error)
84 return error;
85
86 iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */
87
88 error = inode_setattr(inode, iattr);
89 if (error)
90 return error;
91
92 if (!sd_attrs) { 76 if (!sd_attrs) {
93 /* setting attributes for the first time, allocate now */ 77 /* setting attributes for the first time, allocate now */
94 sd_attrs = sysfs_init_inode_attrs(sd); 78 sd_attrs = sysfs_init_inode_attrs(sd);
@@ -111,12 +95,39 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
111 iattrs->ia_ctime = iattr->ia_ctime; 95 iattrs->ia_ctime = iattr->ia_ctime;
112 if (ia_valid & ATTR_MODE) { 96 if (ia_valid & ATTR_MODE) {
113 umode_t mode = iattr->ia_mode; 97 umode_t mode = iattr->ia_mode;
114
115 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
116 mode &= ~S_ISGID;
117 iattrs->ia_mode = sd->s_mode = mode; 98 iattrs->ia_mode = sd->s_mode = mode;
118 } 99 }
119 } 100 }
101 return 0;
102}
103
104int sysfs_setattr(struct dentry *dentry, struct iattr *iattr)
105{
106 struct inode *inode = dentry->d_inode;
107 struct sysfs_dirent *sd = dentry->d_fsdata;
108 int error;
109
110 if (!sd)
111 return -EINVAL;
112
113 error = inode_change_ok(inode, iattr);
114 if (error)
115 return error;
116
117 iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */
118 if (iattr->ia_valid & ATTR_MODE) {
119 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
120 iattr->ia_mode &= ~S_ISGID;
121 }
122
123 error = inode_setattr(inode, iattr);
124 if (error)
125 return error;
126
127 mutex_lock(&sysfs_mutex);
128 error = sysfs_sd_setattr(sd, iattr);
129 mutex_unlock(&sysfs_mutex);
130
120 return error; 131 return error;
121} 132}
122 133
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index af4c4e7482ac..a96d9678ae73 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -155,6 +155,7 @@ static inline void __sysfs_put(struct sysfs_dirent *sd)
155 */ 155 */
156struct inode *sysfs_get_inode(struct sysfs_dirent *sd); 156struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
157void sysfs_delete_inode(struct inode *inode); 157void sysfs_delete_inode(struct inode *inode);
158int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr);
158int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); 159int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
159int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, 160int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
160 size_t size, int flags); 161 size_t size, int flags);