📄 namei.c
字号:
/* copy name */ memcpy ((char *)(deh + 1), name, namelen); /* padd by 0s to the 4 byte boundary */ padd_item ((char *)(deh + 1), ROUND_UP (namelen), namelen); /* entry is ready to be pasted into tree, set 'visibility' and 'stat data in entry' attributes */ mark_de_without_sd (deh); visible ? mark_de_visible (deh) : mark_de_hidden (deh); /* 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 != NAME_FOUND) { reiserfs_warning ("zam-7002:" __FUNCTION__ ": \"reiserfs_find_entry\" has returned" " unexpected value (%d)\n", retval); } return -EEXIST; } gen_number = find_first_zero_bit (bit_string, MAX_GENERATION_NUMBER + 1); if (gen_number > MAX_GENERATION_NUMBER) { /* there is no free generation number */ reiserfs_warning ("reiserfs_add_entry: Congratulations! we have got hash function screwed up\n"); 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 ("vs-7032: reiserfs_add_entry: " "entry with this key (%k) already exists\n", &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, 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_blocks = ((dir->i_size + 511) >> 9); 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;}//// a portion of this function, particularly the VFS interface portion,// was derived from minix or ext2's analog and evolved as the// prototype did. You should be able to tell which portion by looking// at the ext2 code and comparing. It's subfunctions contain no code// used as a template unless they are so labeled.//static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode){ int retval; struct inode * inode; int windex ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 ; struct reiserfs_transaction_handle th ; inode = new_inode(dir->i_sb) ; if (!inode) { return -ENOMEM ; } journal_begin(&th, dir->i_sb, jbegin_count) ; th.t_caller = "create" ; windex = push_journal_writer("reiserfs_create") ; inode = reiserfs_new_inode (&th, dir, mode, 0, 0/*i_size*/, dentry, inode, &retval); if (!inode) { pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return retval; } 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); pop_journal_writer(windex) ; // FIXME: should we put iput here and have stat data deleted // in the same transactioin journal_end(&th, dir->i_sb, jbegin_count) ; iput (inode); return retval; } reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(dir) ; d_instantiate(dentry, inode); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return 0;}//// a portion of this function, particularly the VFS interface portion,// was derived from minix or ext2's analog and evolved as the// prototype did. You should be able to tell which portion by looking// at the ext2 code and comparing. It's subfunctions contain no code// used as a template unless they are so labeled.//static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev){ int retval; struct inode * inode; int windex ; struct reiserfs_transaction_handle th ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; inode = new_inode(dir->i_sb) ; if (!inode) { return -ENOMEM ; } journal_begin(&th, dir->i_sb, jbegin_count) ; windex = push_journal_writer("reiserfs_mknod") ; inode = reiserfs_new_inode (&th, dir, mode, 0, 0/*i_size*/, dentry, inode, &retval); if (!inode) { pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return retval; } init_special_inode(inode, 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); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; iput (inode); return retval; } d_instantiate(dentry, inode); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return 0;}//// a portion of this function, particularly the VFS interface portion,// was derived from minix or ext2's analog and evolved as the// prototype did. You should be able to tell which portion by looking// at the ext2 code and comparing. It's subfunctions contain no code// used as a template unless they are so labeled.//static int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode){ int retval; struct inode * inode; int windex ; struct reiserfs_transaction_handle th ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; inode = new_inode(dir->i_sb) ; if (!inode) { return -ENOMEM ; } journal_begin(&th, dir->i_sb, jbegin_count) ; windex = push_journal_writer("reiserfs_mkdir") ; /* inc the link count now, so another writer doesn't overflow it while ** we sleep later on. */ INC_DIR_INODE_NLINK(dir) mode = S_IFDIR | mode; inode = reiserfs_new_inode (&th, dir, mode, 0/*symlink*/, old_format_only (dir->i_sb) ? EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE, dentry, inode, &retval); if (!inode) { pop_journal_writer(windex) ; dir->i_nlink-- ; journal_end(&th, dir->i_sb, jbegin_count) ; return retval; } 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); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; iput (inode); return retval; } // the above add_entry did not update dir's stat data reiserfs_update_sd (&th, dir); d_instantiate(dentry, inode); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return 0;}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 ;}//// a portion of this function, particularly the VFS interface portion,// was derived from minix or ext2's analog and evolved as the// prototype did. You should be able to tell which portion by looking// at the ext2 code and comparing. It's subfunctions contain no code// used as a template unless they are so labeled.//static int reiserfs_rmdir (struct inode * dir, struct dentry *dentry){ int retval; struct inode * inode; int windex ; 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; journal_begin(&th, dir->i_sb, jbegin_count) ; windex = push_journal_writer("reiserfs_rmdir") ; de.de_gen_number_bit_string = 0; if (reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path, &de) == NAME_NOT_FOUND) { retval = -ENOENT; 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 ) printk ("reiserfs_rmdir: empty directory has nlink != 2 (%d)\n", 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); dir->i_blocks = ((dir->i_size + 511) >> 9); reiserfs_update_sd (&th, dir); /* prevent empty directory from getting lost */ add_save_link (&th, inode, 0/* not truncate */); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; reiserfs_check_path(&path) ; 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); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return retval; }//// a portion of this function, particularly the VFS interface portion,// was derived from minix or ext2's analog and evolved as the// prototype did. You should be able to tell which portion by looking// at the ext2 code and comparing. It's subfunctions contain no code// used as a template unless they are so labeled.//static int reiserfs_unlink (struct inode * dir, struct dentry *dentry){ int retval; struct inode * inode; struct reiserfs_dir_entry de; INITIALIZE_PATH (path); int windex ; struct reiserfs_transaction_handle th ; int jbegin_count; 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; journal_begin(&th, dir->i_sb, jbegin_count) ; windex = push_journal_writer("reiserfs_unlink") ; de.de_gen_number_bit_string = 0; if (reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path, &de) == NAME_NOT_FOUND) { retval = -ENOENT; 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) { printk("reiserfs_unlink: deleting nonexistent file (%s:%lu), %d\n", kdevname(inode->i_dev), inode->i_ino, inode->i_nlink); inode->i_nlink = 1; } retval = reiserfs_cut_from_item (&th, &path, &(de.de_entry_key), dir, NULL, 0); if (retval < 0) goto end_unlink; inode->i_nlink--; inode->i_ctime = CURRENT_TIME; reiserfs_update_sd (&th, inode); dir->i_size -= (de.de_entrylen + DEH_SIZE); dir->i_blocks = ((dir->i_size + 511) >> 9); dir->i_ctime = dir->i_mtime = CURRENT_TIME; reiserfs_update_sd (&th, dir); if (!inode->i_nlink) /* prevent file from getting lost */ add_save_link (&th, inode, 0/* not truncate */); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; reiserfs_check_path(&path) ; return 0; end_unlink: pathrelse (&path); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; reiserfs_check_path(&path) ; return retval;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -