diff options
Diffstat (limited to 'fs/nilfs2/namei.c')
-rw-r--r-- | fs/nilfs2/namei.c | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c new file mode 100644 index 000000000000..df70dadb336f --- /dev/null +++ b/fs/nilfs2/namei.c | |||
@@ -0,0 +1,474 @@ | |||
1 | /* | ||
2 | * namei.c - NILFS pathname lookup operations. | ||
3 | * | ||
4 | * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | * | ||
20 | * Modified for NILFS by Amagai Yoshiji <amagai@osrg.net>, | ||
21 | * Ryusuke Konishi <ryusuke@osrg.net> | ||
22 | */ | ||
23 | /* | ||
24 | * linux/fs/ext2/namei.c | ||
25 | * | ||
26 | * Copyright (C) 1992, 1993, 1994, 1995 | ||
27 | * Remy Card (card@masi.ibp.fr) | ||
28 | * Laboratoire MASI - Institut Blaise Pascal | ||
29 | * Universite Pierre et Marie Curie (Paris VI) | ||
30 | * | ||
31 | * from | ||
32 | * | ||
33 | * linux/fs/minix/namei.c | ||
34 | * | ||
35 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
36 | * | ||
37 | * Big-endian to little-endian byte-swapping/bitmaps by | ||
38 | * David S. Miller (davem@caip.rutgers.edu), 1995 | ||
39 | */ | ||
40 | |||
41 | #include <linux/pagemap.h> | ||
42 | #include "nilfs.h" | ||
43 | |||
44 | |||
45 | static inline int nilfs_add_nondir(struct dentry *dentry, struct inode *inode) | ||
46 | { | ||
47 | int err = nilfs_add_link(dentry, inode); | ||
48 | if (!err) { | ||
49 | d_instantiate(dentry, inode); | ||
50 | return 0; | ||
51 | } | ||
52 | inode_dec_link_count(inode); | ||
53 | iput(inode); | ||
54 | return err; | ||
55 | } | ||
56 | |||
57 | /* | ||
58 | * Methods themselves. | ||
59 | */ | ||
60 | |||
61 | static struct dentry * | ||
62 | nilfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | ||
63 | { | ||
64 | struct inode *inode; | ||
65 | ino_t ino; | ||
66 | |||
67 | if (dentry->d_name.len > NILFS_NAME_LEN) | ||
68 | return ERR_PTR(-ENAMETOOLONG); | ||
69 | |||
70 | ino = nilfs_inode_by_name(dir, dentry); | ||
71 | inode = NULL; | ||
72 | if (ino) { | ||
73 | inode = nilfs_iget(dir->i_sb, ino); | ||
74 | if (IS_ERR(inode)) | ||
75 | return ERR_CAST(inode); | ||
76 | } | ||
77 | return d_splice_alias(inode, dentry); | ||
78 | } | ||
79 | |||
80 | struct dentry *nilfs_get_parent(struct dentry *child) | ||
81 | { | ||
82 | unsigned long ino; | ||
83 | struct inode *inode; | ||
84 | struct dentry dotdot; | ||
85 | |||
86 | dotdot.d_name.name = ".."; | ||
87 | dotdot.d_name.len = 2; | ||
88 | |||
89 | ino = nilfs_inode_by_name(child->d_inode, &dotdot); | ||
90 | if (!ino) | ||
91 | return ERR_PTR(-ENOENT); | ||
92 | |||
93 | inode = nilfs_iget(child->d_inode->i_sb, ino); | ||
94 | if (IS_ERR(inode)) | ||
95 | return ERR_CAST(inode); | ||
96 | return d_obtain_alias(inode); | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * By the time this is called, we already have created | ||
101 | * the directory cache entry for the new file, but it | ||
102 | * is so far negative - it has no inode. | ||
103 | * | ||
104 | * If the create succeeds, we fill in the inode information | ||
105 | * with d_instantiate(). | ||
106 | */ | ||
107 | static int nilfs_create(struct inode *dir, struct dentry *dentry, int mode, | ||
108 | struct nameidata *nd) | ||
109 | { | ||
110 | struct inode *inode; | ||
111 | struct nilfs_transaction_info ti; | ||
112 | int err; | ||
113 | |||
114 | err = nilfs_transaction_begin(dir->i_sb, &ti, 1); | ||
115 | if (err) | ||
116 | return err; | ||
117 | inode = nilfs_new_inode(dir, mode); | ||
118 | err = PTR_ERR(inode); | ||
119 | if (!IS_ERR(inode)) { | ||
120 | inode->i_op = &nilfs_file_inode_operations; | ||
121 | inode->i_fop = &nilfs_file_operations; | ||
122 | inode->i_mapping->a_ops = &nilfs_aops; | ||
123 | mark_inode_dirty(inode); | ||
124 | err = nilfs_add_nondir(dentry, inode); | ||
125 | } | ||
126 | if (!err) | ||
127 | err = nilfs_transaction_commit(dir->i_sb); | ||
128 | else | ||
129 | nilfs_transaction_abort(dir->i_sb); | ||
130 | |||
131 | return err; | ||
132 | } | ||
133 | |||
134 | static int | ||
135 | nilfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | ||
136 | { | ||
137 | struct inode *inode; | ||
138 | struct nilfs_transaction_info ti; | ||
139 | int err; | ||
140 | |||
141 | if (!new_valid_dev(rdev)) | ||
142 | return -EINVAL; | ||
143 | |||
144 | err = nilfs_transaction_begin(dir->i_sb, &ti, 1); | ||
145 | if (err) | ||
146 | return err; | ||
147 | inode = nilfs_new_inode(dir, mode); | ||
148 | err = PTR_ERR(inode); | ||
149 | if (!IS_ERR(inode)) { | ||
150 | init_special_inode(inode, inode->i_mode, rdev); | ||
151 | mark_inode_dirty(inode); | ||
152 | err = nilfs_add_nondir(dentry, inode); | ||
153 | } | ||
154 | if (!err) | ||
155 | err = nilfs_transaction_commit(dir->i_sb); | ||
156 | else | ||
157 | nilfs_transaction_abort(dir->i_sb); | ||
158 | |||
159 | return err; | ||
160 | } | ||
161 | |||
162 | static int nilfs_symlink(struct inode *dir, struct dentry *dentry, | ||
163 | const char *symname) | ||
164 | { | ||
165 | struct nilfs_transaction_info ti; | ||
166 | struct super_block *sb = dir->i_sb; | ||
167 | unsigned l = strlen(symname)+1; | ||
168 | struct inode *inode; | ||
169 | int err; | ||
170 | |||
171 | if (l > sb->s_blocksize) | ||
172 | return -ENAMETOOLONG; | ||
173 | |||
174 | err = nilfs_transaction_begin(dir->i_sb, &ti, 1); | ||
175 | if (err) | ||
176 | return err; | ||
177 | |||
178 | inode = nilfs_new_inode(dir, S_IFLNK | S_IRWXUGO); | ||
179 | err = PTR_ERR(inode); | ||
180 | if (IS_ERR(inode)) | ||
181 | goto out; | ||
182 | |||
183 | /* slow symlink */ | ||
184 | inode->i_op = &nilfs_symlink_inode_operations; | ||
185 | inode->i_mapping->a_ops = &nilfs_aops; | ||
186 | err = page_symlink(inode, symname, l); | ||
187 | if (err) | ||
188 | goto out_fail; | ||
189 | |||
190 | /* mark_inode_dirty(inode); */ | ||
191 | /* nilfs_new_inode() and page_symlink() do this */ | ||
192 | |||
193 | err = nilfs_add_nondir(dentry, inode); | ||
194 | out: | ||
195 | if (!err) | ||
196 | err = nilfs_transaction_commit(dir->i_sb); | ||
197 | else | ||
198 | nilfs_transaction_abort(dir->i_sb); | ||
199 | |||
200 | return err; | ||
201 | |||
202 | out_fail: | ||
203 | inode_dec_link_count(inode); | ||
204 | iput(inode); | ||
205 | goto out; | ||
206 | } | ||
207 | |||
208 | static int nilfs_link(struct dentry *old_dentry, struct inode *dir, | ||
209 | struct dentry *dentry) | ||
210 | { | ||
211 | struct inode *inode = old_dentry->d_inode; | ||
212 | struct nilfs_transaction_info ti; | ||
213 | int err; | ||
214 | |||
215 | if (inode->i_nlink >= NILFS_LINK_MAX) | ||
216 | return -EMLINK; | ||
217 | |||
218 | err = nilfs_transaction_begin(dir->i_sb, &ti, 1); | ||
219 | if (err) | ||
220 | return err; | ||
221 | |||
222 | inode->i_ctime = CURRENT_TIME; | ||
223 | inode_inc_link_count(inode); | ||
224 | atomic_inc(&inode->i_count); | ||
225 | |||
226 | err = nilfs_add_nondir(dentry, inode); | ||
227 | if (!err) | ||
228 | err = nilfs_transaction_commit(dir->i_sb); | ||
229 | else | ||
230 | nilfs_transaction_abort(dir->i_sb); | ||
231 | |||
232 | return err; | ||
233 | } | ||
234 | |||
235 | static int nilfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | ||
236 | { | ||
237 | struct inode *inode; | ||
238 | struct nilfs_transaction_info ti; | ||
239 | int err; | ||
240 | |||
241 | if (dir->i_nlink >= NILFS_LINK_MAX) | ||
242 | return -EMLINK; | ||
243 | |||
244 | err = nilfs_transaction_begin(dir->i_sb, &ti, 1); | ||
245 | if (err) | ||
246 | return err; | ||
247 | |||
248 | inode_inc_link_count(dir); | ||
249 | |||
250 | inode = nilfs_new_inode(dir, S_IFDIR | mode); | ||
251 | err = PTR_ERR(inode); | ||
252 | if (IS_ERR(inode)) | ||
253 | goto out_dir; | ||
254 | |||
255 | inode->i_op = &nilfs_dir_inode_operations; | ||
256 | inode->i_fop = &nilfs_dir_operations; | ||
257 | inode->i_mapping->a_ops = &nilfs_aops; | ||
258 | |||
259 | inode_inc_link_count(inode); | ||
260 | |||
261 | err = nilfs_make_empty(inode, dir); | ||
262 | if (err) | ||
263 | goto out_fail; | ||
264 | |||
265 | err = nilfs_add_link(dentry, inode); | ||
266 | if (err) | ||
267 | goto out_fail; | ||
268 | |||
269 | d_instantiate(dentry, inode); | ||
270 | out: | ||
271 | if (!err) | ||
272 | err = nilfs_transaction_commit(dir->i_sb); | ||
273 | else | ||
274 | nilfs_transaction_abort(dir->i_sb); | ||
275 | |||
276 | return err; | ||
277 | |||
278 | out_fail: | ||
279 | inode_dec_link_count(inode); | ||
280 | inode_dec_link_count(inode); | ||
281 | iput(inode); | ||
282 | out_dir: | ||
283 | inode_dec_link_count(dir); | ||
284 | goto out; | ||
285 | } | ||
286 | |||
287 | static int nilfs_unlink(struct inode *dir, struct dentry *dentry) | ||
288 | { | ||
289 | struct inode *inode; | ||
290 | struct nilfs_dir_entry *de; | ||
291 | struct page *page; | ||
292 | struct nilfs_transaction_info ti; | ||
293 | int err; | ||
294 | |||
295 | err = nilfs_transaction_begin(dir->i_sb, &ti, 0); | ||
296 | if (err) | ||
297 | return err; | ||
298 | |||
299 | err = -ENOENT; | ||
300 | de = nilfs_find_entry(dir, dentry, &page); | ||
301 | if (!de) | ||
302 | goto out; | ||
303 | |||
304 | inode = dentry->d_inode; | ||
305 | err = -EIO; | ||
306 | if (le64_to_cpu(de->inode) != inode->i_ino) | ||
307 | goto out; | ||
308 | |||
309 | if (!inode->i_nlink) { | ||
310 | nilfs_warning(inode->i_sb, __func__, | ||
311 | "deleting nonexistent file (%lu), %d\n", | ||
312 | inode->i_ino, inode->i_nlink); | ||
313 | inode->i_nlink = 1; | ||
314 | } | ||
315 | err = nilfs_delete_entry(de, page); | ||
316 | if (err) | ||
317 | goto out; | ||
318 | |||
319 | inode->i_ctime = dir->i_ctime; | ||
320 | inode_dec_link_count(inode); | ||
321 | err = 0; | ||
322 | out: | ||
323 | if (!err) | ||
324 | err = nilfs_transaction_commit(dir->i_sb); | ||
325 | else | ||
326 | nilfs_transaction_abort(dir->i_sb); | ||
327 | |||
328 | return err; | ||
329 | } | ||
330 | |||
331 | static int nilfs_rmdir(struct inode *dir, struct dentry *dentry) | ||
332 | { | ||
333 | struct inode *inode = dentry->d_inode; | ||
334 | struct nilfs_transaction_info ti; | ||
335 | int err; | ||
336 | |||
337 | err = nilfs_transaction_begin(dir->i_sb, &ti, 0); | ||
338 | if (err) | ||
339 | return err; | ||
340 | |||
341 | err = -ENOTEMPTY; | ||
342 | if (nilfs_empty_dir(inode)) { | ||
343 | err = nilfs_unlink(dir, dentry); | ||
344 | if (!err) { | ||
345 | inode->i_size = 0; | ||
346 | inode_dec_link_count(inode); | ||
347 | inode_dec_link_count(dir); | ||
348 | } | ||
349 | } | ||
350 | if (!err) | ||
351 | err = nilfs_transaction_commit(dir->i_sb); | ||
352 | else | ||
353 | nilfs_transaction_abort(dir->i_sb); | ||
354 | |||
355 | return err; | ||
356 | } | ||
357 | |||
358 | static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry, | ||
359 | struct inode *new_dir, struct dentry *new_dentry) | ||
360 | { | ||
361 | struct inode *old_inode = old_dentry->d_inode; | ||
362 | struct inode *new_inode = new_dentry->d_inode; | ||
363 | struct page *dir_page = NULL; | ||
364 | struct nilfs_dir_entry *dir_de = NULL; | ||
365 | struct page *old_page; | ||
366 | struct nilfs_dir_entry *old_de; | ||
367 | struct nilfs_transaction_info ti; | ||
368 | int err; | ||
369 | |||
370 | err = nilfs_transaction_begin(old_dir->i_sb, &ti, 1); | ||
371 | if (unlikely(err)) | ||
372 | return err; | ||
373 | |||
374 | err = -ENOENT; | ||
375 | old_de = nilfs_find_entry(old_dir, old_dentry, &old_page); | ||
376 | if (!old_de) | ||
377 | goto out; | ||
378 | |||
379 | if (S_ISDIR(old_inode->i_mode)) { | ||
380 | err = -EIO; | ||
381 | dir_de = nilfs_dotdot(old_inode, &dir_page); | ||
382 | if (!dir_de) | ||
383 | goto out_old; | ||
384 | } | ||
385 | |||
386 | if (new_inode) { | ||
387 | struct page *new_page; | ||
388 | struct nilfs_dir_entry *new_de; | ||
389 | |||
390 | err = -ENOTEMPTY; | ||
391 | if (dir_de && !nilfs_empty_dir(new_inode)) | ||
392 | goto out_dir; | ||
393 | |||
394 | err = -ENOENT; | ||
395 | new_de = nilfs_find_entry(new_dir, new_dentry, &new_page); | ||
396 | if (!new_de) | ||
397 | goto out_dir; | ||
398 | inode_inc_link_count(old_inode); | ||
399 | nilfs_set_link(new_dir, new_de, new_page, old_inode); | ||
400 | new_inode->i_ctime = CURRENT_TIME; | ||
401 | if (dir_de) | ||
402 | drop_nlink(new_inode); | ||
403 | inode_dec_link_count(new_inode); | ||
404 | } else { | ||
405 | if (dir_de) { | ||
406 | err = -EMLINK; | ||
407 | if (new_dir->i_nlink >= NILFS_LINK_MAX) | ||
408 | goto out_dir; | ||
409 | } | ||
410 | inode_inc_link_count(old_inode); | ||
411 | err = nilfs_add_link(new_dentry, old_inode); | ||
412 | if (err) { | ||
413 | inode_dec_link_count(old_inode); | ||
414 | goto out_dir; | ||
415 | } | ||
416 | if (dir_de) | ||
417 | inode_inc_link_count(new_dir); | ||
418 | } | ||
419 | |||
420 | /* | ||
421 | * Like most other Unix systems, set the ctime for inodes on a | ||
422 | * rename. | ||
423 | * inode_dec_link_count() will mark the inode dirty. | ||
424 | */ | ||
425 | old_inode->i_ctime = CURRENT_TIME; | ||
426 | |||
427 | nilfs_delete_entry(old_de, old_page); | ||
428 | inode_dec_link_count(old_inode); | ||
429 | |||
430 | if (dir_de) { | ||
431 | nilfs_set_link(old_inode, dir_de, dir_page, new_dir); | ||
432 | inode_dec_link_count(old_dir); | ||
433 | } | ||
434 | |||
435 | err = nilfs_transaction_commit(old_dir->i_sb); | ||
436 | return err; | ||
437 | |||
438 | out_dir: | ||
439 | if (dir_de) { | ||
440 | kunmap(dir_page); | ||
441 | page_cache_release(dir_page); | ||
442 | } | ||
443 | out_old: | ||
444 | kunmap(old_page); | ||
445 | page_cache_release(old_page); | ||
446 | out: | ||
447 | nilfs_transaction_abort(old_dir->i_sb); | ||
448 | return err; | ||
449 | } | ||
450 | |||
451 | struct inode_operations nilfs_dir_inode_operations = { | ||
452 | .create = nilfs_create, | ||
453 | .lookup = nilfs_lookup, | ||
454 | .link = nilfs_link, | ||
455 | .unlink = nilfs_unlink, | ||
456 | .symlink = nilfs_symlink, | ||
457 | .mkdir = nilfs_mkdir, | ||
458 | .rmdir = nilfs_rmdir, | ||
459 | .mknod = nilfs_mknod, | ||
460 | .rename = nilfs_rename, | ||
461 | .setattr = nilfs_setattr, | ||
462 | .permission = nilfs_permission, | ||
463 | }; | ||
464 | |||
465 | struct inode_operations nilfs_special_inode_operations = { | ||
466 | .setattr = nilfs_setattr, | ||
467 | .permission = nilfs_permission, | ||
468 | }; | ||
469 | |||
470 | struct inode_operations nilfs_symlink_inode_operations = { | ||
471 | .readlink = generic_readlink, | ||
472 | .follow_link = page_follow_link_light, | ||
473 | .put_link = page_put_link, | ||
474 | }; | ||