diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2009-11-20 19:08:53 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-11 14:24:54 -0500 |
commit | e61ab4ae48fbf477f5b9fcbec9e1b8dc789920d0 (patch) | |
tree | 70199a29a97a4f5ba8aea4340bc828da4f550e5d /fs/sysfs | |
parent | c099aacd48ee73bd2de7da029e536ed005d72a43 (diff) |
sysfs: Implement sysfs_getattr & sysfs_permission
With the implementation of sysfs_getattr and sysfs_permission
sysfs becomes able to lazily propogate inode attribute changes
from the sysfs_dirents to the vfs inodes. This paves the way
for deleting significant chunks of now unnecessary code.
While doing this we did not reference sysfs_setattr from
sysfs_symlink_inode_operations so I added along with
sysfs_getattr and sysfs_permission.
Acked-by: Tejun Heo <tj@kernel.org>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/dir.c | 2 | ||||
-rw-r--r-- | fs/sysfs/inode.c | 64 | ||||
-rw-r--r-- | fs/sysfs/symlink.c | 3 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 2 |
4 files changed, 54 insertions, 17 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 36ee6d817956..e319379d36db 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -800,7 +800,9 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | |||
800 | 800 | ||
801 | const struct inode_operations sysfs_dir_inode_operations = { | 801 | const struct inode_operations sysfs_dir_inode_operations = { |
802 | .lookup = sysfs_lookup, | 802 | .lookup = sysfs_lookup, |
803 | .permission = sysfs_permission, | ||
803 | .setattr = sysfs_setattr, | 804 | .setattr = sysfs_setattr, |
805 | .getattr = sysfs_getattr, | ||
804 | .setxattr = sysfs_setxattr, | 806 | .setxattr = sysfs_setxattr, |
805 | }; | 807 | }; |
806 | 808 | ||
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 76e977c300f7..1ffd5559926f 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -37,7 +37,9 @@ static struct backing_dev_info sysfs_backing_dev_info = { | |||
37 | }; | 37 | }; |
38 | 38 | ||
39 | static const struct inode_operations sysfs_inode_operations ={ | 39 | static const struct inode_operations sysfs_inode_operations ={ |
40 | .permission = sysfs_permission, | ||
40 | .setattr = sysfs_setattr, | 41 | .setattr = sysfs_setattr, |
42 | .getattr = sysfs_getattr, | ||
41 | .setxattr = sysfs_setxattr, | 43 | .setxattr = sysfs_setxattr, |
42 | }; | 44 | }; |
43 | 45 | ||
@@ -196,7 +198,6 @@ static inline void set_default_inode_attr(struct inode * inode, mode_t mode) | |||
196 | 198 | ||
197 | static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) | 199 | static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) |
198 | { | 200 | { |
199 | inode->i_mode = iattr->ia_mode; | ||
200 | inode->i_uid = iattr->ia_uid; | 201 | inode->i_uid = iattr->ia_uid; |
201 | inode->i_gid = iattr->ia_gid; | 202 | inode->i_gid = iattr->ia_gid; |
202 | inode->i_atime = iattr->ia_atime; | 203 | inode->i_atime = iattr->ia_atime; |
@@ -227,38 +228,56 @@ static int sysfs_count_nlink(struct sysfs_dirent *sd) | |||
227 | return nr + 2; | 228 | return nr + 2; |
228 | } | 229 | } |
229 | 230 | ||
231 | static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode) | ||
232 | { | ||
233 | struct sysfs_inode_attrs *iattrs = sd->s_iattr; | ||
234 | |||
235 | inode->i_mode = sd->s_mode; | ||
236 | if (iattrs) { | ||
237 | /* sysfs_dirent has non-default attributes | ||
238 | * get them from persistent copy in sysfs_dirent | ||
239 | */ | ||
240 | set_inode_attr(inode, &iattrs->ia_iattr); | ||
241 | security_inode_notifysecctx(inode, | ||
242 | iattrs->ia_secdata, | ||
243 | iattrs->ia_secdata_len); | ||
244 | } | ||
245 | |||
246 | if (sysfs_type(sd) == SYSFS_DIR) | ||
247 | inode->i_nlink = sysfs_count_nlink(sd); | ||
248 | } | ||
249 | |||
250 | int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | ||
251 | { | ||
252 | struct sysfs_dirent *sd = dentry->d_fsdata; | ||
253 | struct inode *inode = dentry->d_inode; | ||
254 | |||
255 | mutex_lock(&sysfs_mutex); | ||
256 | sysfs_refresh_inode(sd, inode); | ||
257 | mutex_unlock(&sysfs_mutex); | ||
258 | |||
259 | generic_fillattr(inode, stat); | ||
260 | return 0; | ||
261 | } | ||
262 | |||
230 | static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) | 263 | static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) |
231 | { | 264 | { |
232 | struct bin_attribute *bin_attr; | 265 | struct bin_attribute *bin_attr; |
233 | struct sysfs_inode_attrs *iattrs; | ||
234 | 266 | ||
235 | inode->i_private = sysfs_get(sd); | 267 | inode->i_private = sysfs_get(sd); |
236 | inode->i_mapping->a_ops = &sysfs_aops; | 268 | inode->i_mapping->a_ops = &sysfs_aops; |
237 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; | 269 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; |
238 | inode->i_op = &sysfs_inode_operations; | 270 | inode->i_op = &sysfs_inode_operations; |
239 | inode->i_ino = sd->s_ino; | ||
240 | lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key); | 271 | lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key); |
241 | 272 | ||
242 | iattrs = sd->s_iattr; | 273 | set_default_inode_attr(inode, sd->s_mode); |
243 | if (iattrs) { | 274 | sysfs_refresh_inode(sd, inode); |
244 | /* sysfs_dirent has non-default attributes | ||
245 | * get them for the new inode from persistent copy | ||
246 | * in sysfs_dirent | ||
247 | */ | ||
248 | set_inode_attr(inode, &iattrs->ia_iattr); | ||
249 | if (iattrs->ia_secdata) | ||
250 | security_inode_notifysecctx(inode, | ||
251 | iattrs->ia_secdata, | ||
252 | iattrs->ia_secdata_len); | ||
253 | } else | ||
254 | set_default_inode_attr(inode, sd->s_mode); | ||
255 | 275 | ||
256 | /* initialize inode according to type */ | 276 | /* initialize inode according to type */ |
257 | switch (sysfs_type(sd)) { | 277 | switch (sysfs_type(sd)) { |
258 | case SYSFS_DIR: | 278 | case SYSFS_DIR: |
259 | inode->i_op = &sysfs_dir_inode_operations; | 279 | inode->i_op = &sysfs_dir_inode_operations; |
260 | inode->i_fop = &sysfs_dir_operations; | 280 | inode->i_fop = &sysfs_dir_operations; |
261 | inode->i_nlink = sysfs_count_nlink(sd); | ||
262 | break; | 281 | break; |
263 | case SYSFS_KOBJ_ATTR: | 282 | case SYSFS_KOBJ_ATTR: |
264 | inode->i_size = PAGE_SIZE; | 283 | inode->i_size = PAGE_SIZE; |
@@ -341,3 +360,14 @@ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) | |||
341 | else | 360 | else |
342 | return -ENOENT; | 361 | return -ENOENT; |
343 | } | 362 | } |
363 | |||
364 | int sysfs_permission(struct inode *inode, int mask) | ||
365 | { | ||
366 | struct sysfs_dirent *sd = inode->i_private; | ||
367 | |||
368 | mutex_lock(&sysfs_mutex); | ||
369 | sysfs_refresh_inode(sd, inode); | ||
370 | mutex_unlock(&sysfs_mutex); | ||
371 | |||
372 | return generic_permission(inode, mask, NULL); | ||
373 | } | ||
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 11374182ca67..c5eff49fa41b 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
@@ -214,6 +214,9 @@ const struct inode_operations sysfs_symlink_inode_operations = { | |||
214 | .readlink = generic_readlink, | 214 | .readlink = generic_readlink, |
215 | .follow_link = sysfs_follow_link, | 215 | .follow_link = sysfs_follow_link, |
216 | .put_link = sysfs_put_link, | 216 | .put_link = sysfs_put_link, |
217 | .setattr = sysfs_setattr, | ||
218 | .getattr = sysfs_getattr, | ||
219 | .permission = sysfs_permission, | ||
217 | }; | 220 | }; |
218 | 221 | ||
219 | 222 | ||
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index a96d9678ae73..12ccc07459d8 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -156,7 +156,9 @@ static inline void __sysfs_put(struct sysfs_dirent *sd) | |||
156 | struct inode *sysfs_get_inode(struct sysfs_dirent *sd); | 156 | struct inode *sysfs_get_inode(struct sysfs_dirent *sd); |
157 | void sysfs_delete_inode(struct inode *inode); | 157 | void sysfs_delete_inode(struct inode *inode); |
158 | int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr); | 158 | int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr); |
159 | int sysfs_permission(struct inode *inode, int mask); | ||
159 | int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); | 160 | int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); |
161 | int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); | ||
160 | int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 162 | int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
161 | size_t size, int flags); | 163 | size_t size, int flags); |
162 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); | 164 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); |