diff options
Diffstat (limited to 'fs/sysfs/inode.c')
-rw-r--r-- | fs/sysfs/inode.c | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index e22db6cd4df7..200e1bf6f932 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -122,8 +122,22 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) | |||
122 | */ | 122 | */ |
123 | static struct lock_class_key sysfs_inode_imutex_key; | 123 | static struct lock_class_key sysfs_inode_imutex_key; |
124 | 124 | ||
125 | static int sysfs_count_nlink(struct sysfs_dirent *sd) | ||
126 | { | ||
127 | struct sysfs_dirent *child; | ||
128 | int nr = 0; | ||
129 | |||
130 | for (child = sd->s_children; child; child = child->s_sibling) | ||
131 | if (sysfs_type(child) == SYSFS_DIR) | ||
132 | nr++; | ||
133 | |||
134 | return nr + 2; | ||
135 | } | ||
136 | |||
125 | static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) | 137 | static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) |
126 | { | 138 | { |
139 | struct bin_attribute *bin_attr; | ||
140 | |||
127 | inode->i_blocks = 0; | 141 | inode->i_blocks = 0; |
128 | inode->i_mapping->a_ops = &sysfs_aops; | 142 | inode->i_mapping->a_ops = &sysfs_aops; |
129 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; | 143 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; |
@@ -139,6 +153,37 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) | |||
139 | set_inode_attr(inode, sd->s_iattr); | 153 | set_inode_attr(inode, sd->s_iattr); |
140 | } else | 154 | } else |
141 | set_default_inode_attr(inode, sd->s_mode); | 155 | set_default_inode_attr(inode, sd->s_mode); |
156 | |||
157 | |||
158 | /* initialize inode according to type */ | ||
159 | switch (sysfs_type(sd)) { | ||
160 | case SYSFS_ROOT: | ||
161 | inode->i_op = &sysfs_dir_inode_operations; | ||
162 | inode->i_fop = &sysfs_dir_operations; | ||
163 | inc_nlink(inode); /* directory, account for "." */ | ||
164 | break; | ||
165 | case SYSFS_DIR: | ||
166 | inode->i_op = &sysfs_dir_inode_operations; | ||
167 | inode->i_fop = &sysfs_dir_operations; | ||
168 | inode->i_nlink = sysfs_count_nlink(sd); | ||
169 | break; | ||
170 | case SYSFS_KOBJ_ATTR: | ||
171 | inode->i_size = PAGE_SIZE; | ||
172 | inode->i_fop = &sysfs_file_operations; | ||
173 | break; | ||
174 | case SYSFS_KOBJ_BIN_ATTR: | ||
175 | bin_attr = sd->s_elem.bin_attr.bin_attr; | ||
176 | inode->i_size = bin_attr->size; | ||
177 | inode->i_fop = &bin_fops; | ||
178 | break; | ||
179 | case SYSFS_KOBJ_LINK: | ||
180 | inode->i_op = &sysfs_symlink_inode_operations; | ||
181 | break; | ||
182 | default: | ||
183 | BUG(); | ||
184 | } | ||
185 | |||
186 | unlock_new_inode(inode); | ||
142 | } | 187 | } |
143 | 188 | ||
144 | /** | 189 | /** |
@@ -180,9 +225,6 @@ void sysfs_instantiate(struct dentry *dentry, struct inode *inode) | |||
180 | { | 225 | { |
181 | BUG_ON(!dentry || dentry->d_inode); | 226 | BUG_ON(!dentry || dentry->d_inode); |
182 | 227 | ||
183 | if (inode->i_state & I_NEW) | ||
184 | unlock_new_inode(inode); | ||
185 | |||
186 | d_instantiate(dentry, inode); | 228 | d_instantiate(dentry, inode); |
187 | } | 229 | } |
188 | 230 | ||