diff options
Diffstat (limited to 'fs/kernfs/inode.c')
-rw-r--r-- | fs/kernfs/inode.c | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c new file mode 100644 index 000000000000..e55126f85bd2 --- /dev/null +++ b/fs/kernfs/inode.c | |||
@@ -0,0 +1,377 @@ | |||
1 | /* | ||
2 | * fs/kernfs/inode.c - kernfs inode implementation | ||
3 | * | ||
4 | * Copyright (c) 2001-3 Patrick Mochel | ||
5 | * Copyright (c) 2007 SUSE Linux Products GmbH | ||
6 | * Copyright (c) 2007, 2013 Tejun Heo <tj@kernel.org> | ||
7 | * | ||
8 | * This file is released under the GPLv2. | ||
9 | */ | ||
10 | |||
11 | #include <linux/pagemap.h> | ||
12 | #include <linux/backing-dev.h> | ||
13 | #include <linux/capability.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/xattr.h> | ||
17 | #include <linux/security.h> | ||
18 | |||
19 | #include "kernfs-internal.h" | ||
20 | |||
21 | static const struct address_space_operations kernfs_aops = { | ||
22 | .readpage = simple_readpage, | ||
23 | .write_begin = simple_write_begin, | ||
24 | .write_end = simple_write_end, | ||
25 | }; | ||
26 | |||
27 | static struct backing_dev_info kernfs_bdi = { | ||
28 | .name = "kernfs", | ||
29 | .ra_pages = 0, /* No readahead */ | ||
30 | .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, | ||
31 | }; | ||
32 | |||
33 | static const struct inode_operations kernfs_iops = { | ||
34 | .permission = kernfs_iop_permission, | ||
35 | .setattr = kernfs_iop_setattr, | ||
36 | .getattr = kernfs_iop_getattr, | ||
37 | .setxattr = kernfs_iop_setxattr, | ||
38 | .removexattr = kernfs_iop_removexattr, | ||
39 | .getxattr = kernfs_iop_getxattr, | ||
40 | .listxattr = kernfs_iop_listxattr, | ||
41 | }; | ||
42 | |||
43 | void __init kernfs_inode_init(void) | ||
44 | { | ||
45 | if (bdi_init(&kernfs_bdi)) | ||
46 | panic("failed to init kernfs_bdi"); | ||
47 | } | ||
48 | |||
49 | static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn) | ||
50 | { | ||
51 | struct iattr *iattrs; | ||
52 | |||
53 | if (kn->iattr) | ||
54 | return kn->iattr; | ||
55 | |||
56 | kn->iattr = kzalloc(sizeof(struct kernfs_iattrs), GFP_KERNEL); | ||
57 | if (!kn->iattr) | ||
58 | return NULL; | ||
59 | iattrs = &kn->iattr->ia_iattr; | ||
60 | |||
61 | /* assign default attributes */ | ||
62 | iattrs->ia_mode = kn->mode; | ||
63 | iattrs->ia_uid = GLOBAL_ROOT_UID; | ||
64 | iattrs->ia_gid = GLOBAL_ROOT_GID; | ||
65 | iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME; | ||
66 | |||
67 | simple_xattrs_init(&kn->iattr->xattrs); | ||
68 | |||
69 | return kn->iattr; | ||
70 | } | ||
71 | |||
72 | static int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr) | ||
73 | { | ||
74 | struct kernfs_iattrs *attrs; | ||
75 | struct iattr *iattrs; | ||
76 | unsigned int ia_valid = iattr->ia_valid; | ||
77 | |||
78 | attrs = kernfs_iattrs(kn); | ||
79 | if (!attrs) | ||
80 | return -ENOMEM; | ||
81 | |||
82 | iattrs = &attrs->ia_iattr; | ||
83 | |||
84 | if (ia_valid & ATTR_UID) | ||
85 | iattrs->ia_uid = iattr->ia_uid; | ||
86 | if (ia_valid & ATTR_GID) | ||
87 | iattrs->ia_gid = iattr->ia_gid; | ||
88 | if (ia_valid & ATTR_ATIME) | ||
89 | iattrs->ia_atime = iattr->ia_atime; | ||
90 | if (ia_valid & ATTR_MTIME) | ||
91 | iattrs->ia_mtime = iattr->ia_mtime; | ||
92 | if (ia_valid & ATTR_CTIME) | ||
93 | iattrs->ia_ctime = iattr->ia_ctime; | ||
94 | if (ia_valid & ATTR_MODE) { | ||
95 | umode_t mode = iattr->ia_mode; | ||
96 | iattrs->ia_mode = kn->mode = mode; | ||
97 | } | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * kernfs_setattr - set iattr on a node | ||
103 | * @kn: target node | ||
104 | * @iattr: iattr to set | ||
105 | * | ||
106 | * Returns 0 on success, -errno on failure. | ||
107 | */ | ||
108 | int kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr) | ||
109 | { | ||
110 | int ret; | ||
111 | |||
112 | mutex_lock(&kernfs_mutex); | ||
113 | ret = __kernfs_setattr(kn, iattr); | ||
114 | mutex_unlock(&kernfs_mutex); | ||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr) | ||
119 | { | ||
120 | struct inode *inode = dentry->d_inode; | ||
121 | struct kernfs_node *kn = dentry->d_fsdata; | ||
122 | int error; | ||
123 | |||
124 | if (!kn) | ||
125 | return -EINVAL; | ||
126 | |||
127 | mutex_lock(&kernfs_mutex); | ||
128 | error = inode_change_ok(inode, iattr); | ||
129 | if (error) | ||
130 | goto out; | ||
131 | |||
132 | error = __kernfs_setattr(kn, iattr); | ||
133 | if (error) | ||
134 | goto out; | ||
135 | |||
136 | /* this ignores size changes */ | ||
137 | setattr_copy(inode, iattr); | ||
138 | |||
139 | out: | ||
140 | mutex_unlock(&kernfs_mutex); | ||
141 | return error; | ||
142 | } | ||
143 | |||
144 | static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata, | ||
145 | u32 *secdata_len) | ||
146 | { | ||
147 | struct kernfs_iattrs *attrs; | ||
148 | void *old_secdata; | ||
149 | size_t old_secdata_len; | ||
150 | |||
151 | attrs = kernfs_iattrs(kn); | ||
152 | if (!attrs) | ||
153 | return -ENOMEM; | ||
154 | |||
155 | old_secdata = attrs->ia_secdata; | ||
156 | old_secdata_len = attrs->ia_secdata_len; | ||
157 | |||
158 | attrs->ia_secdata = *secdata; | ||
159 | attrs->ia_secdata_len = *secdata_len; | ||
160 | |||
161 | *secdata = old_secdata; | ||
162 | *secdata_len = old_secdata_len; | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | int kernfs_iop_setxattr(struct dentry *dentry, const char *name, | ||
167 | const void *value, size_t size, int flags) | ||
168 | { | ||
169 | struct kernfs_node *kn = dentry->d_fsdata; | ||
170 | struct kernfs_iattrs *attrs; | ||
171 | void *secdata; | ||
172 | int error; | ||
173 | u32 secdata_len = 0; | ||
174 | |||
175 | attrs = kernfs_iattrs(kn); | ||
176 | if (!attrs) | ||
177 | return -ENOMEM; | ||
178 | |||
179 | if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) { | ||
180 | const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; | ||
181 | error = security_inode_setsecurity(dentry->d_inode, suffix, | ||
182 | value, size, flags); | ||
183 | if (error) | ||
184 | return error; | ||
185 | error = security_inode_getsecctx(dentry->d_inode, | ||
186 | &secdata, &secdata_len); | ||
187 | if (error) | ||
188 | return error; | ||
189 | |||
190 | mutex_lock(&kernfs_mutex); | ||
191 | error = kernfs_node_setsecdata(kn, &secdata, &secdata_len); | ||
192 | mutex_unlock(&kernfs_mutex); | ||
193 | |||
194 | if (secdata) | ||
195 | security_release_secctx(secdata, secdata_len); | ||
196 | return error; | ||
197 | } else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) { | ||
198 | return simple_xattr_set(&attrs->xattrs, name, value, size, | ||
199 | flags); | ||
200 | } | ||
201 | |||
202 | return -EINVAL; | ||
203 | } | ||
204 | |||
205 | int kernfs_iop_removexattr(struct dentry *dentry, const char *name) | ||
206 | { | ||
207 | struct kernfs_node *kn = dentry->d_fsdata; | ||
208 | struct kernfs_iattrs *attrs; | ||
209 | |||
210 | attrs = kernfs_iattrs(kn); | ||
211 | if (!attrs) | ||
212 | return -ENOMEM; | ||
213 | |||
214 | return simple_xattr_remove(&attrs->xattrs, name); | ||
215 | } | ||
216 | |||
217 | ssize_t kernfs_iop_getxattr(struct dentry *dentry, const char *name, void *buf, | ||
218 | size_t size) | ||
219 | { | ||
220 | struct kernfs_node *kn = dentry->d_fsdata; | ||
221 | struct kernfs_iattrs *attrs; | ||
222 | |||
223 | attrs = kernfs_iattrs(kn); | ||
224 | if (!attrs) | ||
225 | return -ENOMEM; | ||
226 | |||
227 | return simple_xattr_get(&attrs->xattrs, name, buf, size); | ||
228 | } | ||
229 | |||
230 | ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size) | ||
231 | { | ||
232 | struct kernfs_node *kn = dentry->d_fsdata; | ||
233 | struct kernfs_iattrs *attrs; | ||
234 | |||
235 | attrs = kernfs_iattrs(kn); | ||
236 | if (!attrs) | ||
237 | return -ENOMEM; | ||
238 | |||
239 | return simple_xattr_list(&attrs->xattrs, buf, size); | ||
240 | } | ||
241 | |||
242 | static inline void set_default_inode_attr(struct inode *inode, umode_t mode) | ||
243 | { | ||
244 | inode->i_mode = mode; | ||
245 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
246 | } | ||
247 | |||
248 | static inline void set_inode_attr(struct inode *inode, struct iattr *iattr) | ||
249 | { | ||
250 | inode->i_uid = iattr->ia_uid; | ||
251 | inode->i_gid = iattr->ia_gid; | ||
252 | inode->i_atime = iattr->ia_atime; | ||
253 | inode->i_mtime = iattr->ia_mtime; | ||
254 | inode->i_ctime = iattr->ia_ctime; | ||
255 | } | ||
256 | |||
257 | static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode) | ||
258 | { | ||
259 | struct kernfs_iattrs *attrs = kn->iattr; | ||
260 | |||
261 | inode->i_mode = kn->mode; | ||
262 | if (attrs) { | ||
263 | /* | ||
264 | * kernfs_node has non-default attributes get them from | ||
265 | * persistent copy in kernfs_node. | ||
266 | */ | ||
267 | set_inode_attr(inode, &attrs->ia_iattr); | ||
268 | security_inode_notifysecctx(inode, attrs->ia_secdata, | ||
269 | attrs->ia_secdata_len); | ||
270 | } | ||
271 | |||
272 | if (kernfs_type(kn) == KERNFS_DIR) | ||
273 | set_nlink(inode, kn->dir.subdirs + 2); | ||
274 | } | ||
275 | |||
276 | int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry, | ||
277 | struct kstat *stat) | ||
278 | { | ||
279 | struct kernfs_node *kn = dentry->d_fsdata; | ||
280 | struct inode *inode = dentry->d_inode; | ||
281 | |||
282 | mutex_lock(&kernfs_mutex); | ||
283 | kernfs_refresh_inode(kn, inode); | ||
284 | mutex_unlock(&kernfs_mutex); | ||
285 | |||
286 | generic_fillattr(inode, stat); | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static void kernfs_init_inode(struct kernfs_node *kn, struct inode *inode) | ||
291 | { | ||
292 | kernfs_get(kn); | ||
293 | inode->i_private = kn; | ||
294 | inode->i_mapping->a_ops = &kernfs_aops; | ||
295 | inode->i_mapping->backing_dev_info = &kernfs_bdi; | ||
296 | inode->i_op = &kernfs_iops; | ||
297 | |||
298 | set_default_inode_attr(inode, kn->mode); | ||
299 | kernfs_refresh_inode(kn, inode); | ||
300 | |||
301 | /* initialize inode according to type */ | ||
302 | switch (kernfs_type(kn)) { | ||
303 | case KERNFS_DIR: | ||
304 | inode->i_op = &kernfs_dir_iops; | ||
305 | inode->i_fop = &kernfs_dir_fops; | ||
306 | break; | ||
307 | case KERNFS_FILE: | ||
308 | inode->i_size = kn->attr.size; | ||
309 | inode->i_fop = &kernfs_file_fops; | ||
310 | break; | ||
311 | case KERNFS_LINK: | ||
312 | inode->i_op = &kernfs_symlink_iops; | ||
313 | break; | ||
314 | default: | ||
315 | BUG(); | ||
316 | } | ||
317 | |||
318 | unlock_new_inode(inode); | ||
319 | } | ||
320 | |||
321 | /** | ||
322 | * kernfs_get_inode - get inode for kernfs_node | ||
323 | * @sb: super block | ||
324 | * @kn: kernfs_node to allocate inode for | ||
325 | * | ||
326 | * Get inode for @kn. If such inode doesn't exist, a new inode is | ||
327 | * allocated and basics are initialized. New inode is returned | ||
328 | * locked. | ||
329 | * | ||
330 | * LOCKING: | ||
331 | * Kernel thread context (may sleep). | ||
332 | * | ||
333 | * RETURNS: | ||
334 | * Pointer to allocated inode on success, NULL on failure. | ||
335 | */ | ||
336 | struct inode *kernfs_get_inode(struct super_block *sb, struct kernfs_node *kn) | ||
337 | { | ||
338 | struct inode *inode; | ||
339 | |||
340 | inode = iget_locked(sb, kn->ino); | ||
341 | if (inode && (inode->i_state & I_NEW)) | ||
342 | kernfs_init_inode(kn, inode); | ||
343 | |||
344 | return inode; | ||
345 | } | ||
346 | |||
347 | /* | ||
348 | * The kernfs_node serves as both an inode and a directory entry for | ||
349 | * kernfs. To prevent the kernfs inode numbers from being freed | ||
350 | * prematurely we take a reference to kernfs_node from the kernfs inode. A | ||
351 | * super_operations.evict_inode() implementation is needed to drop that | ||
352 | * reference upon inode destruction. | ||
353 | */ | ||
354 | void kernfs_evict_inode(struct inode *inode) | ||
355 | { | ||
356 | struct kernfs_node *kn = inode->i_private; | ||
357 | |||
358 | truncate_inode_pages(&inode->i_data, 0); | ||
359 | clear_inode(inode); | ||
360 | kernfs_put(kn); | ||
361 | } | ||
362 | |||
363 | int kernfs_iop_permission(struct inode *inode, int mask) | ||
364 | { | ||
365 | struct kernfs_node *kn; | ||
366 | |||
367 | if (mask & MAY_NOT_BLOCK) | ||
368 | return -ECHILD; | ||
369 | |||
370 | kn = inode->i_private; | ||
371 | |||
372 | mutex_lock(&kernfs_mutex); | ||
373 | kernfs_refresh_inode(kn, inode); | ||
374 | mutex_unlock(&kernfs_mutex); | ||
375 | |||
376 | return generic_permission(inode, mask); | ||
377 | } | ||