587 lines · c
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.c11 *12 * Copyright (C) 1992, 1993, 1994, 199513 * Remy Card (card@masi.ibp.fr)14 * Laboratoire MASI - Institut Blaise Pascal15 * Universite Pierre et Marie Curie (Paris VI)16 *17 * from18 *19 * linux/fs/minix/namei.c20 *21 * Copyright (C) 1991, 1992 Linus Torvalds22 *23 * Big-endian to little-endian byte-swapping/bitmaps by24 * David S. Miller (davem@caip.rutgers.edu), 199525 */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 35static 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 53static struct dentry *54nilfs_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 created77 * the directory cache entry for the new file, but it78 * is so far negative - it has no inode.79 *80 * If the create succeeds, we fill in the inode information81 * with d_instantiate().82 */83static 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 else105 nilfs_transaction_abort(dir->i_sb);106 107 return err;108}109 110static int111nilfs_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 else131 nilfs_transaction_abort(dir->i_sb);132 133 return err;134}135 136static 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 mapping_set_gfp_mask(inode->i_mapping,161 mapping_gfp_constraint(inode->i_mapping,162 ~__GFP_FS));163 inode->i_mapping->a_ops = &nilfs_aops;164 err = page_symlink(inode, symname, l);165 if (err)166 goto out_fail;167 168 /* mark_inode_dirty(inode); */169 /* page_symlink() do this */170 171 err = nilfs_add_nondir(dentry, inode);172out:173 if (!err)174 err = nilfs_transaction_commit(dir->i_sb);175 else176 nilfs_transaction_abort(dir->i_sb);177 178 return err;179 180out_fail:181 drop_nlink(inode);182 nilfs_mark_inode_dirty(inode);183 unlock_new_inode(inode);184 iput(inode);185 goto out;186}187 188static int nilfs_link(struct dentry *old_dentry, struct inode *dir,189 struct dentry *dentry)190{191 struct inode *inode = d_inode(old_dentry);192 struct nilfs_transaction_info ti;193 int err;194 195 err = nilfs_transaction_begin(dir->i_sb, &ti, 1);196 if (err)197 return err;198 199 inode_set_ctime_current(inode);200 inode_inc_link_count(inode);201 ihold(inode);202 203 err = nilfs_add_link(dentry, inode);204 if (!err) {205 d_instantiate(dentry, inode);206 err = nilfs_transaction_commit(dir->i_sb);207 } else {208 inode_dec_link_count(inode);209 iput(inode);210 nilfs_transaction_abort(dir->i_sb);211 }212 213 return err;214}215 216static int nilfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,217 struct dentry *dentry, umode_t mode)218{219 struct inode *inode;220 struct nilfs_transaction_info ti;221 int err;222 223 err = nilfs_transaction_begin(dir->i_sb, &ti, 1);224 if (err)225 return err;226 227 inc_nlink(dir);228 229 inode = nilfs_new_inode(dir, S_IFDIR | mode);230 err = PTR_ERR(inode);231 if (IS_ERR(inode))232 goto out_dir;233 234 inode->i_op = &nilfs_dir_inode_operations;235 inode->i_fop = &nilfs_dir_operations;236 inode->i_mapping->a_ops = &nilfs_aops;237 238 inc_nlink(inode);239 240 err = nilfs_make_empty(inode, dir);241 if (err)242 goto out_fail;243 244 err = nilfs_add_link(dentry, inode);245 if (err)246 goto out_fail;247 248 nilfs_mark_inode_dirty(inode);249 d_instantiate_new(dentry, inode);250out:251 if (!err)252 err = nilfs_transaction_commit(dir->i_sb);253 else254 nilfs_transaction_abort(dir->i_sb);255 256 return err;257 258out_fail:259 drop_nlink(inode);260 drop_nlink(inode);261 nilfs_mark_inode_dirty(inode);262 unlock_new_inode(inode);263 iput(inode);264out_dir:265 drop_nlink(dir);266 nilfs_mark_inode_dirty(dir);267 goto out;268}269 270static int nilfs_do_unlink(struct inode *dir, struct dentry *dentry)271{272 struct inode *inode;273 struct nilfs_dir_entry *de;274 struct folio *folio;275 int err;276 277 de = nilfs_find_entry(dir, &dentry->d_name, &folio);278 if (IS_ERR(de)) {279 err = PTR_ERR(de);280 goto out;281 }282 283 inode = d_inode(dentry);284 err = -EIO;285 if (le64_to_cpu(de->inode) != inode->i_ino)286 goto out;287 288 if (!inode->i_nlink) {289 nilfs_warn(inode->i_sb,290 "deleting nonexistent file (ino=%lu), %d",291 inode->i_ino, inode->i_nlink);292 set_nlink(inode, 1);293 }294 err = nilfs_delete_entry(de, folio);295 folio_release_kmap(folio, de);296 if (err)297 goto out;298 299 inode_set_ctime_to_ts(inode, inode_get_ctime(dir));300 drop_nlink(inode);301 err = 0;302out:303 return err;304}305 306static int nilfs_unlink(struct inode *dir, struct dentry *dentry)307{308 struct nilfs_transaction_info ti;309 int err;310 311 err = nilfs_transaction_begin(dir->i_sb, &ti, 0);312 if (err)313 return err;314 315 err = nilfs_do_unlink(dir, dentry);316 317 if (!err) {318 nilfs_mark_inode_dirty(dir);319 nilfs_mark_inode_dirty(d_inode(dentry));320 err = nilfs_transaction_commit(dir->i_sb);321 } else322 nilfs_transaction_abort(dir->i_sb);323 324 return err;325}326 327static int nilfs_rmdir(struct inode *dir, struct dentry *dentry)328{329 struct inode *inode = d_inode(dentry);330 struct nilfs_transaction_info ti;331 int err;332 333 err = nilfs_transaction_begin(dir->i_sb, &ti, 0);334 if (err)335 return err;336 337 err = -ENOTEMPTY;338 if (nilfs_empty_dir(inode)) {339 err = nilfs_do_unlink(dir, dentry);340 if (!err) {341 inode->i_size = 0;342 drop_nlink(inode);343 nilfs_mark_inode_dirty(inode);344 drop_nlink(dir);345 nilfs_mark_inode_dirty(dir);346 }347 }348 if (!err)349 err = nilfs_transaction_commit(dir->i_sb);350 else351 nilfs_transaction_abort(dir->i_sb);352 353 return err;354}355 356static int nilfs_rename(struct mnt_idmap *idmap,357 struct inode *old_dir, struct dentry *old_dentry,358 struct inode *new_dir, struct dentry *new_dentry,359 unsigned int flags)360{361 struct inode *old_inode = d_inode(old_dentry);362 struct inode *new_inode = d_inode(new_dentry);363 struct folio *dir_folio = NULL;364 struct nilfs_dir_entry *dir_de = NULL;365 struct folio *old_folio;366 struct nilfs_dir_entry *old_de;367 struct nilfs_transaction_info ti;368 int err;369 370 if (flags & ~RENAME_NOREPLACE)371 return -EINVAL;372 373 err = nilfs_transaction_begin(old_dir->i_sb, &ti, 1);374 if (unlikely(err))375 return err;376 377 old_de = nilfs_find_entry(old_dir, &old_dentry->d_name, &old_folio);378 if (IS_ERR(old_de)) {379 err = PTR_ERR(old_de);380 goto out;381 }382 383 if (S_ISDIR(old_inode->i_mode)) {384 err = -EIO;385 dir_de = nilfs_dotdot(old_inode, &dir_folio);386 if (!dir_de)387 goto out_old;388 }389 390 if (new_inode) {391 struct folio *new_folio;392 struct nilfs_dir_entry *new_de;393 394 err = -ENOTEMPTY;395 if (dir_de && !nilfs_empty_dir(new_inode))396 goto out_dir;397 398 new_de = nilfs_find_entry(new_dir, &new_dentry->d_name,399 &new_folio);400 if (IS_ERR(new_de)) {401 err = PTR_ERR(new_de);402 goto out_dir;403 }404 nilfs_set_link(new_dir, new_de, new_folio, old_inode);405 folio_release_kmap(new_folio, new_de);406 nilfs_mark_inode_dirty(new_dir);407 inode_set_ctime_current(new_inode);408 if (dir_de)409 drop_nlink(new_inode);410 drop_nlink(new_inode);411 nilfs_mark_inode_dirty(new_inode);412 } else {413 err = nilfs_add_link(new_dentry, old_inode);414 if (err)415 goto out_dir;416 if (dir_de) {417 inc_nlink(new_dir);418 nilfs_mark_inode_dirty(new_dir);419 }420 }421 422 /*423 * Like most other Unix systems, set the ctime for inodes on a424 * rename.425 */426 inode_set_ctime_current(old_inode);427 428 nilfs_delete_entry(old_de, old_folio);429 430 if (dir_de) {431 nilfs_set_link(old_inode, dir_de, dir_folio, new_dir);432 folio_release_kmap(dir_folio, dir_de);433 drop_nlink(old_dir);434 }435 folio_release_kmap(old_folio, old_de);436 437 nilfs_mark_inode_dirty(old_dir);438 nilfs_mark_inode_dirty(old_inode);439 440 err = nilfs_transaction_commit(old_dir->i_sb);441 return err;442 443out_dir:444 if (dir_de)445 folio_release_kmap(dir_folio, dir_de);446out_old:447 folio_release_kmap(old_folio, old_de);448out:449 nilfs_transaction_abort(old_dir->i_sb);450 return err;451}452 453/*454 * Export operations455 */456static struct dentry *nilfs_get_parent(struct dentry *child)457{458 ino_t ino;459 int res;460 struct nilfs_root *root;461 462 res = nilfs_inode_by_name(d_inode(child), &dotdot_name, &ino);463 if (res)464 return ERR_PTR(res);465 466 root = NILFS_I(d_inode(child))->i_root;467 468 return d_obtain_alias(nilfs_iget(child->d_sb, root, ino));469}470 471static struct dentry *nilfs_get_dentry(struct super_block *sb, u64 cno,472 u64 ino, u32 gen)473{474 struct nilfs_root *root;475 struct inode *inode;476 477 if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO)478 return ERR_PTR(-ESTALE);479 480 root = nilfs_lookup_root(sb->s_fs_info, cno);481 if (!root)482 return ERR_PTR(-ESTALE);483 484 inode = nilfs_iget(sb, root, ino);485 nilfs_put_root(root);486 487 if (IS_ERR(inode))488 return ERR_CAST(inode);489 if (gen && inode->i_generation != gen) {490 iput(inode);491 return ERR_PTR(-ESTALE);492 }493 return d_obtain_alias(inode);494}495 496static struct dentry *nilfs_fh_to_dentry(struct super_block *sb, struct fid *fh,497 int fh_len, int fh_type)498{499 struct nilfs_fid *fid = (struct nilfs_fid *)fh;500 501 if (fh_len < NILFS_FID_SIZE_NON_CONNECTABLE ||502 (fh_type != FILEID_NILFS_WITH_PARENT &&503 fh_type != FILEID_NILFS_WITHOUT_PARENT))504 return NULL;505 506 return nilfs_get_dentry(sb, fid->cno, fid->ino, fid->gen);507}508 509static struct dentry *nilfs_fh_to_parent(struct super_block *sb, struct fid *fh,510 int fh_len, int fh_type)511{512 struct nilfs_fid *fid = (struct nilfs_fid *)fh;513 514 if (fh_len < NILFS_FID_SIZE_CONNECTABLE ||515 fh_type != FILEID_NILFS_WITH_PARENT)516 return NULL;517 518 return nilfs_get_dentry(sb, fid->cno, fid->parent_ino, fid->parent_gen);519}520 521static int nilfs_encode_fh(struct inode *inode, __u32 *fh, int *lenp,522 struct inode *parent)523{524 struct nilfs_fid *fid = (struct nilfs_fid *)fh;525 struct nilfs_root *root = NILFS_I(inode)->i_root;526 int type;527 528 if (parent && *lenp < NILFS_FID_SIZE_CONNECTABLE) {529 *lenp = NILFS_FID_SIZE_CONNECTABLE;530 return FILEID_INVALID;531 }532 if (*lenp < NILFS_FID_SIZE_NON_CONNECTABLE) {533 *lenp = NILFS_FID_SIZE_NON_CONNECTABLE;534 return FILEID_INVALID;535 }536 537 fid->cno = root->cno;538 fid->ino = inode->i_ino;539 fid->gen = inode->i_generation;540 541 if (parent) {542 fid->parent_ino = parent->i_ino;543 fid->parent_gen = parent->i_generation;544 type = FILEID_NILFS_WITH_PARENT;545 *lenp = NILFS_FID_SIZE_CONNECTABLE;546 } else {547 type = FILEID_NILFS_WITHOUT_PARENT;548 *lenp = NILFS_FID_SIZE_NON_CONNECTABLE;549 }550 551 return type;552}553 554const struct inode_operations nilfs_dir_inode_operations = {555 .create = nilfs_create,556 .lookup = nilfs_lookup,557 .link = nilfs_link,558 .unlink = nilfs_unlink,559 .symlink = nilfs_symlink,560 .mkdir = nilfs_mkdir,561 .rmdir = nilfs_rmdir,562 .mknod = nilfs_mknod,563 .rename = nilfs_rename,564 .setattr = nilfs_setattr,565 .permission = nilfs_permission,566 .fiemap = nilfs_fiemap,567 .fileattr_get = nilfs_fileattr_get,568 .fileattr_set = nilfs_fileattr_set,569};570 571const struct inode_operations nilfs_special_inode_operations = {572 .setattr = nilfs_setattr,573 .permission = nilfs_permission,574};575 576const struct inode_operations nilfs_symlink_inode_operations = {577 .get_link = page_get_link,578 .permission = nilfs_permission,579};580 581const struct export_operations nilfs_export_ops = {582 .encode_fh = nilfs_encode_fh,583 .fh_to_dentry = nilfs_fh_to_dentry,584 .fh_to_parent = nilfs_fh_to_parent,585 .get_parent = nilfs_get_parent,586};587