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

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

Version: ~ [ linux-5.16 ] ~ [ linux-5.15.13 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.90 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.170 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.224 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.261 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.296 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.298 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ 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.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp