⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 namei.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		return -ENOMEM;	}	new_inode_init(inode, parent_dir, mode);	reiserfs_write_lock(parent_dir->i_sb);	item_len = ROUND_UP(strlen(symname));	if (item_len > MAX_DIRECT_ITEM_LEN(parent_dir->i_sb->s_blocksize)) {		retval = -ENAMETOOLONG;		drop_new_inode(inode);		goto out_failed;	}	name = kmalloc(item_len, GFP_NOFS);	if (!name) {		drop_new_inode(inode);		retval = -ENOMEM;		goto out_failed;	}	memcpy(name, symname, strlen(symname));	padd_item(name, item_len, strlen(symname));	/* We would inherit the default ACL here, but symlinks don't get ACLs */	retval = journal_begin(&th, parent_dir->i_sb, jbegin_count);	if (retval) {		drop_new_inode(inode);		kfree(name);		goto out_failed;	}	retval =	    reiserfs_new_inode(&th, parent_dir, mode, name, strlen(symname),			       dentry, inode);	kfree(name);	if (retval) {		/* reiserfs_new_inode iputs for us */		goto out_failed;	}	reiserfs_update_inode_transaction(inode);	reiserfs_update_inode_transaction(parent_dir);	inode->i_op = &reiserfs_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, parent_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, parent_dir->i_sb, jbegin_count);		if (err)			retval = err;		iput(inode);		goto out_failed;	}	d_instantiate(dentry, inode);	retval = journal_end(&th, parent_dir->i_sb, jbegin_count);      out_failed:	reiserfs_write_unlock(parent_dir->i_sb);	return retval;}static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,			 struct dentry *dentry){	int retval;	struct inode *inode = old_dentry->d_inode;	struct reiserfs_transaction_handle th;	/* We need blocks for transaction + update of quotas for the owners of the directory */	int jbegin_count =	    JOURNAL_PER_BALANCE_CNT * 3 +	    2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);	reiserfs_write_lock(dir->i_sb);	if (inode->i_nlink >= REISERFS_LINK_MAX) {		//FIXME: sd_nlink is 32 bit for new files		reiserfs_write_unlock(dir->i_sb);		return -EMLINK;	}	if (inode->i_nlink == 0) {		reiserfs_write_unlock(dir->i_sb);		return -ENOENT;	}	/* inc before scheduling so reiserfs_unlink knows we are here */	inc_nlink(inode);	retval = journal_begin(&th, dir->i_sb, jbegin_count);	if (retval) {		inode->i_nlink--;		reiserfs_write_unlock(dir->i_sb);		return retval;	}	/* 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) {		int err;		inode->i_nlink--;		err = journal_end(&th, dir->i_sb, jbegin_count);		reiserfs_write_unlock(dir->i_sb);		return err ? err : retval;	}	inode->i_ctime = CURRENT_TIME_SEC;	reiserfs_update_sd(&th, inode);	atomic_inc(&inode->i_count);	d_instantiate(dentry, inode);	retval = journal_end(&th, dir->i_sb, jbegin_count);	reiserfs_write_unlock(dir->i_sb);	return retval;}// 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(NULL,				       "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(NULL,			       "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 reiserfs_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;}/*  * 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_dentry_inode;	struct reiserfs_transaction_handle th;	int jbegin_count;	umode_t old_inode_mode;	unsigned long savelink = 1;	struct timespec ctime;	/* three balancings: (1) old name removal, (2) new name insertion	   and (3) maybe "save" link insertion	   stat data updates: (1) old directory,	   (2) new directory and (3) maybe old object stat data (when it is	   directory) and (4) maybe stat data of object to which new entry	   pointed initially and (5) maybe block containing ".." of	   renamed directory	   quota updates: two parent directories */	jbegin_count =	    JOURNAL_PER_BALANCE_CNT * 3 + 5 +	    4 * REISERFS_QUOTA_TRANS_BLOCKS(old_dir->i_sb);	old_inode = old_dentry->d_inode;	new_dentry_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 = NULL;	reiserfs_write_lock(old_dir->i_sb);	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 == IO_ERROR) {		reiserfs_write_unlock(old_dir->i_sb);		return -EIO;	}	if (retval != NAME_FOUND || old_de.de_objectid != old_inode->i_ino) {		reiserfs_write_unlock(old_dir->i_sb);		return -ENOENT;	}	old_inode_mode = old_inode->i_mode;	if (S_ISDIR(old_inode_mode)) {		// make sure, that directory being renamed has correct ".." 		// and that its new parent directory has not too many links		// already		if (new_dentry_inode) {			if (!reiserfs_empty_dir(new_dentry_inode)) {				reiserfs_write_unlock(old_dir->i_sb);				return -ENOTEMPTY;			}		}		/* directory is renamed, its parent directory will be changed, 		 ** so find ".." entry 		 */		dot_dot_de.de_gen_number_bit_string = NULL;		retval =		    reiserfs_find_entry(old_inode, "..", 2, &dot_dot_entry_path,					&dot_dot_de);		pathrelse(&dot_dot_entry_path);		if (retval != NAME_FOUND) {			reiserfs_write_unlock(old_dir->i_sb);			return -EIO;		}		/* inode number of .. must equal old_dir->i_ino */		if (dot_dot_de.de_objectid != old_dir->i_ino) {			reiserfs_write_unlock(old_dir->i_sb);			return -EIO;		}	}	retval = journal_begin(&th, old_dir->i_sb, jbegin_count);	if (retval) {		reiserfs_write_unlock(old_dir->i_sb);		return retval;	}	/* 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) {		if (!new_dentry_inode) {			reiserfs_panic(old_dir->i_sb,				       "vs-7050: new entry is found, new inode == 0\n");		}	} else if (retval) {		int err = journal_end(&th, old_dir->i_sb, jbegin_count);		reiserfs_write_unlock(old_dir->i_sb);		return err ? err : 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_dentry_inode)		reiserfs_update_inode_transaction(new_dentry_inode);	while (1) {		// look for old name using corresponding entry key (found by reiserfs_find_entry)		if ((retval =		     search_by_entry_key(new_dir->i_sb, &old_de.de_entry_key,					 &old_entry_path,					 &old_de)) != NAME_FOUND) {			pathrelse(&old_entry_path);			journal_end(&th, old_dir->i_sb, jbegin_count);			reiserfs_write_unlock(old_dir->i_sb);			return -EIO;		}		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 = NULL;		retval =		    reiserfs_find_entry(new_dir, new_dentry->d_name.name,					new_dentry->d_name.len, &new_entry_path,					&new_de);		// reiserfs_add_entry should not return IO_ERROR, because it is called with essentially same parameters from		// reiserfs_add_entry above, and we'll catch any i/o errors before we get here.		if (retval != NAME_FOUND_INVISIBLE && retval != NAME_FOUND) {			pathrelse(&new_entry_path);			pathrelse(&old_entry_path);			journal_end(&th, old_dir->i_sb, jbegin_count);			reiserfs_write_unlock(old_dir->i_sb);			return -EIO;		}		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 ((retval =			     search_by_entry_key(new_dir->i_sb,						 &dot_dot_de.de_entry_key,						 &dot_dot_entry_path,						 &dot_dot_de)) != NAME_FOUND) {				pathrelse(&dot_dot_entry_path);				pathrelse(&new_entry_path);				pathrelse(&old_entry_path);				journal_end(&th, old_dir->i_sb, jbegin_count);				reiserfs_write_unlock(old_dir->i_sb);				return -EIO;			}			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_dentry_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_mode))				reiserfs_restore_prepared_buffer(old_inode->								 i_sb,								 dot_dot_de.								 de_bh);			continue;		}		if (S_ISDIR(old_inode_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_mode) &&		       !buffer_journal_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);	ctime = CURRENT_TIME_SEC;	old_dir->i_ctime = old_dir->i_mtime = ctime;	new_dir->i_ctime = new_dir->i_mtime = ctime;	/* thanks to Alex Adriaanse <alex_a@caltech.edu> for patch which adds ctime update of	   renamed object */	old_inode->i_ctime = ctime;	if (new_dentry_inode) {		// adjust link number of the victim		if (S_ISDIR(new_dentry_inode->i_mode)) {			clear_nlink(new_dentry_inode);		} else {			drop_nlink(new_dentry_inode);		}		new_dentry_inode->i_ctime = ctime;		savelink = new_dentry_inode->i_nlink;	}	if (S_ISDIR(old_inode_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_dentry_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(old_dir->i_sb,				 "vs-7060: reiserfs_rename: couldn't not cut old name. Fsck later?");	old_dir->i_size -= DEH_SIZE + old_de.de_entrylen;	reiserfs_update_sd(&th, old_dir);	reiserfs_update_sd(&th, new_dir);	reiserfs_update_sd(&th, old_inode);	if (new_dentry_inode) {		if (savelink == 0)			add_save_link(&th, new_dentry_inode,				      0 /* not truncate */ );		reiserfs_update_sd(&th, new_dentry_inode);	}	retval = journal_end(&th, old_dir->i_sb, jbegin_count);	reiserfs_write_unlock(old_dir->i_sb);	return retval;}/* * directories can handle most operations... */const 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,	.setattr = reiserfs_setattr,	.setxattr = reiserfs_setxattr,	.getxattr = reiserfs_getxattr,	.listxattr = reiserfs_listxattr,	.removexattr = reiserfs_removexattr,	.permission = reiserfs_permission,};/* * symlink operations.. same as page_symlink_inode_operations, with xattr * stuff added */const struct inode_operations reiserfs_symlink_inode_operations = {	.readlink = generic_readlink,	.follow_link = page_follow_link_light,	.put_link = page_put_link,	.setattr = reiserfs_setattr,	.setxattr = reiserfs_setxattr,	.getxattr = reiserfs_getxattr,	.listxattr = reiserfs_listxattr,	.removexattr = reiserfs_removexattr,	.permission = reiserfs_permission,};/* * special file operations.. just xattr/acl stuff */const struct inode_operations reiserfs_special_inode_operations = {	.setattr = reiserfs_setattr,	.setxattr = reiserfs_setxattr,	.getxattr = reiserfs_getxattr,	.listxattr = reiserfs_listxattr,	.removexattr = reiserfs_removexattr,	.permission = reiserfs_permission,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -