📄 namei.c
字号:
/* find the proper place for the new entry */ memset (bit_string, 0, sizeof (bit_string)); de.de_gen_number_bit_string = (char *)bit_string; retval = reiserfs_find_entry (dir, name, namelen, &path, &de); if( retval != NAME_NOT_FOUND ) { if (buffer != small_buf) reiserfs_kfree (buffer, buflen, dir->i_sb); pathrelse (&path); if ( retval == IO_ERROR ) { return -EIO; } if (retval != NAME_FOUND) { reiserfs_warning (dir->i_sb, "zam-7002:%s: \"reiserfs_find_entry\" " "has returned unexpected value (%d)", __FUNCTION__, retval); } return -EEXIST; } gen_number = find_first_zero_bit ((unsigned long *)bit_string, MAX_GENERATION_NUMBER + 1); if (gen_number > MAX_GENERATION_NUMBER) { /* there is no free generation number */ reiserfs_warning (dir->i_sb, "reiserfs_add_entry: Congratulations! we have got hash function screwed up"); if (buffer != small_buf) reiserfs_kfree (buffer, buflen, dir->i_sb); pathrelse (&path); return -EBUSY; } /* adjust offset of directory enrty */ put_deh_offset(deh, SET_GENERATION_NUMBER(deh_offset(deh), gen_number)); set_cpu_key_k_offset (&entry_key, deh_offset(deh)); /* update max-hash-collisions counter in reiserfs_sb_info */ PROC_INFO_MAX( th -> t_super, max_hash_collisions, gen_number ); if (gen_number != 0) { /* we need to re-search for the insertion point */ if (search_by_entry_key (dir->i_sb, &entry_key, &path, &de) != 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) reiserfs_kfree (buffer, buflen, dir->i_sb); 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) reiserfs_kfree (buffer, buflen, dir->i_sb); if (retval) { reiserfs_check_path(&path) ; return retval; } dir->i_size += paste_size; dir->i_mtime = dir->i_ctime = CURRENT_TIME; 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 hav 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_ALLOC_INODE cannot be called inside a transaction, so we had** to pull some bits of reiserfs_new_inode out into this func.** Yes, the actual quota calls are missing, they are part of the quota** patch.*/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; 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); if (DQUOT_ALLOC_INODE(inode)) { drop_new_inode(inode); return -EDQUOT; } return 0 ;}static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode, struct nameidata *nd){ int retval; struct inode * inode; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 ; struct reiserfs_transaction_handle th ; int locked; if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM ; } retval = new_inode_init(inode, dir, mode); if (retval) return retval; locked = reiserfs_cache_default_acl (dir); reiserfs_write_lock(dir->i_sb); if (locked) reiserfs_write_lock_xattrs (dir->i_sb); journal_begin(&th, dir->i_sb, jbegin_count) ; retval = reiserfs_new_inode (&th, dir, mode, NULL, 0/*i_size*/, dentry, inode); if (locked) reiserfs_write_unlock_xattrs (dir->i_sb); if (retval) { goto out_failed; } 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) { inode->i_nlink--; reiserfs_update_sd (&th, inode); journal_end(&th, dir->i_sb, jbegin_count) ; iput (inode); goto out_failed; } reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(dir) ; d_instantiate(dentry, inode); journal_end(&th, dir->i_sb, jbegin_count) ;out_failed: 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 ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; int locked; if (!new_valid_dev(rdev)) return -EINVAL; if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM ; } retval = new_inode_init(inode, dir, mode); if (retval) return retval; locked = reiserfs_cache_default_acl (dir); reiserfs_write_lock(dir->i_sb); if (locked) reiserfs_write_lock_xattrs (dir->i_sb); journal_begin(&th, dir->i_sb, jbegin_count) ; retval = reiserfs_new_inode (&th, dir, mode, NULL, 0/*i_size*/, dentry, inode); if (locked) reiserfs_write_unlock_xattrs (dir->i_sb); if (retval) { goto out_failed; } 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) { inode->i_nlink--; reiserfs_update_sd (&th, inode); journal_end(&th, dir->i_sb, jbegin_count) ; iput (inode); goto out_failed; } d_instantiate(dentry, inode); journal_end(&th, dir->i_sb, jbegin_count) ;out_failed: 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 ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; 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 ; } retval = new_inode_init(inode, dir, mode); if (retval) return retval; locked = reiserfs_cache_default_acl (dir); reiserfs_write_lock(dir->i_sb); if (locked) reiserfs_write_lock_xattrs (dir->i_sb); journal_begin(&th, dir->i_sb, jbegin_count) ; /* 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 (locked) reiserfs_write_unlock_xattrs (dir->i_sb); if (retval) { dir->i_nlink-- ; goto out_failed; } 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) { inode->i_nlink = 0; DEC_DIR_INODE_NLINK(dir); reiserfs_update_sd (&th, inode); journal_end(&th, dir->i_sb, jbegin_count) ; 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); journal_end(&th, dir->i_sb, jbegin_count) ;out_failed: 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; 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 */ jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2; reiserfs_write_lock(dir->i_sb); journal_begin(&th, dir->i_sb, jbegin_count) ; 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); inode->i_nlink = 0; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; 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 */); journal_end(&th, dir->i_sb, jbegin_count) ; reiserfs_check_path(&path) ; reiserfs_write_unlock(dir->i_sb); return 0; 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); journal_end(&th, dir->i_sb, jbegin_count) ; reiserfs_write_unlock(dir->i_sb); return retval; }static int reiserfs_unlink (struct inode * dir, struct dentry *dentry){ int retval; 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 */ jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2; reiserfs_write_lock(dir->i_sb); journal_begin(&th, dir->i_sb, jbegin_count) ; 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; } inode->i_nlink--; /* * 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) { inode->i_nlink++; goto end_unlink; } inode->i_ctime = CURRENT_TIME; reiserfs_update_sd (&th, inode); dir->i_size -= (de.de_entrylen + DEH_SIZE); dir->i_ctime = dir->i_mtime = CURRENT_TIME; reiserfs_update_sd (&th, dir); if (!savelink) /* prevent file from getting lost */ add_save_link (&th, inode, 0/* not truncate */); journal_end(&th, dir->i_sb, jbegin_count) ; reiserfs_check_path(&path) ; reiserfs_write_unlock(dir->i_sb); return 0; end_unlink:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -