aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs/inode.c')
-rw-r--r--fs/sysfs/inode.c102
1 files changed, 96 insertions, 6 deletions
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index aff7b2dfa8ee..565cac1d4200 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -26,18 +26,107 @@ static struct backing_dev_info sysfs_backing_dev_info = {
26 .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, 26 .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
27}; 27};
28 28
29struct inode * sysfs_new_inode(mode_t mode) 29static struct inode_operations sysfs_inode_operations ={
30 .setattr = sysfs_setattr,
31};
32
33int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
34{
35 struct inode * inode = dentry->d_inode;
36 struct sysfs_dirent * sd = dentry->d_fsdata;
37 struct iattr * sd_iattr;
38 unsigned int ia_valid = iattr->ia_valid;
39 int error;
40
41 if (!sd)
42 return -EINVAL;
43
44 sd_iattr = sd->s_iattr;
45
46 error = inode_change_ok(inode, iattr);
47 if (error)
48 return error;
49
50 error = inode_setattr(inode, iattr);
51 if (error)
52 return error;
53
54 if (!sd_iattr) {
55 /* setting attributes for the first time, allocate now */
56 sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL);
57 if (!sd_iattr)
58 return -ENOMEM;
59 /* assign default attributes */
60 memset(sd_iattr, 0, sizeof(struct iattr));
61 sd_iattr->ia_mode = sd->s_mode;
62 sd_iattr->ia_uid = 0;
63 sd_iattr->ia_gid = 0;
64 sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME;
65 sd->s_iattr = sd_iattr;
66 }
67
68 /* attributes were changed atleast once in past */
69
70 if (ia_valid & ATTR_UID)
71 sd_iattr->ia_uid = iattr->ia_uid;
72 if (ia_valid & ATTR_GID)
73 sd_iattr->ia_gid = iattr->ia_gid;
74 if (ia_valid & ATTR_ATIME)
75 sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
76 inode->i_sb->s_time_gran);
77 if (ia_valid & ATTR_MTIME)
78 sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
79 inode->i_sb->s_time_gran);
80 if (ia_valid & ATTR_CTIME)
81 sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
82 inode->i_sb->s_time_gran);
83 if (ia_valid & ATTR_MODE) {
84 umode_t mode = iattr->ia_mode;
85
86 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
87 mode &= ~S_ISGID;
88 sd_iattr->ia_mode = mode;
89 }
90
91 return error;
92}
93
94static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
95{
96 inode->i_mode = mode;
97 inode->i_uid = 0;
98 inode->i_gid = 0;
99 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
100}
101
102static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
103{
104 inode->i_mode = iattr->ia_mode;
105 inode->i_uid = iattr->ia_uid;
106 inode->i_gid = iattr->ia_gid;
107 inode->i_atime = iattr->ia_atime;
108 inode->i_mtime = iattr->ia_mtime;
109 inode->i_ctime = iattr->ia_ctime;
110}
111
112struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
30{ 113{
31 struct inode * inode = new_inode(sysfs_sb); 114 struct inode * inode = new_inode(sysfs_sb);
32 if (inode) { 115 if (inode) {
33 inode->i_mode = mode;
34 inode->i_uid = 0;
35 inode->i_gid = 0;
36 inode->i_blksize = PAGE_CACHE_SIZE; 116 inode->i_blksize = PAGE_CACHE_SIZE;
37 inode->i_blocks = 0; 117 inode->i_blocks = 0;
38 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
39 inode->i_mapping->a_ops = &sysfs_aops; 118 inode->i_mapping->a_ops = &sysfs_aops;
40 inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; 119 inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
120 inode->i_op = &sysfs_inode_operations;
121
122 if (sd->s_iattr) {
123 /* sysfs_dirent has non-default attributes
124 * get them for the new inode from persistent copy
125 * in sysfs_dirent
126 */
127 set_inode_attr(inode, sd->s_iattr);
128 } else
129 set_default_inode_attr(inode, mode);
41 } 130 }
42 return inode; 131 return inode;
43} 132}
@@ -48,7 +137,8 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
48 struct inode * inode = NULL; 137 struct inode * inode = NULL;
49 if (dentry) { 138 if (dentry) {
50 if (!dentry->d_inode) { 139 if (!dentry->d_inode) {
51 if ((inode = sysfs_new_inode(mode))) { 140 struct sysfs_dirent * sd = dentry->d_fsdata;
141 if ((inode = sysfs_new_inode(mode, sd))) {
52 if (dentry->d_parent && dentry->d_parent->d_inode) { 142 if (dentry->d_parent && dentry->d_parent->d_inode) {
53 struct inode *p_inode = dentry->d_parent->d_inode; 143 struct inode *p_inode = dentry->d_parent->d_inode;
54 p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; 144 p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;