diff options
Diffstat (limited to 'fs/f2fs')
-rw-r--r-- | fs/f2fs/namei.c | 504 |
1 files changed, 504 insertions, 0 deletions
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c new file mode 100644 index 000000000000..aec362f6f0b0 --- /dev/null +++ b/fs/f2fs/namei.c | |||
@@ -0,0 +1,504 @@ | |||
1 | /** | ||
2 | * fs/f2fs/namei.c | ||
3 | * | ||
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||
5 | * http://www.samsung.com/ | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/fs.h> | ||
12 | #include <linux/f2fs_fs.h> | ||
13 | #include <linux/pagemap.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/ctype.h> | ||
16 | |||
17 | #include "f2fs.h" | ||
18 | #include "xattr.h" | ||
19 | #include "acl.h" | ||
20 | |||
21 | static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) | ||
22 | { | ||
23 | struct super_block *sb = dir->i_sb; | ||
24 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | ||
25 | nid_t ino; | ||
26 | struct inode *inode; | ||
27 | bool nid_free = false; | ||
28 | int err; | ||
29 | |||
30 | inode = new_inode(sb); | ||
31 | if (!inode) | ||
32 | return ERR_PTR(-ENOMEM); | ||
33 | |||
34 | mutex_lock_op(sbi, NODE_NEW); | ||
35 | if (!alloc_nid(sbi, &ino)) { | ||
36 | mutex_unlock_op(sbi, NODE_NEW); | ||
37 | err = -ENOSPC; | ||
38 | goto fail; | ||
39 | } | ||
40 | mutex_unlock_op(sbi, NODE_NEW); | ||
41 | |||
42 | inode->i_uid = current_fsuid(); | ||
43 | |||
44 | if (dir->i_mode & S_ISGID) { | ||
45 | inode->i_gid = dir->i_gid; | ||
46 | if (S_ISDIR(mode)) | ||
47 | mode |= S_ISGID; | ||
48 | } else { | ||
49 | inode->i_gid = current_fsgid(); | ||
50 | } | ||
51 | |||
52 | inode->i_ino = ino; | ||
53 | inode->i_mode = mode; | ||
54 | inode->i_blocks = 0; | ||
55 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | ||
56 | inode->i_generation = sbi->s_next_generation++; | ||
57 | |||
58 | err = insert_inode_locked(inode); | ||
59 | if (err) { | ||
60 | err = -EINVAL; | ||
61 | nid_free = true; | ||
62 | goto out; | ||
63 | } | ||
64 | |||
65 | mark_inode_dirty(inode); | ||
66 | return inode; | ||
67 | |||
68 | out: | ||
69 | clear_nlink(inode); | ||
70 | unlock_new_inode(inode); | ||
71 | fail: | ||
72 | iput(inode); | ||
73 | if (nid_free) | ||
74 | alloc_nid_failed(sbi, ino); | ||
75 | return ERR_PTR(err); | ||
76 | } | ||
77 | |||
78 | static int is_multimedia_file(const unsigned char *s, const char *sub) | ||
79 | { | ||
80 | int slen = strlen(s); | ||
81 | int sublen = strlen(sub); | ||
82 | int ret; | ||
83 | |||
84 | if (sublen > slen) | ||
85 | return 1; | ||
86 | |||
87 | ret = memcmp(s + slen - sublen, sub, sublen); | ||
88 | if (ret) { /* compare upper case */ | ||
89 | int i; | ||
90 | char upper_sub[8]; | ||
91 | for (i = 0; i < sublen && i < sizeof(upper_sub); i++) | ||
92 | upper_sub[i] = toupper(sub[i]); | ||
93 | return memcmp(s + slen - sublen, upper_sub, sublen); | ||
94 | } | ||
95 | |||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * Set multimedia files as cold files for hot/cold data separation | ||
101 | */ | ||
102 | static inline void set_cold_file(struct f2fs_sb_info *sbi, struct inode *inode, | ||
103 | const unsigned char *name) | ||
104 | { | ||
105 | int i; | ||
106 | __u8 (*extlist)[8] = sbi->raw_super->extension_list; | ||
107 | |||
108 | int count = le32_to_cpu(sbi->raw_super->extension_count); | ||
109 | for (i = 0; i < count; i++) { | ||
110 | if (!is_multimedia_file(name, extlist[i])) { | ||
111 | F2FS_I(inode)->i_advise |= FADVISE_COLD_BIT; | ||
112 | break; | ||
113 | } | ||
114 | } | ||
115 | } | ||
116 | |||
117 | static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | ||
118 | bool excl) | ||
119 | { | ||
120 | struct super_block *sb = dir->i_sb; | ||
121 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | ||
122 | struct inode *inode; | ||
123 | nid_t ino = 0; | ||
124 | int err; | ||
125 | |||
126 | inode = f2fs_new_inode(dir, mode); | ||
127 | if (IS_ERR(inode)) | ||
128 | return PTR_ERR(inode); | ||
129 | |||
130 | if (!test_opt(sbi, DISABLE_EXT_IDENTIFY)) | ||
131 | set_cold_file(sbi, inode, dentry->d_name.name); | ||
132 | |||
133 | inode->i_op = &f2fs_file_inode_operations; | ||
134 | inode->i_fop = &f2fs_file_operations; | ||
135 | inode->i_mapping->a_ops = &f2fs_dblock_aops; | ||
136 | ino = inode->i_ino; | ||
137 | |||
138 | err = f2fs_add_link(dentry, inode); | ||
139 | if (err) | ||
140 | goto out; | ||
141 | |||
142 | alloc_nid_done(sbi, ino); | ||
143 | |||
144 | if (!sbi->por_doing) | ||
145 | d_instantiate(dentry, inode); | ||
146 | unlock_new_inode(inode); | ||
147 | |||
148 | f2fs_balance_fs(sbi); | ||
149 | return 0; | ||
150 | out: | ||
151 | clear_nlink(inode); | ||
152 | unlock_new_inode(inode); | ||
153 | iput(inode); | ||
154 | alloc_nid_failed(sbi, ino); | ||
155 | return err; | ||
156 | } | ||
157 | |||
158 | static int f2fs_link(struct dentry *old_dentry, struct inode *dir, | ||
159 | struct dentry *dentry) | ||
160 | { | ||
161 | struct inode *inode = old_dentry->d_inode; | ||
162 | struct super_block *sb = dir->i_sb; | ||
163 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | ||
164 | int err; | ||
165 | |||
166 | inode->i_ctime = CURRENT_TIME; | ||
167 | atomic_inc(&inode->i_count); | ||
168 | |||
169 | set_inode_flag(F2FS_I(inode), FI_INC_LINK); | ||
170 | err = f2fs_add_link(dentry, inode); | ||
171 | if (err) | ||
172 | goto out; | ||
173 | |||
174 | d_instantiate(dentry, inode); | ||
175 | |||
176 | f2fs_balance_fs(sbi); | ||
177 | return 0; | ||
178 | out: | ||
179 | clear_inode_flag(F2FS_I(inode), FI_INC_LINK); | ||
180 | iput(inode); | ||
181 | return err; | ||
182 | } | ||
183 | |||
184 | struct dentry *f2fs_get_parent(struct dentry *child) | ||
185 | { | ||
186 | struct qstr dotdot = QSTR_INIT("..", 2); | ||
187 | unsigned long ino = f2fs_inode_by_name(child->d_inode, &dotdot); | ||
188 | if (!ino) | ||
189 | return ERR_PTR(-ENOENT); | ||
190 | return d_obtain_alias(f2fs_iget(child->d_inode->i_sb, ino)); | ||
191 | } | ||
192 | |||
193 | static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry, | ||
194 | unsigned int flags) | ||
195 | { | ||
196 | struct inode *inode = NULL; | ||
197 | struct f2fs_dir_entry *de; | ||
198 | struct page *page; | ||
199 | |||
200 | if (dentry->d_name.len > F2FS_MAX_NAME_LEN) | ||
201 | return ERR_PTR(-ENAMETOOLONG); | ||
202 | |||
203 | de = f2fs_find_entry(dir, &dentry->d_name, &page); | ||
204 | if (de) { | ||
205 | nid_t ino = le32_to_cpu(de->ino); | ||
206 | kunmap(page); | ||
207 | f2fs_put_page(page, 0); | ||
208 | |||
209 | inode = f2fs_iget(dir->i_sb, ino); | ||
210 | if (IS_ERR(inode)) | ||
211 | return ERR_CAST(inode); | ||
212 | } | ||
213 | |||
214 | return d_splice_alias(inode, dentry); | ||
215 | } | ||
216 | |||
217 | static int f2fs_unlink(struct inode *dir, struct dentry *dentry) | ||
218 | { | ||
219 | struct super_block *sb = dir->i_sb; | ||
220 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | ||
221 | struct inode *inode = dentry->d_inode; | ||
222 | struct f2fs_dir_entry *de; | ||
223 | struct page *page; | ||
224 | int err = -ENOENT; | ||
225 | |||
226 | de = f2fs_find_entry(dir, &dentry->d_name, &page); | ||
227 | if (!de) | ||
228 | goto fail; | ||
229 | |||
230 | err = check_orphan_space(sbi); | ||
231 | if (err) { | ||
232 | kunmap(page); | ||
233 | f2fs_put_page(page, 0); | ||
234 | goto fail; | ||
235 | } | ||
236 | |||
237 | f2fs_delete_entry(de, page, inode); | ||
238 | |||
239 | /* In order to evict this inode, we set it dirty */ | ||
240 | mark_inode_dirty(inode); | ||
241 | f2fs_balance_fs(sbi); | ||
242 | fail: | ||
243 | return err; | ||
244 | } | ||
245 | |||
246 | static int f2fs_symlink(struct inode *dir, struct dentry *dentry, | ||
247 | const char *symname) | ||
248 | { | ||
249 | struct super_block *sb = dir->i_sb; | ||
250 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | ||
251 | struct inode *inode; | ||
252 | unsigned symlen = strlen(symname) + 1; | ||
253 | int err; | ||
254 | |||
255 | inode = f2fs_new_inode(dir, S_IFLNK | S_IRWXUGO); | ||
256 | if (IS_ERR(inode)) | ||
257 | return PTR_ERR(inode); | ||
258 | |||
259 | inode->i_op = &f2fs_symlink_inode_operations; | ||
260 | inode->i_mapping->a_ops = &f2fs_dblock_aops; | ||
261 | |||
262 | err = f2fs_add_link(dentry, inode); | ||
263 | if (err) | ||
264 | goto out; | ||
265 | |||
266 | err = page_symlink(inode, symname, symlen); | ||
267 | alloc_nid_done(sbi, inode->i_ino); | ||
268 | |||
269 | d_instantiate(dentry, inode); | ||
270 | unlock_new_inode(inode); | ||
271 | |||
272 | f2fs_balance_fs(sbi); | ||
273 | |||
274 | return err; | ||
275 | out: | ||
276 | clear_nlink(inode); | ||
277 | unlock_new_inode(inode); | ||
278 | iput(inode); | ||
279 | alloc_nid_failed(sbi, inode->i_ino); | ||
280 | return err; | ||
281 | } | ||
282 | |||
283 | static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | ||
284 | { | ||
285 | struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); | ||
286 | struct inode *inode; | ||
287 | int err; | ||
288 | |||
289 | inode = f2fs_new_inode(dir, S_IFDIR | mode); | ||
290 | err = PTR_ERR(inode); | ||
291 | if (IS_ERR(inode)) | ||
292 | return err; | ||
293 | |||
294 | inode->i_op = &f2fs_dir_inode_operations; | ||
295 | inode->i_fop = &f2fs_dir_operations; | ||
296 | inode->i_mapping->a_ops = &f2fs_dblock_aops; | ||
297 | mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS | __GFP_ZERO); | ||
298 | |||
299 | set_inode_flag(F2FS_I(inode), FI_INC_LINK); | ||
300 | err = f2fs_add_link(dentry, inode); | ||
301 | if (err) | ||
302 | goto out_fail; | ||
303 | |||
304 | alloc_nid_done(sbi, inode->i_ino); | ||
305 | |||
306 | d_instantiate(dentry, inode); | ||
307 | unlock_new_inode(inode); | ||
308 | |||
309 | f2fs_balance_fs(sbi); | ||
310 | return 0; | ||
311 | |||
312 | out_fail: | ||
313 | clear_inode_flag(F2FS_I(inode), FI_INC_LINK); | ||
314 | clear_nlink(inode); | ||
315 | unlock_new_inode(inode); | ||
316 | iput(inode); | ||
317 | alloc_nid_failed(sbi, inode->i_ino); | ||
318 | return err; | ||
319 | } | ||
320 | |||
321 | static int f2fs_rmdir(struct inode *dir, struct dentry *dentry) | ||
322 | { | ||
323 | struct inode *inode = dentry->d_inode; | ||
324 | if (f2fs_empty_dir(inode)) | ||
325 | return f2fs_unlink(dir, dentry); | ||
326 | return -ENOTEMPTY; | ||
327 | } | ||
328 | |||
329 | static int f2fs_mknod(struct inode *dir, struct dentry *dentry, | ||
330 | umode_t mode, dev_t rdev) | ||
331 | { | ||
332 | struct super_block *sb = dir->i_sb; | ||
333 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | ||
334 | struct inode *inode; | ||
335 | int err = 0; | ||
336 | |||
337 | if (!new_valid_dev(rdev)) | ||
338 | return -EINVAL; | ||
339 | |||
340 | inode = f2fs_new_inode(dir, mode); | ||
341 | if (IS_ERR(inode)) | ||
342 | return PTR_ERR(inode); | ||
343 | |||
344 | init_special_inode(inode, inode->i_mode, rdev); | ||
345 | inode->i_op = &f2fs_special_inode_operations; | ||
346 | |||
347 | err = f2fs_add_link(dentry, inode); | ||
348 | if (err) | ||
349 | goto out; | ||
350 | |||
351 | alloc_nid_done(sbi, inode->i_ino); | ||
352 | d_instantiate(dentry, inode); | ||
353 | unlock_new_inode(inode); | ||
354 | |||
355 | f2fs_balance_fs(sbi); | ||
356 | |||
357 | return 0; | ||
358 | out: | ||
359 | clear_nlink(inode); | ||
360 | unlock_new_inode(inode); | ||
361 | iput(inode); | ||
362 | alloc_nid_failed(sbi, inode->i_ino); | ||
363 | return err; | ||
364 | } | ||
365 | |||
366 | static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, | ||
367 | struct inode *new_dir, struct dentry *new_dentry) | ||
368 | { | ||
369 | struct super_block *sb = old_dir->i_sb; | ||
370 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | ||
371 | struct inode *old_inode = old_dentry->d_inode; | ||
372 | struct inode *new_inode = new_dentry->d_inode; | ||
373 | struct page *old_dir_page; | ||
374 | struct page *old_page; | ||
375 | struct f2fs_dir_entry *old_dir_entry = NULL; | ||
376 | struct f2fs_dir_entry *old_entry; | ||
377 | struct f2fs_dir_entry *new_entry; | ||
378 | int err = -ENOENT; | ||
379 | |||
380 | old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page); | ||
381 | if (!old_entry) | ||
382 | goto out; | ||
383 | |||
384 | if (S_ISDIR(old_inode->i_mode)) { | ||
385 | err = -EIO; | ||
386 | old_dir_entry = f2fs_parent_dir(old_inode, &old_dir_page); | ||
387 | if (!old_dir_entry) | ||
388 | goto out_old; | ||
389 | } | ||
390 | |||
391 | mutex_lock_op(sbi, RENAME); | ||
392 | |||
393 | if (new_inode) { | ||
394 | struct page *new_page; | ||
395 | |||
396 | err = -ENOTEMPTY; | ||
397 | if (old_dir_entry && !f2fs_empty_dir(new_inode)) | ||
398 | goto out_dir; | ||
399 | |||
400 | err = -ENOENT; | ||
401 | new_entry = f2fs_find_entry(new_dir, &new_dentry->d_name, | ||
402 | &new_page); | ||
403 | if (!new_entry) | ||
404 | goto out_dir; | ||
405 | |||
406 | f2fs_set_link(new_dir, new_entry, new_page, old_inode); | ||
407 | |||
408 | new_inode->i_ctime = CURRENT_TIME; | ||
409 | if (old_dir_entry) | ||
410 | drop_nlink(new_inode); | ||
411 | drop_nlink(new_inode); | ||
412 | if (!new_inode->i_nlink) | ||
413 | add_orphan_inode(sbi, new_inode->i_ino); | ||
414 | f2fs_write_inode(new_inode, NULL); | ||
415 | } else { | ||
416 | err = f2fs_add_link(new_dentry, old_inode); | ||
417 | if (err) | ||
418 | goto out_dir; | ||
419 | |||
420 | if (old_dir_entry) { | ||
421 | inc_nlink(new_dir); | ||
422 | f2fs_write_inode(new_dir, NULL); | ||
423 | } | ||
424 | } | ||
425 | |||
426 | old_inode->i_ctime = CURRENT_TIME; | ||
427 | set_inode_flag(F2FS_I(old_inode), FI_NEED_CP); | ||
428 | mark_inode_dirty(old_inode); | ||
429 | |||
430 | f2fs_delete_entry(old_entry, old_page, NULL); | ||
431 | |||
432 | if (old_dir_entry) { | ||
433 | if (old_dir != new_dir) { | ||
434 | f2fs_set_link(old_inode, old_dir_entry, | ||
435 | old_dir_page, new_dir); | ||
436 | } else { | ||
437 | kunmap(old_dir_page); | ||
438 | f2fs_put_page(old_dir_page, 0); | ||
439 | } | ||
440 | drop_nlink(old_dir); | ||
441 | f2fs_write_inode(old_dir, NULL); | ||
442 | } | ||
443 | |||
444 | mutex_unlock_op(sbi, RENAME); | ||
445 | |||
446 | f2fs_balance_fs(sbi); | ||
447 | return 0; | ||
448 | |||
449 | out_dir: | ||
450 | if (old_dir_entry) { | ||
451 | kunmap(old_dir_page); | ||
452 | f2fs_put_page(old_dir_page, 0); | ||
453 | } | ||
454 | mutex_unlock_op(sbi, RENAME); | ||
455 | out_old: | ||
456 | kunmap(old_page); | ||
457 | f2fs_put_page(old_page, 0); | ||
458 | out: | ||
459 | return err; | ||
460 | } | ||
461 | |||
462 | const struct inode_operations f2fs_dir_inode_operations = { | ||
463 | .create = f2fs_create, | ||
464 | .lookup = f2fs_lookup, | ||
465 | .link = f2fs_link, | ||
466 | .unlink = f2fs_unlink, | ||
467 | .symlink = f2fs_symlink, | ||
468 | .mkdir = f2fs_mkdir, | ||
469 | .rmdir = f2fs_rmdir, | ||
470 | .mknod = f2fs_mknod, | ||
471 | .rename = f2fs_rename, | ||
472 | .setattr = f2fs_setattr, | ||
473 | .get_acl = f2fs_get_acl, | ||
474 | #ifdef CONFIG_F2FS_FS_XATTR | ||
475 | .setxattr = generic_setxattr, | ||
476 | .getxattr = generic_getxattr, | ||
477 | .listxattr = f2fs_listxattr, | ||
478 | .removexattr = generic_removexattr, | ||
479 | #endif | ||
480 | }; | ||
481 | |||
482 | const struct inode_operations f2fs_symlink_inode_operations = { | ||
483 | .readlink = generic_readlink, | ||
484 | .follow_link = page_follow_link_light, | ||
485 | .put_link = page_put_link, | ||
486 | .setattr = f2fs_setattr, | ||
487 | #ifdef CONFIG_F2FS_FS_XATTR | ||
488 | .setxattr = generic_setxattr, | ||
489 | .getxattr = generic_getxattr, | ||
490 | .listxattr = f2fs_listxattr, | ||
491 | .removexattr = generic_removexattr, | ||
492 | #endif | ||
493 | }; | ||
494 | |||
495 | const struct inode_operations f2fs_special_inode_operations = { | ||
496 | .setattr = f2fs_setattr, | ||
497 | .get_acl = f2fs_get_acl, | ||
498 | #ifdef CONFIG_F2FS_FS_XATTR | ||
499 | .setxattr = generic_setxattr, | ||
500 | .getxattr = generic_getxattr, | ||
501 | .listxattr = f2fs_listxattr, | ||
502 | .removexattr = generic_removexattr, | ||
503 | #endif | ||
504 | }; | ||