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

📄 xfs_rename.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */#include "xfs.h"#include "xfs_fs.h"#include "xfs_types.h"#include "xfs_log.h"#include "xfs_inum.h"#include "xfs_trans.h"#include "xfs_sb.h"#include "xfs_ag.h"#include "xfs_dir2.h"#include "xfs_dmapi.h"#include "xfs_mount.h"#include "xfs_da_btree.h"#include "xfs_bmap_btree.h"#include "xfs_dir2_sf.h"#include "xfs_attr_sf.h"#include "xfs_dinode.h"#include "xfs_inode.h"#include "xfs_inode_item.h"#include "xfs_bmap.h"#include "xfs_error.h"#include "xfs_quota.h"#include "xfs_refcache.h"#include "xfs_utils.h"#include "xfs_trans_space.h"/* * Given an array of up to 4 inode pointers, unlock the pointed to inodes. * If there are fewer than 4 entries in the array, the empty entries will * be at the end and will have NULL pointers in them. */STATIC voidxfs_rename_unlock4(	xfs_inode_t	**i_tab,	uint		lock_mode){	int	i;	xfs_iunlock(i_tab[0], lock_mode);	for (i = 1; i < 4; i++) {		if (i_tab[i] == NULL) {			break;		}		/*		 * Watch out for duplicate entries in the table.		 */		if (i_tab[i] != i_tab[i-1]) {			xfs_iunlock(i_tab[i], lock_mode);		}	}}#ifdef DEBUGint xfs_rename_skip, xfs_rename_nskip;#endif/* * The following routine will acquire the locks required for a rename * operation. The code understands the semantics of renames and will * validate that name1 exists under dp1 & that name2 may or may not * exist under dp2. * * We are renaming dp1/name1 to dp2/name2. * * Return ENOENT if dp1 does not exist, other lookup errors, or 0 for success. */STATIC intxfs_lock_for_rename(	xfs_inode_t	*dp1,	/* old (source) directory inode */	xfs_inode_t	*dp2,	/* new (target) directory inode */	bhv_vname_t	*vname1,/* old entry name */	bhv_vname_t	*vname2,/* new entry name */	xfs_inode_t	**ipp1,	/* inode of old entry */	xfs_inode_t	**ipp2,	/* inode of new entry, if it				   already exists, NULL otherwise. */	xfs_inode_t	**i_tab,/* array of inode returned, sorted */	int		*num_inodes)  /* number of inodes in array */{	xfs_inode_t		*ip1, *ip2, *temp;	xfs_ino_t		inum1, inum2;	int			error;	int			i, j;	uint			lock_mode;	int			diff_dirs = (dp1 != dp2);	ip2 = NULL;	/*	 * First, find out the current inums of the entries so that we	 * can determine the initial locking order.  We'll have to	 * sanity check stuff after all the locks have been acquired	 * to see if we still have the right inodes, directories, etc.	 */	lock_mode = xfs_ilock_map_shared(dp1);	error = xfs_get_dir_entry(vname1, &ip1);	if (error) {		xfs_iunlock_map_shared(dp1, lock_mode);		return error;	}	inum1 = ip1->i_ino;	ASSERT(ip1);	ITRACE(ip1);	/*	 * Unlock dp1 and lock dp2 if they are different.	 */	if (diff_dirs) {		xfs_iunlock_map_shared(dp1, lock_mode);		lock_mode = xfs_ilock_map_shared(dp2);	}	error = xfs_dir_lookup_int(dp2, lock_mode, vname2, &inum2, &ip2);	if (error == ENOENT) {		/* target does not need to exist. */		inum2 = 0;	} else if (error) {		/*		 * If dp2 and dp1 are the same, the next line unlocks dp1.		 * Got it?		 */		xfs_iunlock_map_shared(dp2, lock_mode);		IRELE (ip1);		return error;	} else {		ITRACE(ip2);	}	/*	 * i_tab contains a list of pointers to inodes.  We initialize	 * the table here & we'll sort it.  We will then use it to	 * order the acquisition of the inode locks.	 *	 * Note that the table may contain duplicates.  e.g., dp1 == dp2.	 */	i_tab[0] = dp1;	i_tab[1] = dp2;	i_tab[2] = ip1;	if (inum2 == 0) {		*num_inodes = 3;		i_tab[3] = NULL;	} else {		*num_inodes = 4;		i_tab[3] = ip2;	}	/*	 * Sort the elements via bubble sort.  (Remember, there are at	 * most 4 elements to sort, so this is adequate.)	 */	for (i=0; i < *num_inodes; i++) {		for (j=1; j < *num_inodes; j++) {			if (i_tab[j]->i_ino < i_tab[j-1]->i_ino) {				temp = i_tab[j];				i_tab[j] = i_tab[j-1];				i_tab[j-1] = temp;			}		}	}	/*	 * We have dp2 locked. If it isn't first, unlock it.	 * If it is first, tell xfs_lock_inodes so it can skip it	 * when locking. if dp1 == dp2, xfs_lock_inodes will skip both	 * since they are equal. xfs_lock_inodes needs all these inodes	 * so that it can unlock and retry if there might be a dead-lock	 * potential with the log.	 */	if (i_tab[0] == dp2 && lock_mode == XFS_ILOCK_SHARED) {#ifdef DEBUG		xfs_rename_skip++;#endif		xfs_lock_inodes(i_tab, *num_inodes, 1, XFS_ILOCK_SHARED);	} else {#ifdef DEBUG		xfs_rename_nskip++;#endif		xfs_iunlock_map_shared(dp2, lock_mode);		xfs_lock_inodes(i_tab, *num_inodes, 0, XFS_ILOCK_SHARED);	}	/*	 * Set the return value. Null out any unused entries in i_tab.	 */	*ipp1 = *ipp2 = NULL;	for (i=0; i < *num_inodes; i++) {		if (i_tab[i]->i_ino == inum1) {			*ipp1 = i_tab[i];		}		if (i_tab[i]->i_ino == inum2) {			*ipp2 = i_tab[i];		}	}	for (;i < 4; i++) {		i_tab[i] = NULL;	}	return 0;}/* * xfs_rename */intxfs_rename(	xfs_inode_t	*src_dp,	bhv_vname_t	*src_vname,	bhv_vnode_t	*target_dir_vp,	bhv_vname_t	*target_vname){	bhv_vnode_t	*src_dir_vp = XFS_ITOV(src_dp);	xfs_trans_t	*tp;	xfs_inode_t	*target_dp, *src_ip, *target_ip;	xfs_mount_t	*mp = src_dp->i_mount;	int		new_parent;		/* moving to a new dir */	int		src_is_directory;	/* src_name is a directory */	int		error;	xfs_bmap_free_t free_list;	xfs_fsblock_t   first_block;	int		cancel_flags;	int		committed;	xfs_inode_t	*inodes[4];	int		target_ip_dropped = 0;	/* dropped target_ip link? */	int		spaceres;	int		target_link_zero = 0;	int		num_inodes;	char		*src_name = VNAME(src_vname);	char		*target_name = VNAME(target_vname);	int		src_namelen = VNAMELEN(src_vname);	int		target_namelen = VNAMELEN(target_vname);	vn_trace_entry(src_dp, "xfs_rename", (inst_t *)__return_address);	vn_trace_entry(xfs_vtoi(target_dir_vp), "xfs_rename", (inst_t *)__return_address);	/*	 * Find the XFS behavior descriptor for the target directory	 * vnode since it was not handed to us.	 */	target_dp = xfs_vtoi(target_dir_vp);	if (target_dp == NULL) {		return XFS_ERROR(EXDEV);	}	if (DM_EVENT_ENABLED(src_dp, DM_EVENT_RENAME) ||	    DM_EVENT_ENABLED(target_dp, DM_EVENT_RENAME)) {		error = XFS_SEND_NAMESP(mp, DM_EVENT_RENAME,					src_dir_vp, DM_RIGHT_NULL,					target_dir_vp, DM_RIGHT_NULL,					src_name, target_name,					0, 0, 0);		if (error) {			return error;		}	}	/* Return through std_return after this point. */	/*	 * Lock all the participating inodes. Depending upon whether	 * the target_name exists in the target directory, and	 * whether the target directory is the same as the source	 * directory, we can lock from 2 to 4 inodes.	 * xfs_lock_for_rename() will return ENOENT if src_name	 * does not exist in the source directory.	 */	tp = NULL;	error = xfs_lock_for_rename(src_dp, target_dp, src_vname,			target_vname, &src_ip, &target_ip, inodes,			&num_inodes);	if (error) {		/*		 * We have nothing locked, no inode references, and		 * no transaction, so just get out.		 */		goto std_return;	}	ASSERT(src_ip != NULL);	if ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR) {		/*		 * Check for link count overflow on target_dp		 */		if (target_ip == NULL && (src_dp != target_dp) &&		    target_dp->i_d.di_nlink >= XFS_MAXLINK) {			error = XFS_ERROR(EMLINK);			xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);			goto rele_return;		}	}	/*	 * If we are using project inheritance, we only allow renames

⌨️ 快捷键说明

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