📄 namei.c
字号:
//// 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_symlink (struct inode * dir, struct dentry * dentry, const char * symname){ int retval; struct inode * inode; char * name; int item_len; 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 ; } item_len = ROUND_UP (strlen (symname)); if (item_len > MAX_DIRECT_ITEM_LEN (dir->i_sb->s_blocksize)) { iput(inode) ; return -ENAMETOOLONG; } name = kmalloc (item_len, GFP_NOFS); if (!name) { iput(inode) ; return -ENOMEM; } memcpy (name, symname, strlen (symname)); padd_item (name, item_len, strlen (symname)); journal_begin(&th, dir->i_sb, jbegin_count) ; windex = push_journal_writer("reiserfs_symlink") ; inode = reiserfs_new_inode (&th, dir, S_IFLNK | S_IRWXUGO, name, strlen (symname), dentry, inode, &retval); kfree (name); if (inode == 0) { /* reiserfs_new_inode iputs for us */ pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return retval; } reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(dir) ; inode->i_op = &page_symlink_inode_operations; inode->i_mapping->a_ops = &reiserfs_address_space_operations; // must be sure this inode is written with this transaction // //reiserfs_update_sd (&th, inode, READ_BLOCKS); 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_link (struct dentry * old_dentry, struct inode * dir, struct dentry * dentry){ int retval; struct inode *inode = old_dentry->d_inode; int windex ; struct reiserfs_transaction_handle th ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; if (S_ISDIR(inode->i_mode)) return -EPERM; if (inode->i_nlink >= REISERFS_LINK_MAX) { //FIXME: sd_nlink is 32 bit for new files return -EMLINK; } journal_begin(&th, dir->i_sb, jbegin_count) ; windex = push_journal_writer("reiserfs_link") ; /* create new entry */ retval = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, inode, 1/*visible*/); reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(dir) ; if (retval) { pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return retval; } inode->i_nlink++; inode->i_ctime = CURRENT_TIME; reiserfs_update_sd (&th, inode); atomic_inc(&inode->i_count) ; d_instantiate(dentry, inode); pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; return 0;}// de contains information pointing to an entry which static int de_still_valid (const char * name, int len, struct reiserfs_dir_entry * de){ struct reiserfs_dir_entry tmp = *de; // recalculate pointer to name and name length set_de_name_and_namelen (&tmp); // FIXME: could check more if (tmp.de_namelen != len || memcmp (name, de->de_name, len)) return 0; return 1;}static int entry_points_to_object (const char * name, int len, struct reiserfs_dir_entry * de, struct inode * inode){ if (!de_still_valid (name, len, de)) return 0; if (inode) { if (!de_visible (de->de_deh + de->de_entry_num)) reiserfs_panic (0, "vs-7042: entry_points_to_object: entry must be visible"); return (de->de_objectid == inode->i_ino) ? 1 : 0; } /* this must be added hidden entry */ if (de_visible (de->de_deh + de->de_entry_num)) reiserfs_panic (0, "vs-7043: entry_points_to_object: entry must be visible"); return 1;}/* sets key of objectid the entry has to point to */static void set_ino_in_dir_entry (struct reiserfs_dir_entry * de, struct key * key){ /* JDM These operations are endian safe - both are le */ de->de_deh[de->de_entry_num].deh_dir_id = key->k_dir_id; de->de_deh[de->de_entry_num].deh_objectid = key->k_objectid;}//// 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.///* * process, that is going to call fix_nodes/do_balance must hold only * one path. If it holds 2 or more, it can get into endless waiting in * get_empty_nodes or its clones */static int reiserfs_rename (struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir, struct dentry *new_dentry){ int retval; INITIALIZE_PATH (old_entry_path); INITIALIZE_PATH (new_entry_path); INITIALIZE_PATH (dot_dot_entry_path); struct item_head new_entry_ih, old_entry_ih, dot_dot_ih ; struct reiserfs_dir_entry old_de, new_de, dot_dot_de; struct inode * old_inode, * new_inode; int windex ; struct reiserfs_transaction_handle th ; int jbegin_count ; /* two balancings: old name removal, new name insertion or "save" link, stat data updates: old directory and new directory and maybe block containing ".." of renamed directory */ jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 3; old_inode = old_dentry->d_inode; new_inode = new_dentry->d_inode; // make sure, that oldname still exists and points to an object we // are going to rename old_de.de_gen_number_bit_string = 0; retval = reiserfs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_entry_path, &old_de); pathrelse (&old_entry_path); if (retval != NAME_FOUND || old_de.de_objectid != old_inode->i_ino) { // FIXME: IO error is possible here return -ENOENT; } if (S_ISDIR(old_inode->i_mode)) { // make sure, that directory being renamed has correct ".." // and that its new parent directory has not too many links // already if (new_inode) { if (!reiserfs_empty_dir(new_inode)) { return -ENOTEMPTY; } } /* directory is renamed, its parent directory will be changed, ** so find ".." entry */ dot_dot_de.de_gen_number_bit_string = 0; retval = reiserfs_find_entry (old_inode, "..", 2, &dot_dot_entry_path, &dot_dot_de); pathrelse (&dot_dot_entry_path); if (retval != NAME_FOUND) return -EIO; /* inode number of .. must equal old_dir->i_ino */ if (dot_dot_de.de_objectid != old_dir->i_ino) return -EIO; } journal_begin(&th, old_dir->i_sb, jbegin_count) ; windex = push_journal_writer("reiserfs_rename") ; /* add new entry (or find the existing one) */ retval = reiserfs_add_entry (&th, new_dir, new_dentry->d_name.name, new_dentry->d_name.len, old_inode, 0); if (retval == -EEXIST) { // FIXME: is it possible, that new_inode == 0 here? If yes, it // is not clear how does ext2 handle that if (!new_inode) { reiserfs_panic (old_dir->i_sb, "vs-7050: new entry is found, new inode == 0\n"); } } else if (retval) { pop_journal_writer(windex) ; journal_end(&th, old_dir->i_sb, jbegin_count) ; return retval; } reiserfs_update_inode_transaction(old_dir) ; reiserfs_update_inode_transaction(new_dir) ; /* this makes it so an fsync on an open fd for the old name will ** commit the rename operation */ reiserfs_update_inode_transaction(old_inode) ; if (new_inode) reiserfs_update_inode_transaction(new_inode) ; while (1) { // look for old name using corresponding entry key (found by reiserfs_find_entry) if (search_by_entry_key (new_dir->i_sb, &old_de.de_entry_key, &old_entry_path, &old_de) != NAME_FOUND) BUG (); copy_item_head(&old_entry_ih, get_ih(&old_entry_path)) ; reiserfs_prepare_for_journal(old_inode->i_sb, old_de.de_bh, 1) ; // look for new name by reiserfs_find_entry new_de.de_gen_number_bit_string = 0; retval = reiserfs_find_entry (new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_entry_path, &new_de); if (retval != NAME_FOUND_INVISIBLE && retval != NAME_FOUND) BUG (); copy_item_head(&new_entry_ih, get_ih(&new_entry_path)) ; reiserfs_prepare_for_journal(old_inode->i_sb, new_de.de_bh, 1) ; if (S_ISDIR(old_inode->i_mode)) { if (search_by_entry_key (new_dir->i_sb, &dot_dot_de.de_entry_key, &dot_dot_entry_path, &dot_dot_de) != NAME_FOUND) BUG (); copy_item_head(&dot_dot_ih, get_ih(&dot_dot_entry_path)) ; // node containing ".." gets into transaction reiserfs_prepare_for_journal(old_inode->i_sb, dot_dot_de.de_bh, 1) ; } /* we should check seals here, not do this stuff, yes? Then, having gathered everything into RAM we should lock the buffers, yes? -Hans */ /* probably. our rename needs to hold more ** than one path at once. The seals would ** have to be written to deal with multi-path ** issues -chris */ /* sanity checking before doing the rename - avoid races many ** of the above checks could have scheduled. We have to be ** sure our items haven't been shifted by another process. */ if (item_moved(&new_entry_ih, &new_entry_path) || !entry_points_to_object(new_dentry->d_name.name, new_dentry->d_name.len, &new_de, new_inode) || item_moved(&old_entry_ih, &old_entry_path) || !entry_points_to_object (old_dentry->d_name.name, old_dentry->d_name.len, &old_de, old_inode)) { reiserfs_restore_prepared_buffer (old_inode->i_sb, new_de.de_bh); reiserfs_restore_prepared_buffer (old_inode->i_sb, old_de.de_bh); if (S_ISDIR(old_inode->i_mode)) reiserfs_restore_prepared_buffer (old_inode->i_sb, dot_dot_de.de_bh); continue; } if (S_ISDIR(old_inode->i_mode)) { if ( item_moved(&dot_dot_ih, &dot_dot_entry_path) || !entry_points_to_object ( "..", 2, &dot_dot_de, old_dir) ) { reiserfs_restore_prepared_buffer (old_inode->i_sb, old_de.de_bh); reiserfs_restore_prepared_buffer (old_inode->i_sb, new_de.de_bh); reiserfs_restore_prepared_buffer (old_inode->i_sb, dot_dot_de.de_bh); continue; } } RFALSE( S_ISDIR(old_inode->i_mode) && !reiserfs_buffer_prepared(dot_dot_de.de_bh), "" ); break; } /* ok, all the changes can be done in one fell swoop when we have claimed all the buffers needed.*/ mark_de_visible (new_de.de_deh + new_de.de_entry_num); set_ino_in_dir_entry (&new_de, INODE_PKEY (old_inode)); journal_mark_dirty (&th, old_dir->i_sb, new_de.de_bh); mark_de_hidden (old_de.de_deh + old_de.de_entry_num); journal_mark_dirty (&th, old_dir->i_sb, old_de.de_bh); old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME; if (new_inode) { // adjust link number of the victim if (S_ISDIR(new_inode->i_mode)) { new_inode->i_nlink = 0; } else { new_inode->i_nlink--; } new_inode->i_ctime = CURRENT_TIME; } if (S_ISDIR(old_inode->i_mode)) { // adjust ".." of renamed directory set_ino_in_dir_entry (&dot_dot_de, INODE_PKEY (new_dir)); journal_mark_dirty (&th, new_dir->i_sb, dot_dot_de.de_bh); if (!new_inode) /* there (in new_dir) was no directory, so it got new link (".." of renamed directory) */ INC_DIR_INODE_NLINK(new_dir); /* old directory lost one link - ".. " of renamed directory */ DEC_DIR_INODE_NLINK(old_dir); } // looks like in 2.3.99pre3 brelse is atomic. so we can use pathrelse pathrelse (&new_entry_path); pathrelse (&dot_dot_entry_path); // FIXME: this reiserfs_cut_from_item's return value may screw up // anybody, but it will panic if will not be able to find the // entry. This needs one more clean up if (reiserfs_cut_from_item (&th, &old_entry_path, &(old_de.de_entry_key), old_dir, NULL, 0) < 0) reiserfs_warning ("vs-7060: reiserfs_rename: couldn't not cut old name. Fsck later?\n"); old_dir->i_size -= DEH_SIZE + old_de.de_entrylen; old_dir->i_blocks = ((old_dir->i_size + 511) >> 9); reiserfs_update_sd (&th, old_dir); reiserfs_update_sd (&th, new_dir); if (new_inode) { if (new_inode->i_nlink == 0) add_save_link (&th, new_inode, 0/* not truncate */); reiserfs_update_sd (&th, new_inode); } pop_journal_writer(windex) ; journal_end(&th, old_dir->i_sb, jbegin_count) ; return 0;}/* * directories can handle most operations... */struct inode_operations reiserfs_dir_inode_operations = { //&reiserfs_dir_operations, /* default_file_ops */ create: reiserfs_create, lookup: reiserfs_lookup, link: reiserfs_link, unlink: reiserfs_unlink, symlink: reiserfs_symlink, mkdir: reiserfs_mkdir, rmdir: reiserfs_rmdir, mknod: reiserfs_mknod, rename: reiserfs_rename,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -