diff options
Diffstat (limited to 'fs/sysfs/inode.c')
-rw-r--r-- | fs/sysfs/inode.c | 103 |
1 files changed, 55 insertions, 48 deletions
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 10d1b52899f1..9236635111f4 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -1,7 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * inode.c - basic inode and dentry operations. | 2 | * fs/sysfs/inode.c - basic sysfs inode and dentry operations |
3 | * | 3 | * |
4 | * sysfs is Copyright (c) 2001-3 Patrick Mochel | 4 | * Copyright (c) 2001-3 Patrick Mochel |
5 | * Copyright (c) 2007 SUSE Linux Products GmbH | ||
6 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> | ||
7 | * | ||
8 | * This file is released under the GPLv2. | ||
5 | * | 9 | * |
6 | * Please see Documentation/filesystems/sysfs.txt for more information. | 10 | * Please see Documentation/filesystems/sysfs.txt for more information. |
7 | */ | 11 | */ |
@@ -14,7 +18,6 @@ | |||
14 | #include <linux/capability.h> | 18 | #include <linux/capability.h> |
15 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
16 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
17 | #include <asm/semaphore.h> | ||
18 | #include "sysfs.h" | 21 | #include "sysfs.h" |
19 | 22 | ||
20 | extern struct super_block * sysfs_sb; | 23 | extern struct super_block * sysfs_sb; |
@@ -34,16 +37,6 @@ static const struct inode_operations sysfs_inode_operations ={ | |||
34 | .setattr = sysfs_setattr, | 37 | .setattr = sysfs_setattr, |
35 | }; | 38 | }; |
36 | 39 | ||
37 | void sysfs_delete_inode(struct inode *inode) | ||
38 | { | ||
39 | /* Free the shadowed directory inode operations */ | ||
40 | if (sysfs_is_shadowed_inode(inode)) { | ||
41 | kfree(inode->i_op); | ||
42 | inode->i_op = NULL; | ||
43 | } | ||
44 | return generic_delete_inode(inode); | ||
45 | } | ||
46 | |||
47 | int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) | 40 | int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) |
48 | { | 41 | { |
49 | struct inode * inode = dentry->d_inode; | 42 | struct inode * inode = dentry->d_inode; |
@@ -133,8 +126,22 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) | |||
133 | */ | 126 | */ |
134 | static struct lock_class_key sysfs_inode_imutex_key; | 127 | static struct lock_class_key sysfs_inode_imutex_key; |
135 | 128 | ||
129 | static int sysfs_count_nlink(struct sysfs_dirent *sd) | ||
130 | { | ||
131 | struct sysfs_dirent *child; | ||
132 | int nr = 0; | ||
133 | |||
134 | for (child = sd->s_dir.children; child; child = child->s_sibling) | ||
135 | if (sysfs_type(child) == SYSFS_DIR) | ||
136 | nr++; | ||
137 | |||
138 | return nr + 2; | ||
139 | } | ||
140 | |||
136 | static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) | 141 | static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) |
137 | { | 142 | { |
143 | struct bin_attribute *bin_attr; | ||
144 | |||
138 | inode->i_blocks = 0; | 145 | inode->i_blocks = 0; |
139 | inode->i_mapping->a_ops = &sysfs_aops; | 146 | inode->i_mapping->a_ops = &sysfs_aops; |
140 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; | 147 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; |
@@ -150,6 +157,32 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) | |||
150 | set_inode_attr(inode, sd->s_iattr); | 157 | set_inode_attr(inode, sd->s_iattr); |
151 | } else | 158 | } else |
152 | set_default_inode_attr(inode, sd->s_mode); | 159 | set_default_inode_attr(inode, sd->s_mode); |
160 | |||
161 | |||
162 | /* initialize inode according to type */ | ||
163 | switch (sysfs_type(sd)) { | ||
164 | case SYSFS_DIR: | ||
165 | inode->i_op = &sysfs_dir_inode_operations; | ||
166 | inode->i_fop = &sysfs_dir_operations; | ||
167 | inode->i_nlink = sysfs_count_nlink(sd); | ||
168 | break; | ||
169 | case SYSFS_KOBJ_ATTR: | ||
170 | inode->i_size = PAGE_SIZE; | ||
171 | inode->i_fop = &sysfs_file_operations; | ||
172 | break; | ||
173 | case SYSFS_KOBJ_BIN_ATTR: | ||
174 | bin_attr = sd->s_bin_attr.bin_attr; | ||
175 | inode->i_size = bin_attr->size; | ||
176 | inode->i_fop = &bin_fops; | ||
177 | break; | ||
178 | case SYSFS_KOBJ_LINK: | ||
179 | inode->i_op = &sysfs_symlink_inode_operations; | ||
180 | break; | ||
181 | default: | ||
182 | BUG(); | ||
183 | } | ||
184 | |||
185 | unlock_new_inode(inode); | ||
153 | } | 186 | } |
154 | 187 | ||
155 | /** | 188 | /** |
@@ -177,50 +210,24 @@ struct inode * sysfs_get_inode(struct sysfs_dirent *sd) | |||
177 | return inode; | 210 | return inode; |
178 | } | 211 | } |
179 | 212 | ||
180 | /** | ||
181 | * sysfs_instantiate - instantiate dentry | ||
182 | * @dentry: dentry to be instantiated | ||
183 | * @inode: inode associated with @sd | ||
184 | * | ||
185 | * Unlock @inode if locked and instantiate @dentry with @inode. | ||
186 | * | ||
187 | * LOCKING: | ||
188 | * None. | ||
189 | */ | ||
190 | void sysfs_instantiate(struct dentry *dentry, struct inode *inode) | ||
191 | { | ||
192 | BUG_ON(!dentry || dentry->d_inode); | ||
193 | |||
194 | if (inode->i_state & I_NEW) | ||
195 | unlock_new_inode(inode); | ||
196 | |||
197 | d_instantiate(dentry, inode); | ||
198 | } | ||
199 | |||
200 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) | 213 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) |
201 | { | 214 | { |
202 | struct sysfs_addrm_cxt acxt; | 215 | struct sysfs_addrm_cxt acxt; |
203 | struct sysfs_dirent **pos, *sd; | 216 | struct sysfs_dirent *sd; |
204 | 217 | ||
205 | if (!dir_sd) | 218 | if (!dir_sd) |
206 | return -ENOENT; | 219 | return -ENOENT; |
207 | 220 | ||
208 | sysfs_addrm_start(&acxt, dir_sd); | 221 | sysfs_addrm_start(&acxt, dir_sd); |
209 | 222 | ||
210 | for (pos = &dir_sd->s_children; *pos; pos = &(*pos)->s_sibling) { | 223 | sd = sysfs_find_dirent(dir_sd, name); |
211 | sd = *pos; | 224 | if (sd) |
212 | 225 | sysfs_remove_one(&acxt, sd); | |
213 | if (!sysfs_type(sd)) | 226 | |
214 | continue; | 227 | sysfs_addrm_finish(&acxt); |
215 | if (!strcmp(sd->s_name, name)) { | ||
216 | *pos = sd->s_sibling; | ||
217 | sd->s_sibling = NULL; | ||
218 | sysfs_remove_one(&acxt, sd); | ||
219 | break; | ||
220 | } | ||
221 | } | ||
222 | 228 | ||
223 | if (sysfs_addrm_finish(&acxt)) | 229 | if (sd) |
224 | return 0; | 230 | return 0; |
225 | return -ENOENT; | 231 | else |
232 | return -ENOENT; | ||
226 | } | 233 | } |