~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/nilfs2/namei.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0+
  2 /*
  3  * NILFS pathname lookup operations.
  4  *
  5  * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
  6  *
  7  * Modified for NILFS by Amagai Yoshiji and Ryusuke Konishi.
  8  */
  9 /*
 10  *  linux/fs/ext2/namei.c
 11  *
 12  * Copyright (C) 1992, 1993, 1994, 1995
 13  * Remy Card (card@masi.ibp.fr)
 14  * Laboratoire MASI - Institut Blaise Pascal
 15  * Universite Pierre et Marie Curie (Paris VI)
 16  *
 17  *  from
 18  *
 19  *  linux/fs/minix/namei.c
 20  *
 21  *  Copyright (C) 1991, 1992  Linus Torvalds
 22  *
 23  *  Big-endian to little-endian byte-swapping/bitmaps by
 24  *        David S. Miller (davem@caip.rutgers.edu), 1995
 25  */
 26 
 27 #include <linux/pagemap.h>
 28 #include "nilfs.h"
 29 #include "export.h"
 30 
 31 #define NILFS_FID_SIZE_NON_CONNECTABLE \
 32         (offsetof(struct nilfs_fid, parent_gen) / 4)
 33 #define NILFS_FID_SIZE_CONNECTABLE      (sizeof(struct nilfs_fid) / 4)
 34 
 35 static inline int nilfs_add_nondir(struct dentry *dentry, struct inode *inode)
 36 {
 37         int err = nilfs_add_link(dentry, inode);
 38 
 39         if (!err) {
 40                 d_instantiate_new(dentry, inode);
 41                 return 0;
 42         }
 43         inode_dec_link_count(inode);
 44         unlock_new_inode(inode);
 45         iput(inode);
 46         return err;
 47 }
 48 
 49 /*
 50  * Methods themselves.
 51  */
 52 
 53 static struct dentry *
 54 nilfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 55 {
 56         struct inode *inode;
 57         ino_t ino;
 58         int res;
 59 
 60         if (dentry->d_name.len > NILFS_NAME_LEN)
 61                 return ERR_PTR(-ENAMETOOLONG);
 62 
 63         res = nilfs_inode_by_name(dir, &dentry->d_name, &ino);
 64         if (res) {
 65                 if (res != -ENOENT)
 66                         return ERR_PTR(res);
 67                 inode = NULL;
 68         } else {
 69                 inode = nilfs_iget(dir->i_sb, NILFS_I(dir)->i_root, ino);
 70         }
 71 
 72         return d_splice_alias(inode, dentry);
 73 }
 74 
 75 /*
 76  * By the time this is called, we already have created
 77  * the directory cache entry for the new file, but it
 78  * is so far negative - it has no inode.
 79  *
 80  * If the create succeeds, we fill in the inode information
 81  * with d_instantiate().
 82  */
 83 static int nilfs_create(struct mnt_idmap *idmap, struct inode *dir,
 84                         struct dentry *dentry, umode_t mode, bool excl)
 85 {
 86         struct inode *inode;
 87         struct nilfs_transaction_info ti;
 88         int err;
 89 
 90         err = nilfs_transaction_begin(dir->i_sb, &ti, 1);
 91         if (err)
 92                 return err;
 93         inode = nilfs_new_inode(dir, mode);
 94         err = PTR_ERR(inode);
 95         if (!IS_ERR(inode)) {
 96                 inode->i_op = &nilfs_file_inode_operations;
 97                 inode->i_fop = &nilfs_file_operations;
 98                 inode->i_mapping->a_ops = &nilfs_aops;
 99                 nilfs_mark_inode_dirty(inode);
100                 err = nilfs_add_nondir(dentry, inode);
101         }
102         if (!err)
103                 err = nilfs_transaction_commit(dir->i_sb);
104         else
105                 nilfs_transaction_abort(dir->i_sb);
106 
107         return err;
108 }
109 
110 static int
111 nilfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
112             struct dentry *dentry, umode_t mode, dev_t rdev)
113 {
114         struct inode *inode;
115         struct nilfs_transaction_info ti;
116         int err;
117 
118         err = nilfs_transaction_begin(dir->i_sb, &ti, 1);
119         if (err)
120                 return err;
121         inode = nilfs_new_inode(dir, mode);
122         err = PTR_ERR(inode);
123         if (!IS_ERR(inode)) {
124                 init_special_inode(inode, inode->i_mode, rdev);
125                 nilfs_mark_inode_dirty(inode);
126                 err = nilfs_add_nondir(dentry, inode);
127         }
128         if (!err)
129                 err = nilfs_transaction_commit(dir->i_sb);
130         else
131                 nilfs_transaction_abort(dir->i_sb);
132 
133         return err;
134 }
135 
136 static int nilfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
137                          struct dentry *dentry, const char *symname)
138 {
139         struct nilfs_transaction_info ti;
140         struct super_block *sb = dir->i_sb;
141         unsigned int l = strlen(symname) + 1;
142         struct inode *inode;
143         int err;
144 
145         if (l > sb->s_blocksize)
146                 return -ENAMETOOLONG;
147 
148         err = nilfs_transaction_begin(dir->i_sb, &ti, 1);
149         if (err)
150                 return err;
151 
152         inode = nilfs_new_inode(dir, S_IFLNK | 0777);
153         err = PTR_ERR(inode);
154         if (IS_ERR(inode))
155                 goto out;
156 
157         /* slow symlink */
158         inode->i_op = &nilfs_symlink_inode_operations;
159         inode_nohighmem(inode);
160         inode->i_mapping->a_ops = &nilfs_aops;
161         err = page_symlink(inode, symname, l);
162         if (err)
163                 goto out_fail;
164 
165         /* mark_inode_dirty(inode); */
166         /* page_symlink() do this */
167 
168         err = nilfs_add_nondir(dentry, inode);
169 out:
170         if (!err)
171                 err = nilfs_transaction_commit(dir->i_sb);
172         else
173                 nilfs_transaction_abort(dir->i_sb);
174 
175         return err;
176 
177 out_fail:
178         drop_nlink(inode);
179         nilfs_mark_inode_dirty(inode);
180         unlock_new_inode(inode);
181         iput(inode);
182         goto out;
183 }
184 
185 static int nilfs_link(struct dentry *old_dentry, struct inode *dir,
186                       struct dentry *dentry)
187 {
188         struct inode *inode = d_inode(old_dentry);
189         struct nilfs_transaction_info ti;
190         int err;
191 
192         err = nilfs_transaction_begin(dir->i_sb, &ti, 1);
193         if (err)
194                 return err;
195 
196         inode_set_ctime_current(inode);
197         inode_inc_link_count(inode);
198         ihold(inode);
199 
200         err = nilfs_add_link(dentry, inode);
201         if (!err) {
202                 d_instantiate(dentry, inode);
203                 err = nilfs_transaction_commit(dir->i_sb);
204         } else {
205                 inode_dec_link_count(inode);
206                 iput(inode);
207                 nilfs_transaction_abort(dir->i_sb);
208         }
209 
210         return err;
211 }
212 
213 static int nilfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
214                        struct dentry *dentry, umode_t mode)
215 {
216         struct inode *inode;
217         struct nilfs_transaction_info ti;
218         int err;
219 
220         err = nilfs_transaction_begin(dir->i_sb, &ti, 1);
221         if (err)
222                 return err;
223 
224         inc_nlink(dir);
225 
226         inode = nilfs_new_inode(dir, S_IFDIR | mode);
227         err = PTR_ERR(inode);
228         if (IS_ERR(inode))
229                 goto out_dir;
230 
231         inode->i_op = &nilfs_dir_inode_operations;
232         inode->i_fop = &nilfs_dir_operations;
233         inode->i_mapping->a_ops = &nilfs_aops;
234 
235         inc_nlink(inode);
236 
237         err = nilfs_make_empty(inode, dir);
238         if (err)
239                 goto out_fail;
240 
241         err = nilfs_add_link(dentry, inode);
242         if (err)
243                 goto out_fail;
244 
245         nilfs_mark_inode_dirty(inode);
246         d_instantiate_new(dentry, inode);
247 out:
248         if (!err)
249                 err = nilfs_transaction_commit(dir->i_sb);
250         else
251                 nilfs_transaction_abort(dir->i_sb);
252 
253         return err;
254 
255 out_fail:
256         drop_nlink(inode);
257         drop_nlink(inode);
258         nilfs_mark_inode_dirty(inode);
259         unlock_new_inode(inode);
260         iput(inode);
261 out_dir:
262         drop_nlink(dir);
263         nilfs_mark_inode_dirty(dir);
264         goto out;
265 }
266 
267 static int nilfs_do_unlink(struct inode *dir, struct dentry *dentry)
268 {
269         struct inode *inode;
270         struct nilfs_dir_entry *de;
271         struct folio *folio;
272         int err;
273 
274         de = nilfs_find_entry(dir, &dentry->d_name, &folio);
275         if (IS_ERR(de)) {
276                 err = PTR_ERR(de);
277                 goto out;
278         }
279 
280         inode = d_inode(dentry);
281         err = -EIO;
282         if (le64_to_cpu(de->inode) != inode->i_ino)
283                 goto out;
284 
285         if (!inode->i_nlink) {
286                 nilfs_warn(inode->i_sb,
287                            "deleting nonexistent file (ino=%lu), %d",
288                            inode->i_ino, inode->i_nlink);
289                 set_nlink(inode, 1);
290         }
291         err = nilfs_delete_entry(de, folio);
292         folio_release_kmap(folio, de);
293         if (err)
294                 goto out;
295 
296         inode_set_ctime_to_ts(inode, inode_get_ctime(dir));
297         drop_nlink(inode);
298         err = 0;
299 out:
300         return err;
301 }
302 
303 static int nilfs_unlink(struct inode *dir, struct dentry *dentry)
304 {
305         struct nilfs_transaction_info ti;
306         int err;
307 
308         err = nilfs_transaction_begin(dir->i_sb, &ti, 0);
309         if (err)
310                 return err;
311 
312         err = nilfs_do_unlink(dir, dentry);
313 
314         if (!err) {
315                 nilfs_mark_inode_dirty(dir);
316                 nilfs_mark_inode_dirty(d_inode(dentry));
317                 err = nilfs_transaction_commit(dir->i_sb);
318         } else
319                 nilfs_transaction_abort(dir->i_sb);
320 
321         return err;
322 }
323 
324 static int nilfs_rmdir(struct inode *dir, struct dentry *dentry)
325 {
326         struct inode *inode = d_inode(dentry);
327         struct nilfs_transaction_info ti;
328         int err;
329 
330         err = nilfs_transaction_begin(dir->i_sb, &ti, 0);
331         if (err)
332                 return err;
333 
334         err = -ENOTEMPTY;
335         if (nilfs_empty_dir(inode)) {
336                 err = nilfs_do_unlink(dir, dentry);
337                 if (!err) {
338                         inode->i_size = 0;
339                         drop_nlink(inode);
340                         nilfs_mark_inode_dirty(inode);
341                         drop_nlink(dir);
342                         nilfs_mark_inode_dirty(dir);
343                 }
344         }
345         if (!err)
346                 err = nilfs_transaction_commit(dir->i_sb);
347         else
348                 nilfs_transaction_abort(dir->i_sb);
349 
350         return err;
351 }
352 
353 static int nilfs_rename(struct mnt_idmap *idmap,
354                         struct inode *old_dir, struct dentry *old_dentry,
355                         struct inode *new_dir, struct dentry *new_dentry,
356                         unsigned int flags)
357 {
358         struct inode *old_inode = d_inode(old_dentry);
359         struct inode *new_inode = d_inode(new_dentry);
360         struct folio *dir_folio = NULL;
361         struct nilfs_dir_entry *dir_de = NULL;
362         struct folio *old_folio;
363         struct nilfs_dir_entry *old_de;
364         struct nilfs_transaction_info ti;
365         int err;
366 
367         if (flags & ~RENAME_NOREPLACE)
368                 return -EINVAL;
369 
370         err = nilfs_transaction_begin(old_dir->i_sb, &ti, 1);
371         if (unlikely(err))
372                 return err;
373 
374         old_de = nilfs_find_entry(old_dir, &old_dentry->d_name, &old_folio);
375         if (IS_ERR(old_de)) {
376                 err = PTR_ERR(old_de);
377                 goto out;
378         }
379 
380         if (S_ISDIR(old_inode->i_mode)) {
381                 err = -EIO;
382                 dir_de = nilfs_dotdot(old_inode, &dir_folio);
383                 if (!dir_de)
384                         goto out_old;
385         }
386 
387         if (new_inode) {
388                 struct folio *new_folio;
389                 struct nilfs_dir_entry *new_de;
390 
391                 err = -ENOTEMPTY;
392                 if (dir_de && !nilfs_empty_dir(new_inode))
393                         goto out_dir;
394 
395                 new_de = nilfs_find_entry(new_dir, &new_dentry->d_name,
396                                           &new_folio);
397                 if (IS_ERR(new_de)) {
398                         err = PTR_ERR(new_de);
399                         goto out_dir;
400                 }
401                 nilfs_set_link(new_dir, new_de, new_folio, old_inode);
402                 folio_release_kmap(new_folio, new_de);
403                 nilfs_mark_inode_dirty(new_dir);
404                 inode_set_ctime_current(new_inode);
405                 if (dir_de)
406                         drop_nlink(new_inode);
407                 drop_nlink(new_inode);
408                 nilfs_mark_inode_dirty(new_inode);
409         } else {
410                 err = nilfs_add_link(new_dentry, old_inode);
411                 if (err)
412                         goto out_dir;
413                 if (dir_de) {
414                         inc_nlink(new_dir);
415                         nilfs_mark_inode_dirty(new_dir);
416                 }
417         }
418 
419         /*
420          * Like most other Unix systems, set the ctime for inodes on a
421          * rename.
422          */
423         inode_set_ctime_current(old_inode);
424 
425         nilfs_delete_entry(old_de, old_folio);
426 
427         if (dir_de) {
428                 nilfs_set_link(old_inode, dir_de, dir_folio, new_dir);
429                 folio_release_kmap(dir_folio, dir_de);
430                 drop_nlink(old_dir);
431         }
432         folio_release_kmap(old_folio, old_de);
433 
434         nilfs_mark_inode_dirty(old_dir);
435         nilfs_mark_inode_dirty(old_inode);
436 
437         err = nilfs_transaction_commit(old_dir->i_sb);
438         return err;
439 
440 out_dir:
441         if (dir_de)
442                 folio_release_kmap(dir_folio, dir_de);
443 out_old:
444         folio_release_kmap(old_folio, old_de);
445 out:
446         nilfs_transaction_abort(old_dir->i_sb);
447         return err;
448 }
449 
450 /*
451  * Export operations
452  */
453 static struct dentry *nilfs_get_parent(struct dentry *child)
454 {
455         ino_t ino;
456         int res;
457         struct nilfs_root *root;
458 
459         res = nilfs_inode_by_name(d_inode(child), &dotdot_name, &ino);
460         if (res)
461                 return ERR_PTR(res);
462 
463         root = NILFS_I(d_inode(child))->i_root;
464 
465         return d_obtain_alias(nilfs_iget(child->d_sb, root, ino));
466 }
467 
468 static struct dentry *nilfs_get_dentry(struct super_block *sb, u64 cno,
469                                        u64 ino, u32 gen)
470 {
471         struct nilfs_root *root;
472         struct inode *inode;
473 
474         if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO)
475                 return ERR_PTR(-ESTALE);
476 
477         root = nilfs_lookup_root(sb->s_fs_info, cno);
478         if (!root)
479                 return ERR_PTR(-ESTALE);
480 
481         inode = nilfs_iget(sb, root, ino);
482         nilfs_put_root(root);
483 
484         if (IS_ERR(inode))
485                 return ERR_CAST(inode);
486         if (gen && inode->i_generation != gen) {
487                 iput(inode);
488                 return ERR_PTR(-ESTALE);
489         }
490         return d_obtain_alias(inode);
491 }
492 
493 static struct dentry *nilfs_fh_to_dentry(struct super_block *sb, struct fid *fh,
494                                          int fh_len, int fh_type)
495 {
496         struct nilfs_fid *fid = (struct nilfs_fid *)fh;
497 
498         if (fh_len < NILFS_FID_SIZE_NON_CONNECTABLE ||
499             (fh_type != FILEID_NILFS_WITH_PARENT &&
500              fh_type != FILEID_NILFS_WITHOUT_PARENT))
501                 return NULL;
502 
503         return nilfs_get_dentry(sb, fid->cno, fid->ino, fid->gen);
504 }
505 
506 static struct dentry *nilfs_fh_to_parent(struct super_block *sb, struct fid *fh,
507                                          int fh_len, int fh_type)
508 {
509         struct nilfs_fid *fid = (struct nilfs_fid *)fh;
510 
511         if (fh_len < NILFS_FID_SIZE_CONNECTABLE ||
512             fh_type != FILEID_NILFS_WITH_PARENT)
513                 return NULL;
514 
515         return nilfs_get_dentry(sb, fid->cno, fid->parent_ino, fid->parent_gen);
516 }
517 
518 static int nilfs_encode_fh(struct inode *inode, __u32 *fh, int *lenp,
519                            struct inode *parent)
520 {
521         struct nilfs_fid *fid = (struct nilfs_fid *)fh;
522         struct nilfs_root *root = NILFS_I(inode)->i_root;
523         int type;
524 
525         if (parent && *lenp < NILFS_FID_SIZE_CONNECTABLE) {
526                 *lenp = NILFS_FID_SIZE_CONNECTABLE;
527                 return FILEID_INVALID;
528         }
529         if (*lenp < NILFS_FID_SIZE_NON_CONNECTABLE) {
530                 *lenp = NILFS_FID_SIZE_NON_CONNECTABLE;
531                 return FILEID_INVALID;
532         }
533 
534         fid->cno = root->cno;
535         fid->ino = inode->i_ino;
536         fid->gen = inode->i_generation;
537 
538         if (parent) {
539                 fid->parent_ino = parent->i_ino;
540                 fid->parent_gen = parent->i_generation;
541                 type = FILEID_NILFS_WITH_PARENT;
542                 *lenp = NILFS_FID_SIZE_CONNECTABLE;
543         } else {
544                 type = FILEID_NILFS_WITHOUT_PARENT;
545                 *lenp = NILFS_FID_SIZE_NON_CONNECTABLE;
546         }
547 
548         return type;
549 }
550 
551 const struct inode_operations nilfs_dir_inode_operations = {
552         .create         = nilfs_create,
553         .lookup         = nilfs_lookup,
554         .link           = nilfs_link,
555         .unlink         = nilfs_unlink,
556         .symlink        = nilfs_symlink,
557         .mkdir          = nilfs_mkdir,
558         .rmdir          = nilfs_rmdir,
559         .mknod          = nilfs_mknod,
560         .rename         = nilfs_rename,
561         .setattr        = nilfs_setattr,
562         .permission     = nilfs_permission,
563         .fiemap         = nilfs_fiemap,
564         .fileattr_get   = nilfs_fileattr_get,
565         .fileattr_set   = nilfs_fileattr_set,
566 };
567 
568 const struct inode_operations nilfs_special_inode_operations = {
569         .setattr        = nilfs_setattr,
570         .permission     = nilfs_permission,
571 };
572 
573 const struct inode_operations nilfs_symlink_inode_operations = {
574         .get_link       = page_get_link,
575         .permission     = nilfs_permission,
576 };
577 
578 const struct export_operations nilfs_export_ops = {
579         .encode_fh = nilfs_encode_fh,
580         .fh_to_dentry = nilfs_fh_to_dentry,
581         .fh_to_parent = nilfs_fh_to_parent,
582         .get_parent = nilfs_get_parent,
583 };
584 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php