📄 namei.c
字号:
NAME_NOT_FOUND) { reiserfs_warning(dir->i_sb, "vs-7032: reiserfs_add_entry: " "entry with this key (%K) already exists", &entry_key); if (buffer != small_buf) kfree(buffer); pathrelse(&path); return -EBUSY; } } /* perform the insertion of the entry that we have prepared */ retval = reiserfs_paste_into_item(th, &path, &entry_key, dir, buffer, paste_size); if (buffer != small_buf) kfree(buffer); if (retval) { reiserfs_check_path(&path); return retval; } dir->i_size += paste_size; dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; if (!S_ISDIR(inode->i_mode) && visible) // reiserfs_mkdir or reiserfs_rename will do that by itself reiserfs_update_sd(th, dir); reiserfs_check_path(&path); return 0;}/* quota utility function, call if you've had to abort after calling** new_inode_init, and have not called reiserfs_new_inode yet.** This should only be called on inodes that do not have stat data** inserted into the tree yet.*/static int drop_new_inode(struct inode *inode){ DQUOT_DROP(inode); make_bad_inode(inode); inode->i_flags |= S_NOQUOTA; iput(inode); return 0;}/* utility function that does setup for reiserfs_new_inode. ** DQUOT_INIT needs lots of credits so it's better to have it** outside of a transaction, so we had to pull some bits of** reiserfs_new_inode out into this func.*/static int new_inode_init(struct inode *inode, struct inode *dir, int mode){ /* the quota init calls have to know who to charge the quota to, so ** we have to set uid and gid here */ inode->i_uid = current->fsuid; inode->i_mode = mode; /* Make inode invalid - just in case we are going to drop it before * the initialization happens */ INODE_PKEY(inode)->k_objectid = 0; if (dir->i_mode & S_ISGID) { inode->i_gid = dir->i_gid; if (S_ISDIR(mode)) inode->i_mode |= S_ISGID; } else { inode->i_gid = current->fsgid; } DQUOT_INIT(inode); return 0;}static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd){ int retval; struct inode *inode; /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); struct reiserfs_transaction_handle th; int locked; if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM; } new_inode_init(inode, dir, mode); locked = reiserfs_cache_default_acl(dir); reiserfs_write_lock(dir->i_sb); if (locked) reiserfs_write_lock_xattrs(dir->i_sb); retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) { drop_new_inode(inode); goto out_failed; } retval = reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry, inode); if (retval) goto out_failed; if (locked) { reiserfs_write_unlock_xattrs(dir->i_sb); locked = 0; } inode->i_op = &reiserfs_file_inode_operations; inode->i_fop = &reiserfs_file_operations; inode->i_mapping->a_ops = &reiserfs_address_space_operations; retval = reiserfs_add_entry(&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1 /*visible */ ); if (retval) { int err; inode->i_nlink--; reiserfs_update_sd(&th, inode); err = journal_end(&th, dir->i_sb, jbegin_count); if (err) retval = err; iput(inode); goto out_failed; } reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); d_instantiate(dentry, inode); retval = journal_end(&th, dir->i_sb, jbegin_count); out_failed: if (locked) reiserfs_write_unlock_xattrs(dir->i_sb); reiserfs_write_unlock(dir->i_sb); return retval;}static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev){ int retval; struct inode *inode; struct reiserfs_transaction_handle th; /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); int locked; if (!new_valid_dev(rdev)) return -EINVAL; if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM; } new_inode_init(inode, dir, mode); locked = reiserfs_cache_default_acl(dir); reiserfs_write_lock(dir->i_sb); if (locked) reiserfs_write_lock_xattrs(dir->i_sb); retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) { drop_new_inode(inode); goto out_failed; } retval = reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry, inode); if (retval) { goto out_failed; } if (locked) { reiserfs_write_unlock_xattrs(dir->i_sb); locked = 0; } inode->i_op = &reiserfs_special_inode_operations; init_special_inode(inode, inode->i_mode, rdev); //FIXME: needed for block and char devices only reiserfs_update_sd(&th, inode); reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); retval = reiserfs_add_entry(&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1 /*visible */ ); if (retval) { int err; inode->i_nlink--; reiserfs_update_sd(&th, inode); err = journal_end(&th, dir->i_sb, jbegin_count); if (err) retval = err; iput(inode); goto out_failed; } d_instantiate(dentry, inode); retval = journal_end(&th, dir->i_sb, jbegin_count); out_failed: if (locked) reiserfs_write_unlock_xattrs(dir->i_sb); reiserfs_write_unlock(dir->i_sb); return retval;}static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode){ int retval; struct inode *inode; struct reiserfs_transaction_handle th; /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) + REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); int locked;#ifdef DISPLACE_NEW_PACKING_LOCALITIES /* set flag that new packing locality created and new blocks for the content * of that directory are not displaced yet */ REISERFS_I(dir)->new_packing_locality = 1;#endif mode = S_IFDIR | mode; if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM; } new_inode_init(inode, dir, mode); locked = reiserfs_cache_default_acl(dir); reiserfs_write_lock(dir->i_sb); if (locked) reiserfs_write_lock_xattrs(dir->i_sb); retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) { drop_new_inode(inode); goto out_failed; } /* inc the link count now, so another writer doesn't overflow it while ** we sleep later on. */ INC_DIR_INODE_NLINK(dir) retval = reiserfs_new_inode(&th, dir, mode, NULL /*symlink */ , old_format_only(dir->i_sb) ? EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE, dentry, inode); if (retval) { dir->i_nlink--; goto out_failed; } if (locked) { reiserfs_write_unlock_xattrs(dir->i_sb); locked = 0; } reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); inode->i_op = &reiserfs_dir_inode_operations; inode->i_fop = &reiserfs_dir_operations; // note, _this_ add_entry will not update dir's stat data retval = reiserfs_add_entry(&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1 /*visible */ ); if (retval) { int err; inode->i_nlink = 0; DEC_DIR_INODE_NLINK(dir); reiserfs_update_sd(&th, inode); err = journal_end(&th, dir->i_sb, jbegin_count); if (err) retval = err; iput(inode); goto out_failed; } // the above add_entry did not update dir's stat data reiserfs_update_sd(&th, dir); d_instantiate(dentry, inode); retval = journal_end(&th, dir->i_sb, jbegin_count); out_failed: if (locked) reiserfs_write_unlock_xattrs(dir->i_sb); reiserfs_write_unlock(dir->i_sb); return retval;}static inline int reiserfs_empty_dir(struct inode *inode){ /* we can cheat because an old format dir cannot have ** EMPTY_DIR_SIZE, and a new format dir cannot have ** EMPTY_DIR_SIZE_V1. So, if the inode is either size, ** regardless of disk format version, the directory is empty. */ if (inode->i_size != EMPTY_DIR_SIZE && inode->i_size != EMPTY_DIR_SIZE_V1) { return 0; } return 1;}static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry){ int retval, err; struct inode *inode; struct reiserfs_transaction_handle th; int jbegin_count; INITIALIZE_PATH(path); struct reiserfs_dir_entry de; /* we will be doing 2 balancings and update 2 stat data, we change quotas * of the owner of the directory and of the owner of the parent directory. * The quota structure is possibly deleted only on last iput => outside * of this transaction */ jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb); reiserfs_write_lock(dir->i_sb); retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) goto out_rmdir; de.de_gen_number_bit_string = NULL; if ((retval = reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &path, &de)) == NAME_NOT_FOUND) { retval = -ENOENT; goto end_rmdir; } else if (retval == IO_ERROR) { retval = -EIO; goto end_rmdir; } inode = dentry->d_inode; reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); if (de.de_objectid != inode->i_ino) { // FIXME: compare key of an object and a key found in the // entry retval = -EIO; goto end_rmdir; } if (!reiserfs_empty_dir(inode)) { retval = -ENOTEMPTY; goto end_rmdir; } /* cut entry from dir directory */ retval = reiserfs_cut_from_item(&th, &path, &(de.de_entry_key), dir, NULL, /* page */ 0 /*new file size - not used here */ ); if (retval < 0) goto end_rmdir; if (inode->i_nlink != 2 && inode->i_nlink != 1) reiserfs_warning(inode->i_sb, "%s: empty directory has nlink " "!= 2 (%d)", __FUNCTION__, inode->i_nlink); clear_nlink(inode); inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; reiserfs_update_sd(&th, inode); DEC_DIR_INODE_NLINK(dir) dir->i_size -= (DEH_SIZE + de.de_entrylen); reiserfs_update_sd(&th, dir); /* prevent empty directory from getting lost */ add_save_link(&th, inode, 0 /* not truncate */ ); retval = journal_end(&th, dir->i_sb, jbegin_count); reiserfs_check_path(&path); out_rmdir: reiserfs_write_unlock(dir->i_sb); return retval; end_rmdir: /* we must release path, because we did not call reiserfs_cut_from_item, or reiserfs_cut_from_item does not release path if operation was not complete */ pathrelse(&path); err = journal_end(&th, dir->i_sb, jbegin_count); reiserfs_write_unlock(dir->i_sb); return err ? err : retval;}static int reiserfs_unlink(struct inode *dir, struct dentry *dentry){ int retval, err; struct inode *inode; struct reiserfs_dir_entry de; INITIALIZE_PATH(path); struct reiserfs_transaction_handle th; int jbegin_count; unsigned long savelink; inode = dentry->d_inode; /* in this transaction we can be doing at max two balancings and update * two stat datas, we change quotas of the owner of the directory and of * the owner of the parent directory. The quota structure is possibly * deleted only on iput => outside of this transaction */ jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb); reiserfs_write_lock(dir->i_sb); retval = journal_begin(&th, dir->i_sb, jbegin_count); if (retval) goto out_unlink; de.de_gen_number_bit_string = NULL; if ((retval = reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &path, &de)) == NAME_NOT_FOUND) { retval = -ENOENT; goto end_unlink; } else if (retval == IO_ERROR) { retval = -EIO; goto end_unlink; } reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(dir); if (de.de_objectid != inode->i_ino) { // FIXME: compare key of an object and a key found in the // entry retval = -EIO; goto end_unlink; } if (!inode->i_nlink) { reiserfs_warning(inode->i_sb, "%s: deleting nonexistent file " "(%s:%lu), %d", __FUNCTION__, reiserfs_bdevname(inode->i_sb), inode->i_ino, inode->i_nlink); inode->i_nlink = 1; } drop_nlink(inode); /* * we schedule before doing the add_save_link call, save the link * count so we don't race */ savelink = inode->i_nlink; retval = reiserfs_cut_from_item(&th, &path, &(de.de_entry_key), dir, NULL, 0); if (retval < 0) { inc_nlink(inode); goto end_unlink; } inode->i_ctime = CURRENT_TIME_SEC; reiserfs_update_sd(&th, inode); dir->i_size -= (de.de_entrylen + DEH_SIZE); dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; reiserfs_update_sd(&th, dir); if (!savelink) /* prevent file from getting lost */ add_save_link(&th, inode, 0 /* not truncate */ ); retval = journal_end(&th, dir->i_sb, jbegin_count); reiserfs_check_path(&path); reiserfs_write_unlock(dir->i_sb); return retval; end_unlink: pathrelse(&path); err = journal_end(&th, dir->i_sb, jbegin_count); reiserfs_check_path(&path); if (err) retval = err; out_unlink: reiserfs_write_unlock(dir->i_sb); return retval;}static int reiserfs_symlink(struct inode *parent_dir, struct dentry *dentry, const char *symname){ int retval; struct inode *inode; char *name; int item_len; struct reiserfs_transaction_handle th; int mode = S_IFLNK | S_IRWXUGO; /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(parent_dir->i_sb) + REISERFS_QUOTA_TRANS_BLOCKS(parent_dir->i_sb)); if (!(inode = new_inode(parent_dir->i_sb))) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -