public inbox for linux-xfs@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] merge xfs_rmdir into xfs_remove
@ 2008-05-02 10:57 Christoph Hellwig
  2008-05-20  6:36 ` Christoph Hellwig
  2008-05-21  8:25 ` Christoph Hellwig
  0 siblings, 2 replies; 6+ messages in thread
From: Christoph Hellwig @ 2008-05-02 10:57 UTC (permalink / raw)
  To: xfs

xfs_remove and xfs_rmdir are almost the same with a little more work
performed in xfs_rmdir due to the . and .. entries.  This patch merges
xfs_rmdir into xfs_remove and performs these actions conditionally.

Also clean up the error handling which was a nightmare in both versions
before.


Signed-off-by: Christoph Hellwig <hch@lst.de>

Index: linux-2.6-xfs/fs/xfs/xfs_vnodeops.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_vnodeops.c	2008-05-01 22:56:57.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_vnodeops.c	2008-05-02 08:30:24.000000000 +0200
@@ -2135,13 +2135,6 @@ again:
 #endif
 }
 
-#ifdef	DEBUG
-#define	REMOVE_DEBUG_TRACE(x)	{remove_which_error_return = (x);}
-int remove_which_error_return = 0;
-#else /* ! DEBUG */
-#define	REMOVE_DEBUG_TRACE(x)
-#endif	/* ! DEBUG */
-
 int
 xfs_remove(
 	xfs_inode_t             *dp,
@@ -2150,6 +2143,7 @@ xfs_remove(
 {
 	xfs_mount_t		*mp = dp->i_mount;
 	xfs_trans_t             *tp = NULL;
+	int			is_dir = S_ISDIR(ip->i_d.di_mode);
 	int                     error = 0;
 	xfs_bmap_free_t         free_list;
 	xfs_fsblock_t           first_block;
@@ -2157,8 +2151,11 @@ xfs_remove(
 	int			committed;
 	int			link_zero;
 	uint			resblks;
+	uint			trans;
+	uint			log_count;
 
 	xfs_itrace_entry(dp);
+	xfs_itrace_entry(ip);
 
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
@@ -2171,19 +2168,25 @@ xfs_remove(
 			return error;
 	}
 
-	xfs_itrace_entry(ip);
-	xfs_itrace_ref(ip);
-
 	error = XFS_QM_DQATTACH(mp, dp, 0);
-	if (!error)
-		error = XFS_QM_DQATTACH(mp, ip, 0);
-	if (error) {
-		REMOVE_DEBUG_TRACE(__LINE__);
+	if (error)
+		goto std_return;
+
+	error = XFS_QM_DQATTACH(mp, ip, 0);
+	if (error)
 		goto std_return;
+
+	if (is_dir) {
+		trans = XFS_TRANS_RMDIR;
+		log_count = XFS_DEFAULT_LOG_COUNT;
+	} else {
+		trans = XFS_TRANS_REMOVE;
+		log_count = XFS_REMOVE_LOG_COUNT;
 	}
 
-	tp = xfs_trans_alloc(mp, XFS_TRANS_REMOVE);
+	tp = xfs_trans_alloc(mp, trans);
 	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
+
 	/*
 	 * We try to get the real space reservation first,
 	 * allowing for directory btree deletion(s) implying
@@ -2195,25 +2198,21 @@ xfs_remove(
 	 */
 	resblks = XFS_REMOVE_SPACE_RES(mp);
 	error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
-			XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
+				  XFS_TRANS_PERM_LOG_RES, log_count);
 	if (error == ENOSPC) {
 		resblks = 0;
 		error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
-				XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
+					  XFS_TRANS_PERM_LOG_RES, log_count);
 	}
 	if (error) {
 		ASSERT(error != ENOSPC);
-		REMOVE_DEBUG_TRACE(__LINE__);
-		xfs_trans_cancel(tp, 0);
-		return error;
+		cancel_flags = 0;
+		goto out_trans_cancel;
 	}
 
 	error = xfs_lock_dir_and_entry(dp, ip);
-	if (error) {
-		REMOVE_DEBUG_TRACE(__LINE__);
-		xfs_trans_cancel(tp, cancel_flags);
-		goto std_return;
-	}
+	if (error)
+		goto out_trans_cancel;
 
 	/*
 	 * At this point, we've gotten both the directory and the entry
@@ -2226,6 +2225,21 @@ xfs_remove(
 	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 
 	/*
+	 * If we're removing a directory perform some additional validation.
+	 */
+	if (is_dir) {
+		ASSERT(ip->i_d.di_nlink >= 2);
+		if (ip->i_d.di_nlink != 2) {
+			error = XFS_ERROR(ENOTEMPTY);
+			goto out_trans_cancel;
+		}
+		if (!xfs_dir_isempty(ip)) {
+			error = XFS_ERROR(ENOTEMPTY);
+			goto out_trans_cancel;
+		}
+	}
+
+	/*
 	 * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
 	 */
 	XFS_BMAP_INIT(&free_list, &first_block);
@@ -2233,39 +2247,64 @@ xfs_remove(
 					&first_block, &free_list, resblks);
 	if (error) {
 		ASSERT(error != ENOENT);
-		REMOVE_DEBUG_TRACE(__LINE__);
-		goto error1;
+		goto out_bmap_cancel;
 	}
 	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 
+	/*
+	 * Bump the in memory generation count on the parent
+	 * directory so that other can know that it has changed.
+	 */
 	dp->i_gen++;
 	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 
-	error = xfs_droplink(tp, ip);
-	if (error) {
-		REMOVE_DEBUG_TRACE(__LINE__);
-		goto error1;
+	if (is_dir) {
+		/*
+		 * Drop the link from ip's "..".
+		 */
+		error = xfs_droplink(tp, dp);
+		if (error)
+			goto out_bmap_cancel;
+
+		/*
+		 * Drop the link from dp to ip.
+		 */
+		error = xfs_droplink(tp, ip);
+		if (error)
+			goto out_bmap_cancel;
+	} else {
+		/*
+		 * When removing a non-directory we need to log the parent
+		 * inode here for the i_gen update.  For a directory this is
+		 * done implicitly by the xfs_droplink call for the ".." entry.
+		 */
+		xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 	}
 
-	/* Determine if this is the last link while
+	/*
+	 * Drop the "." link from ip to self.
+	 */
+	error = xfs_droplink(tp, ip);
+	if (error)
+		goto out_bmap_cancel;
+
+	/*
+	 * Determine if this is the last link while
 	 * we are in the transaction.
 	 */
-	link_zero = (ip)->i_d.di_nlink==0;
+	link_zero = (ip->i_d.di_nlink == 0);
 
 	/*
 	 * If this is a synchronous mount, make sure that the
 	 * remove transaction goes to disk before returning to
 	 * the user.
 	 */
-	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
+	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
 		xfs_trans_set_sync(tp);
-	}
 
 	error = xfs_bmap_finish(&tp, &free_list, &committed);
-	if (error) {
-		REMOVE_DEBUG_TRACE(__LINE__);
-		goto error_rele;
-	}
+	if (error)
+		goto out_bmap_cancel;
 
 	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
 	if (error)
@@ -2277,39 +2316,27 @@ xfs_remove(
 	 * will get killed on last close in xfs_close() so we don't
 	 * have to worry about that.
 	 */
-	if (link_zero && xfs_inode_is_filestream(ip))
+	if (!is_dir && link_zero && xfs_inode_is_filestream(ip))
 		xfs_filestream_deassociate(ip);
 
 	xfs_itrace_exit(ip);
+	xfs_itrace_exit(dp);
 
-/*	Fall through to std_return with error = 0 */
  std_return:
 	if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
-		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
-				dp, DM_RIGHT_NULL,
-				NULL, DM_RIGHT_NULL,
-				name->name, NULL, ip->i_d.di_mode, error, 0);
+		XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dp, DM_RIGHT_NULL,
+				NULL, DM_RIGHT_NULL, name->name, NULL,
+				ip->i_d.di_mode, error, 0);
 	}
+
 	return error;
 
- error1:
+ out_bmap_cancel:
 	xfs_bmap_cancel(&free_list);
 	cancel_flags |= XFS_TRANS_ABORT;
+ out_trans_cancel:
 	xfs_trans_cancel(tp, cancel_flags);
 	goto std_return;
-
- error_rele:
-	/*
-	 * In this case make sure to not release the inode until after
-	 * the current transaction is aborted.  Releasing it beforehand
-	 * can cause us to go to xfs_inactive and start a recursive
-	 * transaction which can easily deadlock with the current one.
-	 */
-	xfs_bmap_cancel(&free_list);
-	cancel_flags |= XFS_TRANS_ABORT;
-	xfs_trans_cancel(tp, cancel_flags);
-
-	goto std_return;
 }
 
 int
@@ -2675,186 +2702,6 @@ std_return:
 }
 
 int
-xfs_rmdir(
-	xfs_inode_t             *dp,
-	struct xfs_name		*name,
-	xfs_inode_t		*cdp)
-{
-	xfs_mount_t		*mp = dp->i_mount;
-	xfs_trans_t             *tp;
-	int                     error;
-	xfs_bmap_free_t         free_list;
-	xfs_fsblock_t           first_block;
-	int			cancel_flags;
-	int			committed;
-	int			last_cdp_link;
-	uint			resblks;
-
-	xfs_itrace_entry(dp);
-
-	if (XFS_FORCED_SHUTDOWN(mp))
-		return XFS_ERROR(EIO);
-
-	if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) {
-		error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE,
-					dp, DM_RIGHT_NULL,
-					NULL, DM_RIGHT_NULL, name->name,
-					NULL, cdp->i_d.di_mode, 0, 0);
-		if (error)
-			return XFS_ERROR(error);
-	}
-
-	/*
-	 * Get the dquots for the inodes.
-	 */
-	error = XFS_QM_DQATTACH(mp, dp, 0);
-	if (!error)
-		error = XFS_QM_DQATTACH(mp, cdp, 0);
-	if (error) {
-		REMOVE_DEBUG_TRACE(__LINE__);
-		goto std_return;
-	}
-
-	tp = xfs_trans_alloc(mp, XFS_TRANS_RMDIR);
-	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
-	/*
-	 * We try to get the real space reservation first,
-	 * allowing for directory btree deletion(s) implying
-	 * possible bmap insert(s).  If we can't get the space
-	 * reservation then we use 0 instead, and avoid the bmap
-	 * btree insert(s) in the directory code by, if the bmap
-	 * insert tries to happen, instead trimming the LAST
-	 * block from the directory.
-	 */
-	resblks = XFS_REMOVE_SPACE_RES(mp);
-	error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
-			XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
-	if (error == ENOSPC) {
-		resblks = 0;
-		error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
-				XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
-	}
-	if (error) {
-		ASSERT(error != ENOSPC);
-		cancel_flags = 0;
-		goto error_return;
-	}
-	XFS_BMAP_INIT(&free_list, &first_block);
-
-	/*
-	 * Now lock the child directory inode and the parent directory
-	 * inode in the proper order.  This will take care of validating
-	 * that the directory entry for the child directory inode has
-	 * not changed while we were obtaining a log reservation.
-	 */
-	error = xfs_lock_dir_and_entry(dp, cdp);
-	if (error) {
-		xfs_trans_cancel(tp, cancel_flags);
-		goto std_return;
-	}
-
-	IHOLD(dp);
-	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
-
-	IHOLD(cdp);
-	xfs_trans_ijoin(tp, cdp, XFS_ILOCK_EXCL);
-
-	ASSERT(cdp->i_d.di_nlink >= 2);
-	if (cdp->i_d.di_nlink != 2) {
-		error = XFS_ERROR(ENOTEMPTY);
-		goto error_return;
-	}
-	if (!xfs_dir_isempty(cdp)) {
-		error = XFS_ERROR(ENOTEMPTY);
-		goto error_return;
-	}
-
-	error = xfs_dir_removename(tp, dp, name, cdp->i_ino,
-					&first_block, &free_list, resblks);
-	if (error)
-		goto error1;
-
-	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
-
-	/*
-	 * Bump the in memory generation count on the parent
-	 * directory so that other can know that it has changed.
-	 */
-	dp->i_gen++;
-
-	/*
-	 * Drop the link from cdp's "..".
-	 */
-	error = xfs_droplink(tp, dp);
-	if (error) {
-		goto error1;
-	}
-
-	/*
-	 * Drop the link from dp to cdp.
-	 */
-	error = xfs_droplink(tp, cdp);
-	if (error) {
-		goto error1;
-	}
-
-	/*
-	 * Drop the "." link from cdp to self.
-	 */
-	error = xfs_droplink(tp, cdp);
-	if (error) {
-		goto error1;
-	}
-
-	/* Determine these before committing transaction */
-	last_cdp_link = (cdp)->i_d.di_nlink==0;
-
-	/*
-	 * If this is a synchronous mount, make sure that the
-	 * rmdir transaction goes to disk before returning to
-	 * the user.
-	 */
-	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
-		xfs_trans_set_sync(tp);
-	}
-
-	error = xfs_bmap_finish (&tp, &free_list, &committed);
-	if (error) {
-		xfs_bmap_cancel(&free_list);
-		xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
-				 XFS_TRANS_ABORT));
-		goto std_return;
-	}
-
-	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
-	if (error) {
-		goto std_return;
-	}
-
-
-	/* Fall through to std_return with error = 0 or the errno
-	 * from xfs_trans_commit. */
- std_return:
-	if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
-		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
-					dp, DM_RIGHT_NULL,
-					NULL, DM_RIGHT_NULL,
-					name->name, NULL, cdp->i_d.di_mode,
-					error, 0);
-	}
-	return error;
-
- error1:
-	xfs_bmap_cancel(&free_list);
-	cancel_flags |= XFS_TRANS_ABORT;
-	/* FALLTHROUGH */
-
- error_return:
-	xfs_trans_cancel(tp, cancel_flags);
-	goto std_return;
-}
-
-int
 xfs_symlink(
 	xfs_inode_t		*dp,
 	struct xfs_name		*link_name,
Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_iops.c	2008-05-02 00:09:32.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c	2008-05-02 08:30:24.000000000 +0200
@@ -252,8 +252,7 @@ STATIC void
 xfs_cleanup_inode(
 	struct inode	*dir,
 	struct inode	*inode,
-	struct dentry	*dentry,
-	int		mode)
+	struct dentry	*dentry)
 {
 	struct xfs_name	teardown;
 
@@ -264,10 +263,7 @@ xfs_cleanup_inode(
 	 */
 	xfs_dentry_to_name(&teardown, dentry);
 
-	if (S_ISDIR(mode))
-		xfs_rmdir(XFS_I(dir), &teardown, XFS_I(inode));
-	else
-		xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
+	xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
 	iput(inode);
 }
 
@@ -349,7 +345,7 @@ xfs_vn_mknod(
 	return -error;
 
  out_cleanup_inode:
-	xfs_cleanup_inode(dir, inode, dentry, mode);
+	xfs_cleanup_inode(dir, inode, dentry);
  out_free_acl:
 	if (default_acl)
 		_ACL_FREE(default_acl);
@@ -478,31 +474,12 @@ xfs_vn_symlink(
 	return 0;
 
  out_cleanup_inode:
-	xfs_cleanup_inode(dir, inode, dentry, 0);
+	xfs_cleanup_inode(dir, inode, dentry);
  out:
 	return -error;
 }
 
 STATIC int
-xfs_vn_rmdir(
-	struct inode	*dir,
-	struct dentry	*dentry)
-{
-	struct inode	*inode = dentry->d_inode;
-	struct xfs_name	name;
-	int		error;
-
-	xfs_dentry_to_name(&name, dentry);
-
-	error = xfs_rmdir(XFS_I(dir), &name, XFS_I(inode));
-	if (likely(!error)) {
-		xfs_validate_fields(inode);
-		xfs_validate_fields(dir);
-	}
-	return -error;
-}
-
-STATIC int
 xfs_vn_rename(
 	struct inode	*odir,
 	struct dentry	*odentry,
@@ -796,7 +773,13 @@ static const struct inode_operations xfs
 	.unlink			= xfs_vn_unlink,
 	.symlink		= xfs_vn_symlink,
 	.mkdir			= xfs_vn_mkdir,
-	.rmdir			= xfs_vn_rmdir,
+	/*
+	 * Yes, XFS uses the same method for rmdir and unlink.
+	 *
+	 * There are some subtile differences deeper in the code,
+	 * but we use S_ISDIR to check for those.
+	 */
+	.rmdir			= xfs_vn_unlink,
 	.mknod			= xfs_vn_mknod,
 	.rename			= xfs_vn_rename,
 	.permission		= xfs_vn_permission,
Index: linux-2.6-xfs/fs/xfs/xfs_vnodeops.h
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_vnodeops.h	2008-04-26 20:05:39.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_vnodeops.h	2008-05-02 08:30:24.000000000 +0200
@@ -32,8 +32,6 @@ int xfs_link(struct xfs_inode *tdp, stru
 		struct xfs_name *target_name);
 int xfs_mkdir(struct xfs_inode *dp, struct xfs_name *dir_name,
 		mode_t mode, struct xfs_inode **ipp, struct cred *credp);
-int xfs_rmdir(struct xfs_inode *dp, struct xfs_name *name,
-		struct xfs_inode *cdp);
 int xfs_readdir(struct xfs_inode	*dp, void *dirent, size_t bufsize,
 		       xfs_off_t *offset, filldir_t filldir);
 int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] merge xfs_rmdir into xfs_remove
  2008-05-02 10:57 [PATCH 1/2] merge xfs_rmdir into xfs_remove Christoph Hellwig
@ 2008-05-20  6:36 ` Christoph Hellwig
  2008-05-21  8:25 ` Christoph Hellwig
  1 sibling, 0 replies; 6+ messages in thread
From: Christoph Hellwig @ 2008-05-20  6:36 UTC (permalink / raw)
  To: xfs

ping?

On Fri, May 02, 2008 at 12:57:57PM +0200, Christoph Hellwig wrote:
> xfs_remove and xfs_rmdir are almost the same with a little more work
> performed in xfs_rmdir due to the . and .. entries.  This patch merges
> xfs_rmdir into xfs_remove and performs these actions conditionally.
> 
> Also clean up the error handling which was a nightmare in both versions
> before.
> 
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> 
> Index: linux-2.6-xfs/fs/xfs/xfs_vnodeops.c
> ===================================================================
> --- linux-2.6-xfs.orig/fs/xfs/xfs_vnodeops.c	2008-05-01 22:56:57.000000000 +0200
> +++ linux-2.6-xfs/fs/xfs/xfs_vnodeops.c	2008-05-02 08:30:24.000000000 +0200
> @@ -2135,13 +2135,6 @@ again:
>  #endif
>  }
>  
> -#ifdef	DEBUG
> -#define	REMOVE_DEBUG_TRACE(x)	{remove_which_error_return = (x);}
> -int remove_which_error_return = 0;
> -#else /* ! DEBUG */
> -#define	REMOVE_DEBUG_TRACE(x)
> -#endif	/* ! DEBUG */
> -
>  int
>  xfs_remove(
>  	xfs_inode_t             *dp,
> @@ -2150,6 +2143,7 @@ xfs_remove(
>  {
>  	xfs_mount_t		*mp = dp->i_mount;
>  	xfs_trans_t             *tp = NULL;
> +	int			is_dir = S_ISDIR(ip->i_d.di_mode);
>  	int                     error = 0;
>  	xfs_bmap_free_t         free_list;
>  	xfs_fsblock_t           first_block;
> @@ -2157,8 +2151,11 @@ xfs_remove(
>  	int			committed;
>  	int			link_zero;
>  	uint			resblks;
> +	uint			trans;
> +	uint			log_count;
>  
>  	xfs_itrace_entry(dp);
> +	xfs_itrace_entry(ip);
>  
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return XFS_ERROR(EIO);
> @@ -2171,19 +2168,25 @@ xfs_remove(
>  			return error;
>  	}
>  
> -	xfs_itrace_entry(ip);
> -	xfs_itrace_ref(ip);
> -
>  	error = XFS_QM_DQATTACH(mp, dp, 0);
> -	if (!error)
> -		error = XFS_QM_DQATTACH(mp, ip, 0);
> -	if (error) {
> -		REMOVE_DEBUG_TRACE(__LINE__);
> +	if (error)
> +		goto std_return;
> +
> +	error = XFS_QM_DQATTACH(mp, ip, 0);
> +	if (error)
>  		goto std_return;
> +
> +	if (is_dir) {
> +		trans = XFS_TRANS_RMDIR;
> +		log_count = XFS_DEFAULT_LOG_COUNT;
> +	} else {
> +		trans = XFS_TRANS_REMOVE;
> +		log_count = XFS_REMOVE_LOG_COUNT;
>  	}
>  
> -	tp = xfs_trans_alloc(mp, XFS_TRANS_REMOVE);
> +	tp = xfs_trans_alloc(mp, trans);
>  	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
> +
>  	/*
>  	 * We try to get the real space reservation first,
>  	 * allowing for directory btree deletion(s) implying
> @@ -2195,25 +2198,21 @@ xfs_remove(
>  	 */
>  	resblks = XFS_REMOVE_SPACE_RES(mp);
>  	error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
> -			XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
> +				  XFS_TRANS_PERM_LOG_RES, log_count);
>  	if (error == ENOSPC) {
>  		resblks = 0;
>  		error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
> -				XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
> +					  XFS_TRANS_PERM_LOG_RES, log_count);
>  	}
>  	if (error) {
>  		ASSERT(error != ENOSPC);
> -		REMOVE_DEBUG_TRACE(__LINE__);
> -		xfs_trans_cancel(tp, 0);
> -		return error;
> +		cancel_flags = 0;
> +		goto out_trans_cancel;
>  	}
>  
>  	error = xfs_lock_dir_and_entry(dp, ip);
> -	if (error) {
> -		REMOVE_DEBUG_TRACE(__LINE__);
> -		xfs_trans_cancel(tp, cancel_flags);
> -		goto std_return;
> -	}
> +	if (error)
> +		goto out_trans_cancel;
>  
>  	/*
>  	 * At this point, we've gotten both the directory and the entry
> @@ -2226,6 +2225,21 @@ xfs_remove(
>  	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
>  
>  	/*
> +	 * If we're removing a directory perform some additional validation.
> +	 */
> +	if (is_dir) {
> +		ASSERT(ip->i_d.di_nlink >= 2);
> +		if (ip->i_d.di_nlink != 2) {
> +			error = XFS_ERROR(ENOTEMPTY);
> +			goto out_trans_cancel;
> +		}
> +		if (!xfs_dir_isempty(ip)) {
> +			error = XFS_ERROR(ENOTEMPTY);
> +			goto out_trans_cancel;
> +		}
> +	}
> +
> +	/*
>  	 * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
>  	 */
>  	XFS_BMAP_INIT(&free_list, &first_block);
> @@ -2233,39 +2247,64 @@ xfs_remove(
>  					&first_block, &free_list, resblks);
>  	if (error) {
>  		ASSERT(error != ENOENT);
> -		REMOVE_DEBUG_TRACE(__LINE__);
> -		goto error1;
> +		goto out_bmap_cancel;
>  	}
>  	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
>  
> +	/*
> +	 * Bump the in memory generation count on the parent
> +	 * directory so that other can know that it has changed.
> +	 */
>  	dp->i_gen++;
>  	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
>  
> -	error = xfs_droplink(tp, ip);
> -	if (error) {
> -		REMOVE_DEBUG_TRACE(__LINE__);
> -		goto error1;
> +	if (is_dir) {
> +		/*
> +		 * Drop the link from ip's "..".
> +		 */
> +		error = xfs_droplink(tp, dp);
> +		if (error)
> +			goto out_bmap_cancel;
> +
> +		/*
> +		 * Drop the link from dp to ip.
> +		 */
> +		error = xfs_droplink(tp, ip);
> +		if (error)
> +			goto out_bmap_cancel;
> +	} else {
> +		/*
> +		 * When removing a non-directory we need to log the parent
> +		 * inode here for the i_gen update.  For a directory this is
> +		 * done implicitly by the xfs_droplink call for the ".." entry.
> +		 */
> +		xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
>  	}
>  
> -	/* Determine if this is the last link while
> +	/*
> +	 * Drop the "." link from ip to self.
> +	 */
> +	error = xfs_droplink(tp, ip);
> +	if (error)
> +		goto out_bmap_cancel;
> +
> +	/*
> +	 * Determine if this is the last link while
>  	 * we are in the transaction.
>  	 */
> -	link_zero = (ip)->i_d.di_nlink==0;
> +	link_zero = (ip->i_d.di_nlink == 0);
>  
>  	/*
>  	 * If this is a synchronous mount, make sure that the
>  	 * remove transaction goes to disk before returning to
>  	 * the user.
>  	 */
> -	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
> +	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
>  		xfs_trans_set_sync(tp);
> -	}
>  
>  	error = xfs_bmap_finish(&tp, &free_list, &committed);
> -	if (error) {
> -		REMOVE_DEBUG_TRACE(__LINE__);
> -		goto error_rele;
> -	}
> +	if (error)
> +		goto out_bmap_cancel;
>  
>  	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
>  	if (error)
> @@ -2277,39 +2316,27 @@ xfs_remove(
>  	 * will get killed on last close in xfs_close() so we don't
>  	 * have to worry about that.
>  	 */
> -	if (link_zero && xfs_inode_is_filestream(ip))
> +	if (!is_dir && link_zero && xfs_inode_is_filestream(ip))
>  		xfs_filestream_deassociate(ip);
>  
>  	xfs_itrace_exit(ip);
> +	xfs_itrace_exit(dp);
>  
> -/*	Fall through to std_return with error = 0 */
>   std_return:
>  	if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
> -		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
> -				dp, DM_RIGHT_NULL,
> -				NULL, DM_RIGHT_NULL,
> -				name->name, NULL, ip->i_d.di_mode, error, 0);
> +		XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dp, DM_RIGHT_NULL,
> +				NULL, DM_RIGHT_NULL, name->name, NULL,
> +				ip->i_d.di_mode, error, 0);
>  	}
> +
>  	return error;
>  
> - error1:
> + out_bmap_cancel:
>  	xfs_bmap_cancel(&free_list);
>  	cancel_flags |= XFS_TRANS_ABORT;
> + out_trans_cancel:
>  	xfs_trans_cancel(tp, cancel_flags);
>  	goto std_return;
> -
> - error_rele:
> -	/*
> -	 * In this case make sure to not release the inode until after
> -	 * the current transaction is aborted.  Releasing it beforehand
> -	 * can cause us to go to xfs_inactive and start a recursive
> -	 * transaction which can easily deadlock with the current one.
> -	 */
> -	xfs_bmap_cancel(&free_list);
> -	cancel_flags |= XFS_TRANS_ABORT;
> -	xfs_trans_cancel(tp, cancel_flags);
> -
> -	goto std_return;
>  }
>  
>  int
> @@ -2675,186 +2702,6 @@ std_return:
>  }
>  
>  int
> -xfs_rmdir(
> -	xfs_inode_t             *dp,
> -	struct xfs_name		*name,
> -	xfs_inode_t		*cdp)
> -{
> -	xfs_mount_t		*mp = dp->i_mount;
> -	xfs_trans_t             *tp;
> -	int                     error;
> -	xfs_bmap_free_t         free_list;
> -	xfs_fsblock_t           first_block;
> -	int			cancel_flags;
> -	int			committed;
> -	int			last_cdp_link;
> -	uint			resblks;
> -
> -	xfs_itrace_entry(dp);
> -
> -	if (XFS_FORCED_SHUTDOWN(mp))
> -		return XFS_ERROR(EIO);
> -
> -	if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) {
> -		error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE,
> -					dp, DM_RIGHT_NULL,
> -					NULL, DM_RIGHT_NULL, name->name,
> -					NULL, cdp->i_d.di_mode, 0, 0);
> -		if (error)
> -			return XFS_ERROR(error);
> -	}
> -
> -	/*
> -	 * Get the dquots for the inodes.
> -	 */
> -	error = XFS_QM_DQATTACH(mp, dp, 0);
> -	if (!error)
> -		error = XFS_QM_DQATTACH(mp, cdp, 0);
> -	if (error) {
> -		REMOVE_DEBUG_TRACE(__LINE__);
> -		goto std_return;
> -	}
> -
> -	tp = xfs_trans_alloc(mp, XFS_TRANS_RMDIR);
> -	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
> -	/*
> -	 * We try to get the real space reservation first,
> -	 * allowing for directory btree deletion(s) implying
> -	 * possible bmap insert(s).  If we can't get the space
> -	 * reservation then we use 0 instead, and avoid the bmap
> -	 * btree insert(s) in the directory code by, if the bmap
> -	 * insert tries to happen, instead trimming the LAST
> -	 * block from the directory.
> -	 */
> -	resblks = XFS_REMOVE_SPACE_RES(mp);
> -	error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
> -			XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
> -	if (error == ENOSPC) {
> -		resblks = 0;
> -		error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
> -				XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
> -	}
> -	if (error) {
> -		ASSERT(error != ENOSPC);
> -		cancel_flags = 0;
> -		goto error_return;
> -	}
> -	XFS_BMAP_INIT(&free_list, &first_block);
> -
> -	/*
> -	 * Now lock the child directory inode and the parent directory
> -	 * inode in the proper order.  This will take care of validating
> -	 * that the directory entry for the child directory inode has
> -	 * not changed while we were obtaining a log reservation.
> -	 */
> -	error = xfs_lock_dir_and_entry(dp, cdp);
> -	if (error) {
> -		xfs_trans_cancel(tp, cancel_flags);
> -		goto std_return;
> -	}
> -
> -	IHOLD(dp);
> -	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
> -
> -	IHOLD(cdp);
> -	xfs_trans_ijoin(tp, cdp, XFS_ILOCK_EXCL);
> -
> -	ASSERT(cdp->i_d.di_nlink >= 2);
> -	if (cdp->i_d.di_nlink != 2) {
> -		error = XFS_ERROR(ENOTEMPTY);
> -		goto error_return;
> -	}
> -	if (!xfs_dir_isempty(cdp)) {
> -		error = XFS_ERROR(ENOTEMPTY);
> -		goto error_return;
> -	}
> -
> -	error = xfs_dir_removename(tp, dp, name, cdp->i_ino,
> -					&first_block, &free_list, resblks);
> -	if (error)
> -		goto error1;
> -
> -	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
> -
> -	/*
> -	 * Bump the in memory generation count on the parent
> -	 * directory so that other can know that it has changed.
> -	 */
> -	dp->i_gen++;
> -
> -	/*
> -	 * Drop the link from cdp's "..".
> -	 */
> -	error = xfs_droplink(tp, dp);
> -	if (error) {
> -		goto error1;
> -	}
> -
> -	/*
> -	 * Drop the link from dp to cdp.
> -	 */
> -	error = xfs_droplink(tp, cdp);
> -	if (error) {
> -		goto error1;
> -	}
> -
> -	/*
> -	 * Drop the "." link from cdp to self.
> -	 */
> -	error = xfs_droplink(tp, cdp);
> -	if (error) {
> -		goto error1;
> -	}
> -
> -	/* Determine these before committing transaction */
> -	last_cdp_link = (cdp)->i_d.di_nlink==0;
> -
> -	/*
> -	 * If this is a synchronous mount, make sure that the
> -	 * rmdir transaction goes to disk before returning to
> -	 * the user.
> -	 */
> -	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
> -		xfs_trans_set_sync(tp);
> -	}
> -
> -	error = xfs_bmap_finish (&tp, &free_list, &committed);
> -	if (error) {
> -		xfs_bmap_cancel(&free_list);
> -		xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
> -				 XFS_TRANS_ABORT));
> -		goto std_return;
> -	}
> -
> -	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
> -	if (error) {
> -		goto std_return;
> -	}
> -
> -
> -	/* Fall through to std_return with error = 0 or the errno
> -	 * from xfs_trans_commit. */
> - std_return:
> -	if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
> -		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
> -					dp, DM_RIGHT_NULL,
> -					NULL, DM_RIGHT_NULL,
> -					name->name, NULL, cdp->i_d.di_mode,
> -					error, 0);
> -	}
> -	return error;
> -
> - error1:
> -	xfs_bmap_cancel(&free_list);
> -	cancel_flags |= XFS_TRANS_ABORT;
> -	/* FALLTHROUGH */
> -
> - error_return:
> -	xfs_trans_cancel(tp, cancel_flags);
> -	goto std_return;
> -}
> -
> -int
>  xfs_symlink(
>  	xfs_inode_t		*dp,
>  	struct xfs_name		*link_name,
> Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c
> ===================================================================
> --- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_iops.c	2008-05-02 00:09:32.000000000 +0200
> +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c	2008-05-02 08:30:24.000000000 +0200
> @@ -252,8 +252,7 @@ STATIC void
>  xfs_cleanup_inode(
>  	struct inode	*dir,
>  	struct inode	*inode,
> -	struct dentry	*dentry,
> -	int		mode)
> +	struct dentry	*dentry)
>  {
>  	struct xfs_name	teardown;
>  
> @@ -264,10 +263,7 @@ xfs_cleanup_inode(
>  	 */
>  	xfs_dentry_to_name(&teardown, dentry);
>  
> -	if (S_ISDIR(mode))
> -		xfs_rmdir(XFS_I(dir), &teardown, XFS_I(inode));
> -	else
> -		xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
> +	xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
>  	iput(inode);
>  }
>  
> @@ -349,7 +345,7 @@ xfs_vn_mknod(
>  	return -error;
>  
>   out_cleanup_inode:
> -	xfs_cleanup_inode(dir, inode, dentry, mode);
> +	xfs_cleanup_inode(dir, inode, dentry);
>   out_free_acl:
>  	if (default_acl)
>  		_ACL_FREE(default_acl);
> @@ -478,31 +474,12 @@ xfs_vn_symlink(
>  	return 0;
>  
>   out_cleanup_inode:
> -	xfs_cleanup_inode(dir, inode, dentry, 0);
> +	xfs_cleanup_inode(dir, inode, dentry);
>   out:
>  	return -error;
>  }
>  
>  STATIC int
> -xfs_vn_rmdir(
> -	struct inode	*dir,
> -	struct dentry	*dentry)
> -{
> -	struct inode	*inode = dentry->d_inode;
> -	struct xfs_name	name;
> -	int		error;
> -
> -	xfs_dentry_to_name(&name, dentry);
> -
> -	error = xfs_rmdir(XFS_I(dir), &name, XFS_I(inode));
> -	if (likely(!error)) {
> -		xfs_validate_fields(inode);
> -		xfs_validate_fields(dir);
> -	}
> -	return -error;
> -}
> -
> -STATIC int
>  xfs_vn_rename(
>  	struct inode	*odir,
>  	struct dentry	*odentry,
> @@ -796,7 +773,13 @@ static const struct inode_operations xfs
>  	.unlink			= xfs_vn_unlink,
>  	.symlink		= xfs_vn_symlink,
>  	.mkdir			= xfs_vn_mkdir,
> -	.rmdir			= xfs_vn_rmdir,
> +	/*
> +	 * Yes, XFS uses the same method for rmdir and unlink.
> +	 *
> +	 * There are some subtile differences deeper in the code,
> +	 * but we use S_ISDIR to check for those.
> +	 */
> +	.rmdir			= xfs_vn_unlink,
>  	.mknod			= xfs_vn_mknod,
>  	.rename			= xfs_vn_rename,
>  	.permission		= xfs_vn_permission,
> Index: linux-2.6-xfs/fs/xfs/xfs_vnodeops.h
> ===================================================================
> --- linux-2.6-xfs.orig/fs/xfs/xfs_vnodeops.h	2008-04-26 20:05:39.000000000 +0200
> +++ linux-2.6-xfs/fs/xfs/xfs_vnodeops.h	2008-05-02 08:30:24.000000000 +0200
> @@ -32,8 +32,6 @@ int xfs_link(struct xfs_inode *tdp, stru
>  		struct xfs_name *target_name);
>  int xfs_mkdir(struct xfs_inode *dp, struct xfs_name *dir_name,
>  		mode_t mode, struct xfs_inode **ipp, struct cred *credp);
> -int xfs_rmdir(struct xfs_inode *dp, struct xfs_name *name,
> -		struct xfs_inode *cdp);
>  int xfs_readdir(struct xfs_inode	*dp, void *dirent, size_t bufsize,
>  		       xfs_off_t *offset, filldir_t filldir);
>  int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,
---end quoted text---

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] merge xfs_rmdir into xfs_remove
  2008-05-02 10:57 [PATCH 1/2] merge xfs_rmdir into xfs_remove Christoph Hellwig
  2008-05-20  6:36 ` Christoph Hellwig
@ 2008-05-21  8:25 ` Christoph Hellwig
  2008-06-16  6:18   ` Christoph Hellwig
  1 sibling, 1 reply; 6+ messages in thread
From: Christoph Hellwig @ 2008-05-21  8:25 UTC (permalink / raw)
  To: xfs

On Fri, May 02, 2008 at 12:57:57PM +0200, Christoph Hellwig wrote:
> xfs_remove and xfs_rmdir are almost the same with a little more work
> performed in xfs_rmdir due to the . and .. entries.  This patch merges
> xfs_rmdir into xfs_remove and performs these actions conditionally.
> 
> Also clean up the error handling which was a nightmare in both versions
> before.

Updated for the case-insensitive filename changes.


Signed-off-by: Christoph Hellwig <hch@lst.de>

Index: linux-2.6-xfs/fs/xfs/xfs_vnodeops.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_vnodeops.c	2008-05-21 10:10:30.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_vnodeops.c	2008-05-21 10:21:31.000000000 +0200
@@ -2116,13 +2116,6 @@ again:
 #endif
 }
 
-#ifdef	DEBUG
-#define	REMOVE_DEBUG_TRACE(x)	{remove_which_error_return = (x);}
-int remove_which_error_return = 0;
-#else /* ! DEBUG */
-#define	REMOVE_DEBUG_TRACE(x)
-#endif	/* ! DEBUG */
-
 int
 xfs_remove(
 	xfs_inode_t             *dp,
@@ -2131,6 +2124,7 @@ xfs_remove(
 {
 	xfs_mount_t		*mp = dp->i_mount;
 	xfs_trans_t             *tp = NULL;
+	int			is_dir = S_ISDIR(ip->i_d.di_mode);
 	int                     error = 0;
 	xfs_bmap_free_t         free_list;
 	xfs_fsblock_t           first_block;
@@ -2138,8 +2132,11 @@ xfs_remove(
 	int			committed;
 	int			link_zero;
 	uint			resblks;
+	uint			trans;
+	uint			log_count;
 
 	xfs_itrace_entry(dp);
+	xfs_itrace_entry(ip);
 
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
@@ -2152,19 +2149,25 @@ xfs_remove(
 			return error;
 	}
 
-	xfs_itrace_entry(ip);
-	xfs_itrace_ref(ip);
-
 	error = XFS_QM_DQATTACH(mp, dp, 0);
-	if (!error)
-		error = XFS_QM_DQATTACH(mp, ip, 0);
-	if (error) {
-		REMOVE_DEBUG_TRACE(__LINE__);
+	if (error)
+		goto std_return;
+
+	error = XFS_QM_DQATTACH(mp, ip, 0);
+	if (error)
 		goto std_return;
+
+	if (is_dir) {
+		trans = XFS_TRANS_RMDIR;
+		log_count = XFS_DEFAULT_LOG_COUNT;
+	} else {
+		trans = XFS_TRANS_REMOVE;
+		log_count = XFS_REMOVE_LOG_COUNT;
 	}
 
-	tp = xfs_trans_alloc(mp, XFS_TRANS_REMOVE);
+	tp = xfs_trans_alloc(mp, trans);
 	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
+
 	/*
 	 * We try to get the real space reservation first,
 	 * allowing for directory btree deletion(s) implying
@@ -2176,25 +2179,21 @@ xfs_remove(
 	 */
 	resblks = XFS_REMOVE_SPACE_RES(mp);
 	error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
-			XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
+				  XFS_TRANS_PERM_LOG_RES, log_count);
 	if (error == ENOSPC) {
 		resblks = 0;
 		error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
-				XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
+					  XFS_TRANS_PERM_LOG_RES, log_count);
 	}
 	if (error) {
 		ASSERT(error != ENOSPC);
-		REMOVE_DEBUG_TRACE(__LINE__);
-		xfs_trans_cancel(tp, 0);
-		return error;
+		cancel_flags = 0;
+		goto out_trans_cancel;
 	}
 
 	error = xfs_lock_dir_and_entry(dp, ip);
-	if (error) {
-		REMOVE_DEBUG_TRACE(__LINE__);
-		xfs_trans_cancel(tp, cancel_flags);
-		goto std_return;
-	}
+	if (error)
+		goto out_trans_cancel;
 
 	/*
 	 * At this point, we've gotten both the directory and the entry
@@ -2207,6 +2206,21 @@ xfs_remove(
 	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 
 	/*
+	 * If we're removing a directory perform some additional validation.
+	 */
+	if (is_dir) {
+		ASSERT(ip->i_d.di_nlink >= 2);
+		if (ip->i_d.di_nlink != 2) {
+			error = XFS_ERROR(ENOTEMPTY);
+			goto out_trans_cancel;
+		}
+		if (!xfs_dir_isempty(ip)) {
+			error = XFS_ERROR(ENOTEMPTY);
+			goto out_trans_cancel;
+		}
+	}
+
+	/*
 	 * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
 	 */
 	XFS_BMAP_INIT(&free_list, &first_block);
@@ -2214,39 +2228,64 @@ xfs_remove(
 					&first_block, &free_list, resblks);
 	if (error) {
 		ASSERT(error != ENOENT);
-		REMOVE_DEBUG_TRACE(__LINE__);
-		goto error1;
+		goto out_bmap_cancel;
 	}
 	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 
+	/*
+	 * Bump the in memory generation count on the parent
+	 * directory so that other can know that it has changed.
+	 */
 	dp->i_gen++;
 	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 
-	error = xfs_droplink(tp, ip);
-	if (error) {
-		REMOVE_DEBUG_TRACE(__LINE__);
-		goto error1;
+	if (is_dir) {
+		/*
+		 * Drop the link from ip's "..".
+		 */
+		error = xfs_droplink(tp, dp);
+		if (error)
+			goto out_bmap_cancel;
+
+		/*
+		 * Drop the link from dp to ip.
+		 */
+		error = xfs_droplink(tp, ip);
+		if (error)
+			goto out_bmap_cancel;
+	} else {
+		/*
+		 * When removing a non-directory we need to log the parent
+		 * inode here for the i_gen update.  For a directory this is
+		 * done implicitly by the xfs_droplink call for the ".." entry.
+		 */
+		xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 	}
 
-	/* Determine if this is the last link while
+	/*
+	 * Drop the "." link from ip to self.
+	 */
+	error = xfs_droplink(tp, ip);
+	if (error)
+		goto out_bmap_cancel;
+
+	/*
+	 * Determine if this is the last link while
 	 * we are in the transaction.
 	 */
-	link_zero = (ip)->i_d.di_nlink==0;
+	link_zero = (ip->i_d.di_nlink == 0);
 
 	/*
 	 * If this is a synchronous mount, make sure that the
 	 * remove transaction goes to disk before returning to
 	 * the user.
 	 */
-	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
+	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
 		xfs_trans_set_sync(tp);
-	}
 
 	error = xfs_bmap_finish(&tp, &free_list, &committed);
-	if (error) {
-		REMOVE_DEBUG_TRACE(__LINE__);
-		goto error_rele;
-	}
+	if (error)
+		goto out_bmap_cancel;
 
 	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
 	if (error)
@@ -2258,39 +2297,27 @@ xfs_remove(
 	 * will get killed on last close in xfs_close() so we don't
 	 * have to worry about that.
 	 */
-	if (link_zero && xfs_inode_is_filestream(ip))
+	if (!is_dir && link_zero && xfs_inode_is_filestream(ip))
 		xfs_filestream_deassociate(ip);
 
 	xfs_itrace_exit(ip);
+	xfs_itrace_exit(dp);
 
-/*	Fall through to std_return with error = 0 */
  std_return:
 	if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
-		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
-				dp, DM_RIGHT_NULL,
-				NULL, DM_RIGHT_NULL,
-				name->name, NULL, ip->i_d.di_mode, error, 0);
+		XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dp, DM_RIGHT_NULL,
+				NULL, DM_RIGHT_NULL, name->name, NULL,
+				ip->i_d.di_mode, error, 0);
 	}
+
 	return error;
 
- error1:
+ out_bmap_cancel:
 	xfs_bmap_cancel(&free_list);
 	cancel_flags |= XFS_TRANS_ABORT;
+ out_trans_cancel:
 	xfs_trans_cancel(tp, cancel_flags);
 	goto std_return;
-
- error_rele:
-	/*
-	 * In this case make sure to not release the inode until after
-	 * the current transaction is aborted.  Releasing it beforehand
-	 * can cause us to go to xfs_inactive and start a recursive
-	 * transaction which can easily deadlock with the current one.
-	 */
-	xfs_bmap_cancel(&free_list);
-	cancel_flags |= XFS_TRANS_ABORT;
-	xfs_trans_cancel(tp, cancel_flags);
-
-	goto std_return;
 }
 
 int
@@ -2656,186 +2683,6 @@ std_return:
 }
 
 int
-xfs_rmdir(
-	xfs_inode_t             *dp,
-	struct xfs_name		*name,
-	xfs_inode_t		*cdp)
-{
-	xfs_mount_t		*mp = dp->i_mount;
-	xfs_trans_t             *tp;
-	int                     error;
-	xfs_bmap_free_t         free_list;
-	xfs_fsblock_t           first_block;
-	int			cancel_flags;
-	int			committed;
-	int			last_cdp_link;
-	uint			resblks;
-
-	xfs_itrace_entry(dp);
-
-	if (XFS_FORCED_SHUTDOWN(mp))
-		return XFS_ERROR(EIO);
-
-	if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) {
-		error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE,
-					dp, DM_RIGHT_NULL,
-					NULL, DM_RIGHT_NULL, name->name,
-					NULL, cdp->i_d.di_mode, 0, 0);
-		if (error)
-			return XFS_ERROR(error);
-	}
-
-	/*
-	 * Get the dquots for the inodes.
-	 */
-	error = XFS_QM_DQATTACH(mp, dp, 0);
-	if (!error)
-		error = XFS_QM_DQATTACH(mp, cdp, 0);
-	if (error) {
-		REMOVE_DEBUG_TRACE(__LINE__);
-		goto std_return;
-	}
-
-	tp = xfs_trans_alloc(mp, XFS_TRANS_RMDIR);
-	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
-	/*
-	 * We try to get the real space reservation first,
-	 * allowing for directory btree deletion(s) implying
-	 * possible bmap insert(s).  If we can't get the space
-	 * reservation then we use 0 instead, and avoid the bmap
-	 * btree insert(s) in the directory code by, if the bmap
-	 * insert tries to happen, instead trimming the LAST
-	 * block from the directory.
-	 */
-	resblks = XFS_REMOVE_SPACE_RES(mp);
-	error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
-			XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
-	if (error == ENOSPC) {
-		resblks = 0;
-		error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
-				XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
-	}
-	if (error) {
-		ASSERT(error != ENOSPC);
-		cancel_flags = 0;
-		goto error_return;
-	}
-	XFS_BMAP_INIT(&free_list, &first_block);
-
-	/*
-	 * Now lock the child directory inode and the parent directory
-	 * inode in the proper order.  This will take care of validating
-	 * that the directory entry for the child directory inode has
-	 * not changed while we were obtaining a log reservation.
-	 */
-	error = xfs_lock_dir_and_entry(dp, cdp);
-	if (error) {
-		xfs_trans_cancel(tp, cancel_flags);
-		goto std_return;
-	}
-
-	IHOLD(dp);
-	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
-
-	IHOLD(cdp);
-	xfs_trans_ijoin(tp, cdp, XFS_ILOCK_EXCL);
-
-	ASSERT(cdp->i_d.di_nlink >= 2);
-	if (cdp->i_d.di_nlink != 2) {
-		error = XFS_ERROR(ENOTEMPTY);
-		goto error_return;
-	}
-	if (!xfs_dir_isempty(cdp)) {
-		error = XFS_ERROR(ENOTEMPTY);
-		goto error_return;
-	}
-
-	error = xfs_dir_removename(tp, dp, name, cdp->i_ino,
-					&first_block, &free_list, resblks);
-	if (error)
-		goto error1;
-
-	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
-
-	/*
-	 * Bump the in memory generation count on the parent
-	 * directory so that other can know that it has changed.
-	 */
-	dp->i_gen++;
-
-	/*
-	 * Drop the link from cdp's "..".
-	 */
-	error = xfs_droplink(tp, dp);
-	if (error) {
-		goto error1;
-	}
-
-	/*
-	 * Drop the link from dp to cdp.
-	 */
-	error = xfs_droplink(tp, cdp);
-	if (error) {
-		goto error1;
-	}
-
-	/*
-	 * Drop the "." link from cdp to self.
-	 */
-	error = xfs_droplink(tp, cdp);
-	if (error) {
-		goto error1;
-	}
-
-	/* Determine these before committing transaction */
-	last_cdp_link = (cdp)->i_d.di_nlink==0;
-
-	/*
-	 * If this is a synchronous mount, make sure that the
-	 * rmdir transaction goes to disk before returning to
-	 * the user.
-	 */
-	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
-		xfs_trans_set_sync(tp);
-	}
-
-	error = xfs_bmap_finish (&tp, &free_list, &committed);
-	if (error) {
-		xfs_bmap_cancel(&free_list);
-		xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
-				 XFS_TRANS_ABORT));
-		goto std_return;
-	}
-
-	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
-	if (error) {
-		goto std_return;
-	}
-
-
-	/* Fall through to std_return with error = 0 or the errno
-	 * from xfs_trans_commit. */
- std_return:
-	if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
-		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
-					dp, DM_RIGHT_NULL,
-					NULL, DM_RIGHT_NULL,
-					name->name, NULL, cdp->i_d.di_mode,
-					error, 0);
-	}
-	return error;
-
- error1:
-	xfs_bmap_cancel(&free_list);
-	cancel_flags |= XFS_TRANS_ABORT;
-	/* FALLTHROUGH */
-
- error_return:
-	xfs_trans_cancel(tp, cancel_flags);
-	goto std_return;
-}
-
-int
 xfs_symlink(
 	xfs_inode_t		*dp,
 	struct xfs_name		*link_name,
Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_iops.c	2008-05-21 10:17:36.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c	2008-05-21 10:21:53.000000000 +0200
@@ -252,8 +252,7 @@ STATIC void
 xfs_cleanup_inode(
 	struct inode	*dir,
 	struct inode	*inode,
-	struct dentry	*dentry,
-	int		mode)
+	struct dentry	*dentry)
 {
 	struct xfs_name	teardown;
 
@@ -264,10 +263,7 @@ xfs_cleanup_inode(
 	 */
 	xfs_dentry_to_name(&teardown, dentry);
 
-	if (S_ISDIR(mode))
-		xfs_rmdir(XFS_I(dir), &teardown, XFS_I(inode));
-	else
-		xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
+	xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
 	iput(inode);
 }
 
@@ -349,7 +345,7 @@ xfs_vn_mknod(
 	return -error;
 
  out_cleanup_inode:
-	xfs_cleanup_inode(dir, inode, dentry, mode);
+	xfs_cleanup_inode(dir, inode, dentry);
  out_free_acl:
 	if (default_acl)
 		_ACL_FREE(default_acl);
@@ -514,31 +510,12 @@ xfs_vn_symlink(
 	return 0;
 
  out_cleanup_inode:
-	xfs_cleanup_inode(dir, inode, dentry, 0);
+	xfs_cleanup_inode(dir, inode, dentry);
  out:
 	return -error;
 }
 
 STATIC int
-xfs_vn_rmdir(
-	struct inode	*dir,
-	struct dentry	*dentry)
-{
-	struct inode	*inode = dentry->d_inode;
-	struct xfs_name	name;
-	int		error;
-
-	xfs_dentry_to_name(&name, dentry);
-
-	error = xfs_rmdir(XFS_I(dir), &name, XFS_I(inode));
-	if (likely(!error)) {
-		xfs_validate_fields(inode);
-		xfs_validate_fields(dir);
-	}
-	return -error;
-}
-
-STATIC int
 xfs_vn_rename(
 	struct inode	*odir,
 	struct dentry	*odentry,
@@ -832,7 +809,13 @@ static const struct inode_operations xfs
 	.unlink			= xfs_vn_unlink,
 	.symlink		= xfs_vn_symlink,
 	.mkdir			= xfs_vn_mkdir,
-	.rmdir			= xfs_vn_rmdir,
+	/*
+	 * Yes, XFS uses the same method for rmdir and unlink.
+	 *
+	 * There are some subtile differences deeper in the code,
+	 * but we use S_ISDIR to check for those.
+	 */
+	.rmdir			= xfs_vn_unlink,
 	.mknod			= xfs_vn_mknod,
 	.rename			= xfs_vn_rename,
 	.permission		= xfs_vn_permission,
@@ -851,7 +834,13 @@ static const struct inode_operations xfs
 	.unlink			= xfs_vn_unlink,
 	.symlink		= xfs_vn_symlink,
 	.mkdir			= xfs_vn_mkdir,
-	.rmdir			= xfs_vn_rmdir,
+	/*
+	 * Yes, XFS uses the same method for rmdir and unlink.
+	 *
+	 * There are some subtile differences deeper in the code,
+	 * but we use S_ISDIR to check for those.
+	 */
+	.rmdir			= xfs_vn_unlink,
 	.mknod			= xfs_vn_mknod,
 	.rename			= xfs_vn_rename,
 	.permission		= xfs_vn_permission,
Index: linux-2.6-xfs/fs/xfs/xfs_vnodeops.h
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_vnodeops.h	2008-05-21 10:10:30.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_vnodeops.h	2008-05-21 10:21:31.000000000 +0200
@@ -31,8 +31,6 @@ int xfs_link(struct xfs_inode *tdp, stru
 		struct xfs_name *target_name);
 int xfs_mkdir(struct xfs_inode *dp, struct xfs_name *dir_name,
 		mode_t mode, struct xfs_inode **ipp, struct cred *credp);
-int xfs_rmdir(struct xfs_inode *dp, struct xfs_name *name,
-		struct xfs_inode *cdp);
 int xfs_readdir(struct xfs_inode	*dp, void *dirent, size_t bufsize,
 		       xfs_off_t *offset, filldir_t filldir);
 int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] merge xfs_rmdir into xfs_remove
  2008-05-21  8:25 ` Christoph Hellwig
@ 2008-06-16  6:18   ` Christoph Hellwig
  2008-07-23  8:06     ` Christoph Hellwig
  0 siblings, 1 reply; 6+ messages in thread
From: Christoph Hellwig @ 2008-06-16  6:18 UTC (permalink / raw)
  To: xfs

On Wed, May 21, 2008 at 10:25:48AM +0200, Christoph Hellwig wrote:
> On Fri, May 02, 2008 at 12:57:57PM +0200, Christoph Hellwig wrote:
> > xfs_remove and xfs_rmdir are almost the same with a little more work
> > performed in xfs_rmdir due to the . and .. entries.  This patch merges
> > xfs_rmdir into xfs_remove and performs these actions conditionally.
> > 
> > Also clean up the error handling which was a nightmare in both versions
> > before.
> 
> Updated for the case-insensitive filename changes.

And another update for the d_invalidate added on unlink/rmdir.

Index: linux-2.6-xfs/fs/xfs/xfs_vnodeops.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_vnodeops.c	2008-06-16 08:11:12.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_vnodeops.c	2008-06-16 08:14:16.000000000 +0200
@@ -2116,13 +2116,6 @@ again:
 #endif
 }
 
-#ifdef	DEBUG
-#define	REMOVE_DEBUG_TRACE(x)	{remove_which_error_return = (x);}
-int remove_which_error_return = 0;
-#else /* ! DEBUG */
-#define	REMOVE_DEBUG_TRACE(x)
-#endif	/* ! DEBUG */
-
 int
 xfs_remove(
 	xfs_inode_t             *dp,
@@ -2131,6 +2124,7 @@ xfs_remove(
 {
 	xfs_mount_t		*mp = dp->i_mount;
 	xfs_trans_t             *tp = NULL;
+	int			is_dir = S_ISDIR(ip->i_d.di_mode);
 	int                     error = 0;
 	xfs_bmap_free_t         free_list;
 	xfs_fsblock_t           first_block;
@@ -2138,8 +2132,11 @@ xfs_remove(
 	int			committed;
 	int			link_zero;
 	uint			resblks;
+	uint			trans;
+	uint			log_count;
 
 	xfs_itrace_entry(dp);
+	xfs_itrace_entry(ip);
 
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
@@ -2152,19 +2149,25 @@ xfs_remove(
 			return error;
 	}
 
-	xfs_itrace_entry(ip);
-	xfs_itrace_ref(ip);
-
 	error = XFS_QM_DQATTACH(mp, dp, 0);
-	if (!error)
-		error = XFS_QM_DQATTACH(mp, ip, 0);
-	if (error) {
-		REMOVE_DEBUG_TRACE(__LINE__);
+	if (error)
+		goto std_return;
+
+	error = XFS_QM_DQATTACH(mp, ip, 0);
+	if (error)
 		goto std_return;
+
+	if (is_dir) {
+		trans = XFS_TRANS_RMDIR;
+		log_count = XFS_DEFAULT_LOG_COUNT;
+	} else {
+		trans = XFS_TRANS_REMOVE;
+		log_count = XFS_REMOVE_LOG_COUNT;
 	}
 
-	tp = xfs_trans_alloc(mp, XFS_TRANS_REMOVE);
+	tp = xfs_trans_alloc(mp, trans);
 	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
+
 	/*
 	 * We try to get the real space reservation first,
 	 * allowing for directory btree deletion(s) implying
@@ -2176,25 +2179,21 @@ xfs_remove(
 	 */
 	resblks = XFS_REMOVE_SPACE_RES(mp);
 	error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
-			XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
+				  XFS_TRANS_PERM_LOG_RES, log_count);
 	if (error == ENOSPC) {
 		resblks = 0;
 		error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
-				XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
+					  XFS_TRANS_PERM_LOG_RES, log_count);
 	}
 	if (error) {
 		ASSERT(error != ENOSPC);
-		REMOVE_DEBUG_TRACE(__LINE__);
-		xfs_trans_cancel(tp, 0);
-		return error;
+		cancel_flags = 0;
+		goto out_trans_cancel;
 	}
 
 	error = xfs_lock_dir_and_entry(dp, ip);
-	if (error) {
-		REMOVE_DEBUG_TRACE(__LINE__);
-		xfs_trans_cancel(tp, cancel_flags);
-		goto std_return;
-	}
+	if (error)
+		goto out_trans_cancel;
 
 	/*
 	 * At this point, we've gotten both the directory and the entry
@@ -2207,6 +2206,21 @@ xfs_remove(
 	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 
 	/*
+	 * If we're removing a directory perform some additional validation.
+	 */
+	if (is_dir) {
+		ASSERT(ip->i_d.di_nlink >= 2);
+		if (ip->i_d.di_nlink != 2) {
+			error = XFS_ERROR(ENOTEMPTY);
+			goto out_trans_cancel;
+		}
+		if (!xfs_dir_isempty(ip)) {
+			error = XFS_ERROR(ENOTEMPTY);
+			goto out_trans_cancel;
+		}
+	}
+
+	/*
 	 * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
 	 */
 	XFS_BMAP_INIT(&free_list, &first_block);
@@ -2214,39 +2228,64 @@ xfs_remove(
 					&first_block, &free_list, resblks);
 	if (error) {
 		ASSERT(error != ENOENT);
-		REMOVE_DEBUG_TRACE(__LINE__);
-		goto error1;
+		goto out_bmap_cancel;
 	}
 	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 
+	/*
+	 * Bump the in memory generation count on the parent
+	 * directory so that other can know that it has changed.
+	 */
 	dp->i_gen++;
 	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 
-	error = xfs_droplink(tp, ip);
-	if (error) {
-		REMOVE_DEBUG_TRACE(__LINE__);
-		goto error1;
+	if (is_dir) {
+		/*
+		 * Drop the link from ip's "..".
+		 */
+		error = xfs_droplink(tp, dp);
+		if (error)
+			goto out_bmap_cancel;
+
+		/*
+		 * Drop the link from dp to ip.
+		 */
+		error = xfs_droplink(tp, ip);
+		if (error)
+			goto out_bmap_cancel;
+	} else {
+		/*
+		 * When removing a non-directory we need to log the parent
+		 * inode here for the i_gen update.  For a directory this is
+		 * done implicitly by the xfs_droplink call for the ".." entry.
+		 */
+		xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 	}
 
-	/* Determine if this is the last link while
+	/*
+	 * Drop the "." link from ip to self.
+	 */
+	error = xfs_droplink(tp, ip);
+	if (error)
+		goto out_bmap_cancel;
+
+	/*
+	 * Determine if this is the last link while
 	 * we are in the transaction.
 	 */
-	link_zero = (ip)->i_d.di_nlink==0;
+	link_zero = (ip->i_d.di_nlink == 0);
 
 	/*
 	 * If this is a synchronous mount, make sure that the
 	 * remove transaction goes to disk before returning to
 	 * the user.
 	 */
-	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
+	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
 		xfs_trans_set_sync(tp);
-	}
 
 	error = xfs_bmap_finish(&tp, &free_list, &committed);
-	if (error) {
-		REMOVE_DEBUG_TRACE(__LINE__);
-		goto error_rele;
-	}
+	if (error)
+		goto out_bmap_cancel;
 
 	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
 	if (error)
@@ -2258,39 +2297,27 @@ xfs_remove(
 	 * will get killed on last close in xfs_close() so we don't
 	 * have to worry about that.
 	 */
-	if (link_zero && xfs_inode_is_filestream(ip))
+	if (!is_dir && link_zero && xfs_inode_is_filestream(ip))
 		xfs_filestream_deassociate(ip);
 
 	xfs_itrace_exit(ip);
+	xfs_itrace_exit(dp);
 
-/*	Fall through to std_return with error = 0 */
  std_return:
 	if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
-		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
-				dp, DM_RIGHT_NULL,
-				NULL, DM_RIGHT_NULL,
-				name->name, NULL, ip->i_d.di_mode, error, 0);
+		XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dp, DM_RIGHT_NULL,
+				NULL, DM_RIGHT_NULL, name->name, NULL,
+				ip->i_d.di_mode, error, 0);
 	}
+
 	return error;
 
- error1:
+ out_bmap_cancel:
 	xfs_bmap_cancel(&free_list);
 	cancel_flags |= XFS_TRANS_ABORT;
+ out_trans_cancel:
 	xfs_trans_cancel(tp, cancel_flags);
 	goto std_return;
-
- error_rele:
-	/*
-	 * In this case make sure to not release the inode until after
-	 * the current transaction is aborted.  Releasing it beforehand
-	 * can cause us to go to xfs_inactive and start a recursive
-	 * transaction which can easily deadlock with the current one.
-	 */
-	xfs_bmap_cancel(&free_list);
-	cancel_flags |= XFS_TRANS_ABORT;
-	xfs_trans_cancel(tp, cancel_flags);
-
-	goto std_return;
 }
 
 int
@@ -2656,186 +2683,6 @@ std_return:
 }
 
 int
-xfs_rmdir(
-	xfs_inode_t             *dp,
-	struct xfs_name		*name,
-	xfs_inode_t		*cdp)
-{
-	xfs_mount_t		*mp = dp->i_mount;
-	xfs_trans_t             *tp;
-	int                     error;
-	xfs_bmap_free_t         free_list;
-	xfs_fsblock_t           first_block;
-	int			cancel_flags;
-	int			committed;
-	int			last_cdp_link;
-	uint			resblks;
-
-	xfs_itrace_entry(dp);
-
-	if (XFS_FORCED_SHUTDOWN(mp))
-		return XFS_ERROR(EIO);
-
-	if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) {
-		error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE,
-					dp, DM_RIGHT_NULL,
-					NULL, DM_RIGHT_NULL, name->name,
-					NULL, cdp->i_d.di_mode, 0, 0);
-		if (error)
-			return XFS_ERROR(error);
-	}
-
-	/*
-	 * Get the dquots for the inodes.
-	 */
-	error = XFS_QM_DQATTACH(mp, dp, 0);
-	if (!error)
-		error = XFS_QM_DQATTACH(mp, cdp, 0);
-	if (error) {
-		REMOVE_DEBUG_TRACE(__LINE__);
-		goto std_return;
-	}
-
-	tp = xfs_trans_alloc(mp, XFS_TRANS_RMDIR);
-	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
-	/*
-	 * We try to get the real space reservation first,
-	 * allowing for directory btree deletion(s) implying
-	 * possible bmap insert(s).  If we can't get the space
-	 * reservation then we use 0 instead, and avoid the bmap
-	 * btree insert(s) in the directory code by, if the bmap
-	 * insert tries to happen, instead trimming the LAST
-	 * block from the directory.
-	 */
-	resblks = XFS_REMOVE_SPACE_RES(mp);
-	error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
-			XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
-	if (error == ENOSPC) {
-		resblks = 0;
-		error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
-				XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
-	}
-	if (error) {
-		ASSERT(error != ENOSPC);
-		cancel_flags = 0;
-		goto error_return;
-	}
-	XFS_BMAP_INIT(&free_list, &first_block);
-
-	/*
-	 * Now lock the child directory inode and the parent directory
-	 * inode in the proper order.  This will take care of validating
-	 * that the directory entry for the child directory inode has
-	 * not changed while we were obtaining a log reservation.
-	 */
-	error = xfs_lock_dir_and_entry(dp, cdp);
-	if (error) {
-		xfs_trans_cancel(tp, cancel_flags);
-		goto std_return;
-	}
-
-	IHOLD(dp);
-	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
-
-	IHOLD(cdp);
-	xfs_trans_ijoin(tp, cdp, XFS_ILOCK_EXCL);
-
-	ASSERT(cdp->i_d.di_nlink >= 2);
-	if (cdp->i_d.di_nlink != 2) {
-		error = XFS_ERROR(ENOTEMPTY);
-		goto error_return;
-	}
-	if (!xfs_dir_isempty(cdp)) {
-		error = XFS_ERROR(ENOTEMPTY);
-		goto error_return;
-	}
-
-	error = xfs_dir_removename(tp, dp, name, cdp->i_ino,
-					&first_block, &free_list, resblks);
-	if (error)
-		goto error1;
-
-	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
-
-	/*
-	 * Bump the in memory generation count on the parent
-	 * directory so that other can know that it has changed.
-	 */
-	dp->i_gen++;
-
-	/*
-	 * Drop the link from cdp's "..".
-	 */
-	error = xfs_droplink(tp, dp);
-	if (error) {
-		goto error1;
-	}
-
-	/*
-	 * Drop the link from dp to cdp.
-	 */
-	error = xfs_droplink(tp, cdp);
-	if (error) {
-		goto error1;
-	}
-
-	/*
-	 * Drop the "." link from cdp to self.
-	 */
-	error = xfs_droplink(tp, cdp);
-	if (error) {
-		goto error1;
-	}
-
-	/* Determine these before committing transaction */
-	last_cdp_link = (cdp)->i_d.di_nlink==0;
-
-	/*
-	 * If this is a synchronous mount, make sure that the
-	 * rmdir transaction goes to disk before returning to
-	 * the user.
-	 */
-	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
-		xfs_trans_set_sync(tp);
-	}
-
-	error = xfs_bmap_finish (&tp, &free_list, &committed);
-	if (error) {
-		xfs_bmap_cancel(&free_list);
-		xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
-				 XFS_TRANS_ABORT));
-		goto std_return;
-	}
-
-	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
-	if (error) {
-		goto std_return;
-	}
-
-
-	/* Fall through to std_return with error = 0 or the errno
-	 * from xfs_trans_commit. */
- std_return:
-	if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
-		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
-					dp, DM_RIGHT_NULL,
-					NULL, DM_RIGHT_NULL,
-					name->name, NULL, cdp->i_d.di_mode,
-					error, 0);
-	}
-	return error;
-
- error1:
-	xfs_bmap_cancel(&free_list);
-	cancel_flags |= XFS_TRANS_ABORT;
-	/* FALLTHROUGH */
-
- error_return:
-	xfs_trans_cancel(tp, cancel_flags);
-	goto std_return;
-}
-
-int
 xfs_symlink(
 	xfs_inode_t		*dp,
 	struct xfs_name		*link_name,
Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_iops.c	2008-06-16 08:14:12.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c	2008-06-16 08:15:00.000000000 +0200
@@ -252,8 +252,7 @@ STATIC void
 xfs_cleanup_inode(
 	struct inode	*dir,
 	struct inode	*inode,
-	struct dentry	*dentry,
-	int		mode)
+	struct dentry	*dentry)
 {
 	struct xfs_name	teardown;
 
@@ -264,10 +263,7 @@ xfs_cleanup_inode(
 	 */
 	xfs_dentry_to_name(&teardown, dentry);
 
-	if (S_ISDIR(mode))
-		xfs_rmdir(XFS_I(dir), &teardown, XFS_I(inode));
-	else
-		xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
+	xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
 	iput(inode);
 }
 
@@ -349,7 +345,7 @@ xfs_vn_mknod(
 	return -error;
 
  out_cleanup_inode:
-	xfs_cleanup_inode(dir, inode, dentry, mode);
+	xfs_cleanup_inode(dir, inode, dentry);
  out_free_acl:
 	if (default_acl)
 		_ACL_FREE(default_acl);
@@ -525,38 +521,12 @@ xfs_vn_symlink(
 	return 0;
 
  out_cleanup_inode:
-	xfs_cleanup_inode(dir, inode, dentry, 0);
+	xfs_cleanup_inode(dir, inode, dentry);
  out:
 	return -error;
 }
 
 STATIC int
-xfs_vn_rmdir(
-	struct inode	*dir,
-	struct dentry	*dentry)
-{
-	struct inode	*inode = dentry->d_inode;
-	struct xfs_name	name;
-	int		error;
-
-	xfs_dentry_to_name(&name, dentry);
-
-	error = xfs_rmdir(XFS_I(dir), &name, XFS_I(inode));
-	if (likely(!error)) {
-		xfs_validate_fields(inode);
-		xfs_validate_fields(dir);
-		/*
-		 * With rmdir, the VFS makes the dentry "negative": no inode,
-		 * but still hashed. This is incompatible with case-insensitive
-		 * mode, so invalidate (unhash) the dentry in CI-mode.
-		 */
-		if (xfs_sb_version_hasasciici(&XFS_M(dir->i_sb)->m_sb))
-			d_invalidate(dentry);
-	}
-	return -error;
-}
-
-STATIC int
 xfs_vn_rename(
 	struct inode	*odir,
 	struct dentry	*odentry,
@@ -850,7 +820,13 @@ static const struct inode_operations xfs
 	.unlink			= xfs_vn_unlink,
 	.symlink		= xfs_vn_symlink,
 	.mkdir			= xfs_vn_mkdir,
-	.rmdir			= xfs_vn_rmdir,
+	/*
+	 * Yes, XFS uses the same method for rmdir and unlink.
+	 *
+	 * There are some subtile differences deeper in the code,
+	 * but we use S_ISDIR to check for those.
+	 */
+	.rmdir			= xfs_vn_unlink,
 	.mknod			= xfs_vn_mknod,
 	.rename			= xfs_vn_rename,
 	.permission		= xfs_vn_permission,
@@ -869,7 +845,13 @@ static const struct inode_operations xfs
 	.unlink			= xfs_vn_unlink,
 	.symlink		= xfs_vn_symlink,
 	.mkdir			= xfs_vn_mkdir,
-	.rmdir			= xfs_vn_rmdir,
+	/*
+	 * Yes, XFS uses the same method for rmdir and unlink.
+	 *
+	 * There are some subtile differences deeper in the code,
+	 * but we use S_ISDIR to check for those.
+	 */
+	.rmdir			= xfs_vn_unlink,
 	.mknod			= xfs_vn_mknod,
 	.rename			= xfs_vn_rename,
 	.permission		= xfs_vn_permission,
Index: linux-2.6-xfs/fs/xfs/xfs_vnodeops.h
===================================================================
--- linux-2.6-xfs.orig/fs/xfs/xfs_vnodeops.h	2008-06-16 08:11:12.000000000 +0200
+++ linux-2.6-xfs/fs/xfs/xfs_vnodeops.h	2008-06-16 08:14:16.000000000 +0200
@@ -31,8 +31,6 @@ int xfs_link(struct xfs_inode *tdp, stru
 		struct xfs_name *target_name);
 int xfs_mkdir(struct xfs_inode *dp, struct xfs_name *dir_name,
 		mode_t mode, struct xfs_inode **ipp, struct cred *credp);
-int xfs_rmdir(struct xfs_inode *dp, struct xfs_name *name,
-		struct xfs_inode *cdp);
 int xfs_readdir(struct xfs_inode	*dp, void *dirent, size_t bufsize,
 		       xfs_off_t *offset, filldir_t filldir);
 int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] merge xfs_rmdir into xfs_remove
  2008-06-16  6:18   ` Christoph Hellwig
@ 2008-07-23  8:06     ` Christoph Hellwig
  2008-07-23  8:12       ` Christoph Hellwig
  0 siblings, 1 reply; 6+ messages in thread
From: Christoph Hellwig @ 2008-07-23  8:06 UTC (permalink / raw)
  To: xfs

ping?

On Mon, Jun 16, 2008 at 08:18:39AM +0200, Christoph Hellwig wrote:
> On Wed, May 21, 2008 at 10:25:48AM +0200, Christoph Hellwig wrote:
> > On Fri, May 02, 2008 at 12:57:57PM +0200, Christoph Hellwig wrote:
> > > xfs_remove and xfs_rmdir are almost the same with a little more work
> > > performed in xfs_rmdir due to the . and .. entries.  This patch merges
> > > xfs_rmdir into xfs_remove and performs these actions conditionally.
> > > 
> > > Also clean up the error handling which was a nightmare in both versions
> > > before.
> > 
> > Updated for the case-insensitive filename changes.
> 
> And another update for the d_invalidate added on unlink/rmdir.
> 
> Index: linux-2.6-xfs/fs/xfs/xfs_vnodeops.c
> ===================================================================
> --- linux-2.6-xfs.orig/fs/xfs/xfs_vnodeops.c	2008-06-16 08:11:12.000000000 +0200
> +++ linux-2.6-xfs/fs/xfs/xfs_vnodeops.c	2008-06-16 08:14:16.000000000 +0200
> @@ -2116,13 +2116,6 @@ again:
>  #endif
>  }
>  
> -#ifdef	DEBUG
> -#define	REMOVE_DEBUG_TRACE(x)	{remove_which_error_return = (x);}
> -int remove_which_error_return = 0;
> -#else /* ! DEBUG */
> -#define	REMOVE_DEBUG_TRACE(x)
> -#endif	/* ! DEBUG */
> -
>  int
>  xfs_remove(
>  	xfs_inode_t             *dp,
> @@ -2131,6 +2124,7 @@ xfs_remove(
>  {
>  	xfs_mount_t		*mp = dp->i_mount;
>  	xfs_trans_t             *tp = NULL;
> +	int			is_dir = S_ISDIR(ip->i_d.di_mode);
>  	int                     error = 0;
>  	xfs_bmap_free_t         free_list;
>  	xfs_fsblock_t           first_block;
> @@ -2138,8 +2132,11 @@ xfs_remove(
>  	int			committed;
>  	int			link_zero;
>  	uint			resblks;
> +	uint			trans;
> +	uint			log_count;
>  
>  	xfs_itrace_entry(dp);
> +	xfs_itrace_entry(ip);
>  
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return XFS_ERROR(EIO);
> @@ -2152,19 +2149,25 @@ xfs_remove(
>  			return error;
>  	}
>  
> -	xfs_itrace_entry(ip);
> -	xfs_itrace_ref(ip);
> -
>  	error = XFS_QM_DQATTACH(mp, dp, 0);
> -	if (!error)
> -		error = XFS_QM_DQATTACH(mp, ip, 0);
> -	if (error) {
> -		REMOVE_DEBUG_TRACE(__LINE__);
> +	if (error)
> +		goto std_return;
> +
> +	error = XFS_QM_DQATTACH(mp, ip, 0);
> +	if (error)
>  		goto std_return;
> +
> +	if (is_dir) {
> +		trans = XFS_TRANS_RMDIR;
> +		log_count = XFS_DEFAULT_LOG_COUNT;
> +	} else {
> +		trans = XFS_TRANS_REMOVE;
> +		log_count = XFS_REMOVE_LOG_COUNT;
>  	}
>  
> -	tp = xfs_trans_alloc(mp, XFS_TRANS_REMOVE);
> +	tp = xfs_trans_alloc(mp, trans);
>  	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
> +
>  	/*
>  	 * We try to get the real space reservation first,
>  	 * allowing for directory btree deletion(s) implying
> @@ -2176,25 +2179,21 @@ xfs_remove(
>  	 */
>  	resblks = XFS_REMOVE_SPACE_RES(mp);
>  	error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
> -			XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
> +				  XFS_TRANS_PERM_LOG_RES, log_count);
>  	if (error == ENOSPC) {
>  		resblks = 0;
>  		error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
> -				XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
> +					  XFS_TRANS_PERM_LOG_RES, log_count);
>  	}
>  	if (error) {
>  		ASSERT(error != ENOSPC);
> -		REMOVE_DEBUG_TRACE(__LINE__);
> -		xfs_trans_cancel(tp, 0);
> -		return error;
> +		cancel_flags = 0;
> +		goto out_trans_cancel;
>  	}
>  
>  	error = xfs_lock_dir_and_entry(dp, ip);
> -	if (error) {
> -		REMOVE_DEBUG_TRACE(__LINE__);
> -		xfs_trans_cancel(tp, cancel_flags);
> -		goto std_return;
> -	}
> +	if (error)
> +		goto out_trans_cancel;
>  
>  	/*
>  	 * At this point, we've gotten both the directory and the entry
> @@ -2207,6 +2206,21 @@ xfs_remove(
>  	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
>  
>  	/*
> +	 * If we're removing a directory perform some additional validation.
> +	 */
> +	if (is_dir) {
> +		ASSERT(ip->i_d.di_nlink >= 2);
> +		if (ip->i_d.di_nlink != 2) {
> +			error = XFS_ERROR(ENOTEMPTY);
> +			goto out_trans_cancel;
> +		}
> +		if (!xfs_dir_isempty(ip)) {
> +			error = XFS_ERROR(ENOTEMPTY);
> +			goto out_trans_cancel;
> +		}
> +	}
> +
> +	/*
>  	 * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
>  	 */
>  	XFS_BMAP_INIT(&free_list, &first_block);
> @@ -2214,39 +2228,64 @@ xfs_remove(
>  					&first_block, &free_list, resblks);
>  	if (error) {
>  		ASSERT(error != ENOENT);
> -		REMOVE_DEBUG_TRACE(__LINE__);
> -		goto error1;
> +		goto out_bmap_cancel;
>  	}
>  	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
>  
> +	/*
> +	 * Bump the in memory generation count on the parent
> +	 * directory so that other can know that it has changed.
> +	 */
>  	dp->i_gen++;
>  	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
>  
> -	error = xfs_droplink(tp, ip);
> -	if (error) {
> -		REMOVE_DEBUG_TRACE(__LINE__);
> -		goto error1;
> +	if (is_dir) {
> +		/*
> +		 * Drop the link from ip's "..".
> +		 */
> +		error = xfs_droplink(tp, dp);
> +		if (error)
> +			goto out_bmap_cancel;
> +
> +		/*
> +		 * Drop the link from dp to ip.
> +		 */
> +		error = xfs_droplink(tp, ip);
> +		if (error)
> +			goto out_bmap_cancel;
> +	} else {
> +		/*
> +		 * When removing a non-directory we need to log the parent
> +		 * inode here for the i_gen update.  For a directory this is
> +		 * done implicitly by the xfs_droplink call for the ".." entry.
> +		 */
> +		xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
>  	}
>  
> -	/* Determine if this is the last link while
> +	/*
> +	 * Drop the "." link from ip to self.
> +	 */
> +	error = xfs_droplink(tp, ip);
> +	if (error)
> +		goto out_bmap_cancel;
> +
> +	/*
> +	 * Determine if this is the last link while
>  	 * we are in the transaction.
>  	 */
> -	link_zero = (ip)->i_d.di_nlink==0;
> +	link_zero = (ip->i_d.di_nlink == 0);
>  
>  	/*
>  	 * If this is a synchronous mount, make sure that the
>  	 * remove transaction goes to disk before returning to
>  	 * the user.
>  	 */
> -	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
> +	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
>  		xfs_trans_set_sync(tp);
> -	}
>  
>  	error = xfs_bmap_finish(&tp, &free_list, &committed);
> -	if (error) {
> -		REMOVE_DEBUG_TRACE(__LINE__);
> -		goto error_rele;
> -	}
> +	if (error)
> +		goto out_bmap_cancel;
>  
>  	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
>  	if (error)
> @@ -2258,39 +2297,27 @@ xfs_remove(
>  	 * will get killed on last close in xfs_close() so we don't
>  	 * have to worry about that.
>  	 */
> -	if (link_zero && xfs_inode_is_filestream(ip))
> +	if (!is_dir && link_zero && xfs_inode_is_filestream(ip))
>  		xfs_filestream_deassociate(ip);
>  
>  	xfs_itrace_exit(ip);
> +	xfs_itrace_exit(dp);
>  
> -/*	Fall through to std_return with error = 0 */
>   std_return:
>  	if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
> -		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
> -				dp, DM_RIGHT_NULL,
> -				NULL, DM_RIGHT_NULL,
> -				name->name, NULL, ip->i_d.di_mode, error, 0);
> +		XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dp, DM_RIGHT_NULL,
> +				NULL, DM_RIGHT_NULL, name->name, NULL,
> +				ip->i_d.di_mode, error, 0);
>  	}
> +
>  	return error;
>  
> - error1:
> + out_bmap_cancel:
>  	xfs_bmap_cancel(&free_list);
>  	cancel_flags |= XFS_TRANS_ABORT;
> + out_trans_cancel:
>  	xfs_trans_cancel(tp, cancel_flags);
>  	goto std_return;
> -
> - error_rele:
> -	/*
> -	 * In this case make sure to not release the inode until after
> -	 * the current transaction is aborted.  Releasing it beforehand
> -	 * can cause us to go to xfs_inactive and start a recursive
> -	 * transaction which can easily deadlock with the current one.
> -	 */
> -	xfs_bmap_cancel(&free_list);
> -	cancel_flags |= XFS_TRANS_ABORT;
> -	xfs_trans_cancel(tp, cancel_flags);
> -
> -	goto std_return;
>  }
>  
>  int
> @@ -2656,186 +2683,6 @@ std_return:
>  }
>  
>  int
> -xfs_rmdir(
> -	xfs_inode_t             *dp,
> -	struct xfs_name		*name,
> -	xfs_inode_t		*cdp)
> -{
> -	xfs_mount_t		*mp = dp->i_mount;
> -	xfs_trans_t             *tp;
> -	int                     error;
> -	xfs_bmap_free_t         free_list;
> -	xfs_fsblock_t           first_block;
> -	int			cancel_flags;
> -	int			committed;
> -	int			last_cdp_link;
> -	uint			resblks;
> -
> -	xfs_itrace_entry(dp);
> -
> -	if (XFS_FORCED_SHUTDOWN(mp))
> -		return XFS_ERROR(EIO);
> -
> -	if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) {
> -		error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE,
> -					dp, DM_RIGHT_NULL,
> -					NULL, DM_RIGHT_NULL, name->name,
> -					NULL, cdp->i_d.di_mode, 0, 0);
> -		if (error)
> -			return XFS_ERROR(error);
> -	}
> -
> -	/*
> -	 * Get the dquots for the inodes.
> -	 */
> -	error = XFS_QM_DQATTACH(mp, dp, 0);
> -	if (!error)
> -		error = XFS_QM_DQATTACH(mp, cdp, 0);
> -	if (error) {
> -		REMOVE_DEBUG_TRACE(__LINE__);
> -		goto std_return;
> -	}
> -
> -	tp = xfs_trans_alloc(mp, XFS_TRANS_RMDIR);
> -	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
> -	/*
> -	 * We try to get the real space reservation first,
> -	 * allowing for directory btree deletion(s) implying
> -	 * possible bmap insert(s).  If we can't get the space
> -	 * reservation then we use 0 instead, and avoid the bmap
> -	 * btree insert(s) in the directory code by, if the bmap
> -	 * insert tries to happen, instead trimming the LAST
> -	 * block from the directory.
> -	 */
> -	resblks = XFS_REMOVE_SPACE_RES(mp);
> -	error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
> -			XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
> -	if (error == ENOSPC) {
> -		resblks = 0;
> -		error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
> -				XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
> -	}
> -	if (error) {
> -		ASSERT(error != ENOSPC);
> -		cancel_flags = 0;
> -		goto error_return;
> -	}
> -	XFS_BMAP_INIT(&free_list, &first_block);
> -
> -	/*
> -	 * Now lock the child directory inode and the parent directory
> -	 * inode in the proper order.  This will take care of validating
> -	 * that the directory entry for the child directory inode has
> -	 * not changed while we were obtaining a log reservation.
> -	 */
> -	error = xfs_lock_dir_and_entry(dp, cdp);
> -	if (error) {
> -		xfs_trans_cancel(tp, cancel_flags);
> -		goto std_return;
> -	}
> -
> -	IHOLD(dp);
> -	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
> -
> -	IHOLD(cdp);
> -	xfs_trans_ijoin(tp, cdp, XFS_ILOCK_EXCL);
> -
> -	ASSERT(cdp->i_d.di_nlink >= 2);
> -	if (cdp->i_d.di_nlink != 2) {
> -		error = XFS_ERROR(ENOTEMPTY);
> -		goto error_return;
> -	}
> -	if (!xfs_dir_isempty(cdp)) {
> -		error = XFS_ERROR(ENOTEMPTY);
> -		goto error_return;
> -	}
> -
> -	error = xfs_dir_removename(tp, dp, name, cdp->i_ino,
> -					&first_block, &free_list, resblks);
> -	if (error)
> -		goto error1;
> -
> -	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
> -
> -	/*
> -	 * Bump the in memory generation count on the parent
> -	 * directory so that other can know that it has changed.
> -	 */
> -	dp->i_gen++;
> -
> -	/*
> -	 * Drop the link from cdp's "..".
> -	 */
> -	error = xfs_droplink(tp, dp);
> -	if (error) {
> -		goto error1;
> -	}
> -
> -	/*
> -	 * Drop the link from dp to cdp.
> -	 */
> -	error = xfs_droplink(tp, cdp);
> -	if (error) {
> -		goto error1;
> -	}
> -
> -	/*
> -	 * Drop the "." link from cdp to self.
> -	 */
> -	error = xfs_droplink(tp, cdp);
> -	if (error) {
> -		goto error1;
> -	}
> -
> -	/* Determine these before committing transaction */
> -	last_cdp_link = (cdp)->i_d.di_nlink==0;
> -
> -	/*
> -	 * If this is a synchronous mount, make sure that the
> -	 * rmdir transaction goes to disk before returning to
> -	 * the user.
> -	 */
> -	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
> -		xfs_trans_set_sync(tp);
> -	}
> -
> -	error = xfs_bmap_finish (&tp, &free_list, &committed);
> -	if (error) {
> -		xfs_bmap_cancel(&free_list);
> -		xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
> -				 XFS_TRANS_ABORT));
> -		goto std_return;
> -	}
> -
> -	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
> -	if (error) {
> -		goto std_return;
> -	}
> -
> -
> -	/* Fall through to std_return with error = 0 or the errno
> -	 * from xfs_trans_commit. */
> - std_return:
> -	if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
> -		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
> -					dp, DM_RIGHT_NULL,
> -					NULL, DM_RIGHT_NULL,
> -					name->name, NULL, cdp->i_d.di_mode,
> -					error, 0);
> -	}
> -	return error;
> -
> - error1:
> -	xfs_bmap_cancel(&free_list);
> -	cancel_flags |= XFS_TRANS_ABORT;
> -	/* FALLTHROUGH */
> -
> - error_return:
> -	xfs_trans_cancel(tp, cancel_flags);
> -	goto std_return;
> -}
> -
> -int
>  xfs_symlink(
>  	xfs_inode_t		*dp,
>  	struct xfs_name		*link_name,
> Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c
> ===================================================================
> --- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_iops.c	2008-06-16 08:14:12.000000000 +0200
> +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c	2008-06-16 08:15:00.000000000 +0200
> @@ -252,8 +252,7 @@ STATIC void
>  xfs_cleanup_inode(
>  	struct inode	*dir,
>  	struct inode	*inode,
> -	struct dentry	*dentry,
> -	int		mode)
> +	struct dentry	*dentry)
>  {
>  	struct xfs_name	teardown;
>  
> @@ -264,10 +263,7 @@ xfs_cleanup_inode(
>  	 */
>  	xfs_dentry_to_name(&teardown, dentry);
>  
> -	if (S_ISDIR(mode))
> -		xfs_rmdir(XFS_I(dir), &teardown, XFS_I(inode));
> -	else
> -		xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
> +	xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
>  	iput(inode);
>  }
>  
> @@ -349,7 +345,7 @@ xfs_vn_mknod(
>  	return -error;
>  
>   out_cleanup_inode:
> -	xfs_cleanup_inode(dir, inode, dentry, mode);
> +	xfs_cleanup_inode(dir, inode, dentry);
>   out_free_acl:
>  	if (default_acl)
>  		_ACL_FREE(default_acl);
> @@ -525,38 +521,12 @@ xfs_vn_symlink(
>  	return 0;
>  
>   out_cleanup_inode:
> -	xfs_cleanup_inode(dir, inode, dentry, 0);
> +	xfs_cleanup_inode(dir, inode, dentry);
>   out:
>  	return -error;
>  }
>  
>  STATIC int
> -xfs_vn_rmdir(
> -	struct inode	*dir,
> -	struct dentry	*dentry)
> -{
> -	struct inode	*inode = dentry->d_inode;
> -	struct xfs_name	name;
> -	int		error;
> -
> -	xfs_dentry_to_name(&name, dentry);
> -
> -	error = xfs_rmdir(XFS_I(dir), &name, XFS_I(inode));
> -	if (likely(!error)) {
> -		xfs_validate_fields(inode);
> -		xfs_validate_fields(dir);
> -		/*
> -		 * With rmdir, the VFS makes the dentry "negative": no inode,
> -		 * but still hashed. This is incompatible with case-insensitive
> -		 * mode, so invalidate (unhash) the dentry in CI-mode.
> -		 */
> -		if (xfs_sb_version_hasasciici(&XFS_M(dir->i_sb)->m_sb))
> -			d_invalidate(dentry);
> -	}
> -	return -error;
> -}
> -
> -STATIC int
>  xfs_vn_rename(
>  	struct inode	*odir,
>  	struct dentry	*odentry,
> @@ -850,7 +820,13 @@ static const struct inode_operations xfs
>  	.unlink			= xfs_vn_unlink,
>  	.symlink		= xfs_vn_symlink,
>  	.mkdir			= xfs_vn_mkdir,
> -	.rmdir			= xfs_vn_rmdir,
> +	/*
> +	 * Yes, XFS uses the same method for rmdir and unlink.
> +	 *
> +	 * There are some subtile differences deeper in the code,
> +	 * but we use S_ISDIR to check for those.
> +	 */
> +	.rmdir			= xfs_vn_unlink,
>  	.mknod			= xfs_vn_mknod,
>  	.rename			= xfs_vn_rename,
>  	.permission		= xfs_vn_permission,
> @@ -869,7 +845,13 @@ static const struct inode_operations xfs
>  	.unlink			= xfs_vn_unlink,
>  	.symlink		= xfs_vn_symlink,
>  	.mkdir			= xfs_vn_mkdir,
> -	.rmdir			= xfs_vn_rmdir,
> +	/*
> +	 * Yes, XFS uses the same method for rmdir and unlink.
> +	 *
> +	 * There are some subtile differences deeper in the code,
> +	 * but we use S_ISDIR to check for those.
> +	 */
> +	.rmdir			= xfs_vn_unlink,
>  	.mknod			= xfs_vn_mknod,
>  	.rename			= xfs_vn_rename,
>  	.permission		= xfs_vn_permission,
> Index: linux-2.6-xfs/fs/xfs/xfs_vnodeops.h
> ===================================================================
> --- linux-2.6-xfs.orig/fs/xfs/xfs_vnodeops.h	2008-06-16 08:11:12.000000000 +0200
> +++ linux-2.6-xfs/fs/xfs/xfs_vnodeops.h	2008-06-16 08:14:16.000000000 +0200
> @@ -31,8 +31,6 @@ int xfs_link(struct xfs_inode *tdp, stru
>  		struct xfs_name *target_name);
>  int xfs_mkdir(struct xfs_inode *dp, struct xfs_name *dir_name,
>  		mode_t mode, struct xfs_inode **ipp, struct cred *credp);
> -int xfs_rmdir(struct xfs_inode *dp, struct xfs_name *name,
> -		struct xfs_inode *cdp);
>  int xfs_readdir(struct xfs_inode	*dp, void *dirent, size_t bufsize,
>  		       xfs_off_t *offset, filldir_t filldir);
>  int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,
---end quoted text---

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] merge xfs_rmdir into xfs_remove
  2008-07-23  8:06     ` Christoph Hellwig
@ 2008-07-23  8:12       ` Christoph Hellwig
  0 siblings, 0 replies; 6+ messages in thread
From: Christoph Hellwig @ 2008-07-23  8:12 UTC (permalink / raw)
  To: xfs

Oops, sorry.  This one obviously is in already, I men to ping from 2/2
from this series.

On Wed, Jul 23, 2008 at 10:06:18AM +0200, Christoph Hellwig wrote:
> ping?
> 
> On Mon, Jun 16, 2008 at 08:18:39AM +0200, Christoph Hellwig wrote:
> > On Wed, May 21, 2008 at 10:25:48AM +0200, Christoph Hellwig wrote:
> > > On Fri, May 02, 2008 at 12:57:57PM +0200, Christoph Hellwig wrote:
> > > > xfs_remove and xfs_rmdir are almost the same with a little more work
> > > > performed in xfs_rmdir due to the . and .. entries.  This patch merges
> > > > xfs_rmdir into xfs_remove and performs these actions conditionally.
> > > > 
> > > > Also clean up the error handling which was a nightmare in both versions
> > > > before.
> > > 
> > > Updated for the case-insensitive filename changes.
> > 
> > And another update for the d_invalidate added on unlink/rmdir.
> > 
> > Index: linux-2.6-xfs/fs/xfs/xfs_vnodeops.c
> > ===================================================================
> > --- linux-2.6-xfs.orig/fs/xfs/xfs_vnodeops.c	2008-06-16 08:11:12.000000000 +0200
> > +++ linux-2.6-xfs/fs/xfs/xfs_vnodeops.c	2008-06-16 08:14:16.000000000 +0200
> > @@ -2116,13 +2116,6 @@ again:
> >  #endif
> >  }
> >  
> > -#ifdef	DEBUG
> > -#define	REMOVE_DEBUG_TRACE(x)	{remove_which_error_return = (x);}
> > -int remove_which_error_return = 0;
> > -#else /* ! DEBUG */
> > -#define	REMOVE_DEBUG_TRACE(x)
> > -#endif	/* ! DEBUG */
> > -
> >  int
> >  xfs_remove(
> >  	xfs_inode_t             *dp,
> > @@ -2131,6 +2124,7 @@ xfs_remove(
> >  {
> >  	xfs_mount_t		*mp = dp->i_mount;
> >  	xfs_trans_t             *tp = NULL;
> > +	int			is_dir = S_ISDIR(ip->i_d.di_mode);
> >  	int                     error = 0;
> >  	xfs_bmap_free_t         free_list;
> >  	xfs_fsblock_t           first_block;
> > @@ -2138,8 +2132,11 @@ xfs_remove(
> >  	int			committed;
> >  	int			link_zero;
> >  	uint			resblks;
> > +	uint			trans;
> > +	uint			log_count;
> >  
> >  	xfs_itrace_entry(dp);
> > +	xfs_itrace_entry(ip);
> >  
> >  	if (XFS_FORCED_SHUTDOWN(mp))
> >  		return XFS_ERROR(EIO);
> > @@ -2152,19 +2149,25 @@ xfs_remove(
> >  			return error;
> >  	}
> >  
> > -	xfs_itrace_entry(ip);
> > -	xfs_itrace_ref(ip);
> > -
> >  	error = XFS_QM_DQATTACH(mp, dp, 0);
> > -	if (!error)
> > -		error = XFS_QM_DQATTACH(mp, ip, 0);
> > -	if (error) {
> > -		REMOVE_DEBUG_TRACE(__LINE__);
> > +	if (error)
> > +		goto std_return;
> > +
> > +	error = XFS_QM_DQATTACH(mp, ip, 0);
> > +	if (error)
> >  		goto std_return;
> > +
> > +	if (is_dir) {
> > +		trans = XFS_TRANS_RMDIR;
> > +		log_count = XFS_DEFAULT_LOG_COUNT;
> > +	} else {
> > +		trans = XFS_TRANS_REMOVE;
> > +		log_count = XFS_REMOVE_LOG_COUNT;
> >  	}
> >  
> > -	tp = xfs_trans_alloc(mp, XFS_TRANS_REMOVE);
> > +	tp = xfs_trans_alloc(mp, trans);
> >  	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
> > +
> >  	/*
> >  	 * We try to get the real space reservation first,
> >  	 * allowing for directory btree deletion(s) implying
> > @@ -2176,25 +2179,21 @@ xfs_remove(
> >  	 */
> >  	resblks = XFS_REMOVE_SPACE_RES(mp);
> >  	error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
> > -			XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
> > +				  XFS_TRANS_PERM_LOG_RES, log_count);
> >  	if (error == ENOSPC) {
> >  		resblks = 0;
> >  		error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
> > -				XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
> > +					  XFS_TRANS_PERM_LOG_RES, log_count);
> >  	}
> >  	if (error) {
> >  		ASSERT(error != ENOSPC);
> > -		REMOVE_DEBUG_TRACE(__LINE__);
> > -		xfs_trans_cancel(tp, 0);
> > -		return error;
> > +		cancel_flags = 0;
> > +		goto out_trans_cancel;
> >  	}
> >  
> >  	error = xfs_lock_dir_and_entry(dp, ip);
> > -	if (error) {
> > -		REMOVE_DEBUG_TRACE(__LINE__);
> > -		xfs_trans_cancel(tp, cancel_flags);
> > -		goto std_return;
> > -	}
> > +	if (error)
> > +		goto out_trans_cancel;
> >  
> >  	/*
> >  	 * At this point, we've gotten both the directory and the entry
> > @@ -2207,6 +2206,21 @@ xfs_remove(
> >  	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
> >  
> >  	/*
> > +	 * If we're removing a directory perform some additional validation.
> > +	 */
> > +	if (is_dir) {
> > +		ASSERT(ip->i_d.di_nlink >= 2);
> > +		if (ip->i_d.di_nlink != 2) {
> > +			error = XFS_ERROR(ENOTEMPTY);
> > +			goto out_trans_cancel;
> > +		}
> > +		if (!xfs_dir_isempty(ip)) {
> > +			error = XFS_ERROR(ENOTEMPTY);
> > +			goto out_trans_cancel;
> > +		}
> > +	}
> > +
> > +	/*
> >  	 * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
> >  	 */
> >  	XFS_BMAP_INIT(&free_list, &first_block);
> > @@ -2214,39 +2228,64 @@ xfs_remove(
> >  					&first_block, &free_list, resblks);
> >  	if (error) {
> >  		ASSERT(error != ENOENT);
> > -		REMOVE_DEBUG_TRACE(__LINE__);
> > -		goto error1;
> > +		goto out_bmap_cancel;
> >  	}
> >  	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
> >  
> > +	/*
> > +	 * Bump the in memory generation count on the parent
> > +	 * directory so that other can know that it has changed.
> > +	 */
> >  	dp->i_gen++;
> >  	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
> >  
> > -	error = xfs_droplink(tp, ip);
> > -	if (error) {
> > -		REMOVE_DEBUG_TRACE(__LINE__);
> > -		goto error1;
> > +	if (is_dir) {
> > +		/*
> > +		 * Drop the link from ip's "..".
> > +		 */
> > +		error = xfs_droplink(tp, dp);
> > +		if (error)
> > +			goto out_bmap_cancel;
> > +
> > +		/*
> > +		 * Drop the link from dp to ip.
> > +		 */
> > +		error = xfs_droplink(tp, ip);
> > +		if (error)
> > +			goto out_bmap_cancel;
> > +	} else {
> > +		/*
> > +		 * When removing a non-directory we need to log the parent
> > +		 * inode here for the i_gen update.  For a directory this is
> > +		 * done implicitly by the xfs_droplink call for the ".." entry.
> > +		 */
> > +		xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
> >  	}
> >  
> > -	/* Determine if this is the last link while
> > +	/*
> > +	 * Drop the "." link from ip to self.
> > +	 */
> > +	error = xfs_droplink(tp, ip);
> > +	if (error)
> > +		goto out_bmap_cancel;
> > +
> > +	/*
> > +	 * Determine if this is the last link while
> >  	 * we are in the transaction.
> >  	 */
> > -	link_zero = (ip)->i_d.di_nlink==0;
> > +	link_zero = (ip->i_d.di_nlink == 0);
> >  
> >  	/*
> >  	 * If this is a synchronous mount, make sure that the
> >  	 * remove transaction goes to disk before returning to
> >  	 * the user.
> >  	 */
> > -	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
> > +	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
> >  		xfs_trans_set_sync(tp);
> > -	}
> >  
> >  	error = xfs_bmap_finish(&tp, &free_list, &committed);
> > -	if (error) {
> > -		REMOVE_DEBUG_TRACE(__LINE__);
> > -		goto error_rele;
> > -	}
> > +	if (error)
> > +		goto out_bmap_cancel;
> >  
> >  	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
> >  	if (error)
> > @@ -2258,39 +2297,27 @@ xfs_remove(
> >  	 * will get killed on last close in xfs_close() so we don't
> >  	 * have to worry about that.
> >  	 */
> > -	if (link_zero && xfs_inode_is_filestream(ip))
> > +	if (!is_dir && link_zero && xfs_inode_is_filestream(ip))
> >  		xfs_filestream_deassociate(ip);
> >  
> >  	xfs_itrace_exit(ip);
> > +	xfs_itrace_exit(dp);
> >  
> > -/*	Fall through to std_return with error = 0 */
> >   std_return:
> >  	if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
> > -		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
> > -				dp, DM_RIGHT_NULL,
> > -				NULL, DM_RIGHT_NULL,
> > -				name->name, NULL, ip->i_d.di_mode, error, 0);
> > +		XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dp, DM_RIGHT_NULL,
> > +				NULL, DM_RIGHT_NULL, name->name, NULL,
> > +				ip->i_d.di_mode, error, 0);
> >  	}
> > +
> >  	return error;
> >  
> > - error1:
> > + out_bmap_cancel:
> >  	xfs_bmap_cancel(&free_list);
> >  	cancel_flags |= XFS_TRANS_ABORT;
> > + out_trans_cancel:
> >  	xfs_trans_cancel(tp, cancel_flags);
> >  	goto std_return;
> > -
> > - error_rele:
> > -	/*
> > -	 * In this case make sure to not release the inode until after
> > -	 * the current transaction is aborted.  Releasing it beforehand
> > -	 * can cause us to go to xfs_inactive and start a recursive
> > -	 * transaction which can easily deadlock with the current one.
> > -	 */
> > -	xfs_bmap_cancel(&free_list);
> > -	cancel_flags |= XFS_TRANS_ABORT;
> > -	xfs_trans_cancel(tp, cancel_flags);
> > -
> > -	goto std_return;
> >  }
> >  
> >  int
> > @@ -2656,186 +2683,6 @@ std_return:
> >  }
> >  
> >  int
> > -xfs_rmdir(
> > -	xfs_inode_t             *dp,
> > -	struct xfs_name		*name,
> > -	xfs_inode_t		*cdp)
> > -{
> > -	xfs_mount_t		*mp = dp->i_mount;
> > -	xfs_trans_t             *tp;
> > -	int                     error;
> > -	xfs_bmap_free_t         free_list;
> > -	xfs_fsblock_t           first_block;
> > -	int			cancel_flags;
> > -	int			committed;
> > -	int			last_cdp_link;
> > -	uint			resblks;
> > -
> > -	xfs_itrace_entry(dp);
> > -
> > -	if (XFS_FORCED_SHUTDOWN(mp))
> > -		return XFS_ERROR(EIO);
> > -
> > -	if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) {
> > -		error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE,
> > -					dp, DM_RIGHT_NULL,
> > -					NULL, DM_RIGHT_NULL, name->name,
> > -					NULL, cdp->i_d.di_mode, 0, 0);
> > -		if (error)
> > -			return XFS_ERROR(error);
> > -	}
> > -
> > -	/*
> > -	 * Get the dquots for the inodes.
> > -	 */
> > -	error = XFS_QM_DQATTACH(mp, dp, 0);
> > -	if (!error)
> > -		error = XFS_QM_DQATTACH(mp, cdp, 0);
> > -	if (error) {
> > -		REMOVE_DEBUG_TRACE(__LINE__);
> > -		goto std_return;
> > -	}
> > -
> > -	tp = xfs_trans_alloc(mp, XFS_TRANS_RMDIR);
> > -	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
> > -	/*
> > -	 * We try to get the real space reservation first,
> > -	 * allowing for directory btree deletion(s) implying
> > -	 * possible bmap insert(s).  If we can't get the space
> > -	 * reservation then we use 0 instead, and avoid the bmap
> > -	 * btree insert(s) in the directory code by, if the bmap
> > -	 * insert tries to happen, instead trimming the LAST
> > -	 * block from the directory.
> > -	 */
> > -	resblks = XFS_REMOVE_SPACE_RES(mp);
> > -	error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
> > -			XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
> > -	if (error == ENOSPC) {
> > -		resblks = 0;
> > -		error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
> > -				XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
> > -	}
> > -	if (error) {
> > -		ASSERT(error != ENOSPC);
> > -		cancel_flags = 0;
> > -		goto error_return;
> > -	}
> > -	XFS_BMAP_INIT(&free_list, &first_block);
> > -
> > -	/*
> > -	 * Now lock the child directory inode and the parent directory
> > -	 * inode in the proper order.  This will take care of validating
> > -	 * that the directory entry for the child directory inode has
> > -	 * not changed while we were obtaining a log reservation.
> > -	 */
> > -	error = xfs_lock_dir_and_entry(dp, cdp);
> > -	if (error) {
> > -		xfs_trans_cancel(tp, cancel_flags);
> > -		goto std_return;
> > -	}
> > -
> > -	IHOLD(dp);
> > -	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
> > -
> > -	IHOLD(cdp);
> > -	xfs_trans_ijoin(tp, cdp, XFS_ILOCK_EXCL);
> > -
> > -	ASSERT(cdp->i_d.di_nlink >= 2);
> > -	if (cdp->i_d.di_nlink != 2) {
> > -		error = XFS_ERROR(ENOTEMPTY);
> > -		goto error_return;
> > -	}
> > -	if (!xfs_dir_isempty(cdp)) {
> > -		error = XFS_ERROR(ENOTEMPTY);
> > -		goto error_return;
> > -	}
> > -
> > -	error = xfs_dir_removename(tp, dp, name, cdp->i_ino,
> > -					&first_block, &free_list, resblks);
> > -	if (error)
> > -		goto error1;
> > -
> > -	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
> > -
> > -	/*
> > -	 * Bump the in memory generation count on the parent
> > -	 * directory so that other can know that it has changed.
> > -	 */
> > -	dp->i_gen++;
> > -
> > -	/*
> > -	 * Drop the link from cdp's "..".
> > -	 */
> > -	error = xfs_droplink(tp, dp);
> > -	if (error) {
> > -		goto error1;
> > -	}
> > -
> > -	/*
> > -	 * Drop the link from dp to cdp.
> > -	 */
> > -	error = xfs_droplink(tp, cdp);
> > -	if (error) {
> > -		goto error1;
> > -	}
> > -
> > -	/*
> > -	 * Drop the "." link from cdp to self.
> > -	 */
> > -	error = xfs_droplink(tp, cdp);
> > -	if (error) {
> > -		goto error1;
> > -	}
> > -
> > -	/* Determine these before committing transaction */
> > -	last_cdp_link = (cdp)->i_d.di_nlink==0;
> > -
> > -	/*
> > -	 * If this is a synchronous mount, make sure that the
> > -	 * rmdir transaction goes to disk before returning to
> > -	 * the user.
> > -	 */
> > -	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
> > -		xfs_trans_set_sync(tp);
> > -	}
> > -
> > -	error = xfs_bmap_finish (&tp, &free_list, &committed);
> > -	if (error) {
> > -		xfs_bmap_cancel(&free_list);
> > -		xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
> > -				 XFS_TRANS_ABORT));
> > -		goto std_return;
> > -	}
> > -
> > -	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
> > -	if (error) {
> > -		goto std_return;
> > -	}
> > -
> > -
> > -	/* Fall through to std_return with error = 0 or the errno
> > -	 * from xfs_trans_commit. */
> > - std_return:
> > -	if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
> > -		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
> > -					dp, DM_RIGHT_NULL,
> > -					NULL, DM_RIGHT_NULL,
> > -					name->name, NULL, cdp->i_d.di_mode,
> > -					error, 0);
> > -	}
> > -	return error;
> > -
> > - error1:
> > -	xfs_bmap_cancel(&free_list);
> > -	cancel_flags |= XFS_TRANS_ABORT;
> > -	/* FALLTHROUGH */
> > -
> > - error_return:
> > -	xfs_trans_cancel(tp, cancel_flags);
> > -	goto std_return;
> > -}
> > -
> > -int
> >  xfs_symlink(
> >  	xfs_inode_t		*dp,
> >  	struct xfs_name		*link_name,
> > Index: linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c
> > ===================================================================
> > --- linux-2.6-xfs.orig/fs/xfs/linux-2.6/xfs_iops.c	2008-06-16 08:14:12.000000000 +0200
> > +++ linux-2.6-xfs/fs/xfs/linux-2.6/xfs_iops.c	2008-06-16 08:15:00.000000000 +0200
> > @@ -252,8 +252,7 @@ STATIC void
> >  xfs_cleanup_inode(
> >  	struct inode	*dir,
> >  	struct inode	*inode,
> > -	struct dentry	*dentry,
> > -	int		mode)
> > +	struct dentry	*dentry)
> >  {
> >  	struct xfs_name	teardown;
> >  
> > @@ -264,10 +263,7 @@ xfs_cleanup_inode(
> >  	 */
> >  	xfs_dentry_to_name(&teardown, dentry);
> >  
> > -	if (S_ISDIR(mode))
> > -		xfs_rmdir(XFS_I(dir), &teardown, XFS_I(inode));
> > -	else
> > -		xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
> > +	xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
> >  	iput(inode);
> >  }
> >  
> > @@ -349,7 +345,7 @@ xfs_vn_mknod(
> >  	return -error;
> >  
> >   out_cleanup_inode:
> > -	xfs_cleanup_inode(dir, inode, dentry, mode);
> > +	xfs_cleanup_inode(dir, inode, dentry);
> >   out_free_acl:
> >  	if (default_acl)
> >  		_ACL_FREE(default_acl);
> > @@ -525,38 +521,12 @@ xfs_vn_symlink(
> >  	return 0;
> >  
> >   out_cleanup_inode:
> > -	xfs_cleanup_inode(dir, inode, dentry, 0);
> > +	xfs_cleanup_inode(dir, inode, dentry);
> >   out:
> >  	return -error;
> >  }
> >  
> >  STATIC int
> > -xfs_vn_rmdir(
> > -	struct inode	*dir,
> > -	struct dentry	*dentry)
> > -{
> > -	struct inode	*inode = dentry->d_inode;
> > -	struct xfs_name	name;
> > -	int		error;
> > -
> > -	xfs_dentry_to_name(&name, dentry);
> > -
> > -	error = xfs_rmdir(XFS_I(dir), &name, XFS_I(inode));
> > -	if (likely(!error)) {
> > -		xfs_validate_fields(inode);
> > -		xfs_validate_fields(dir);
> > -		/*
> > -		 * With rmdir, the VFS makes the dentry "negative": no inode,
> > -		 * but still hashed. This is incompatible with case-insensitive
> > -		 * mode, so invalidate (unhash) the dentry in CI-mode.
> > -		 */
> > -		if (xfs_sb_version_hasasciici(&XFS_M(dir->i_sb)->m_sb))
> > -			d_invalidate(dentry);
> > -	}
> > -	return -error;
> > -}
> > -
> > -STATIC int
> >  xfs_vn_rename(
> >  	struct inode	*odir,
> >  	struct dentry	*odentry,
> > @@ -850,7 +820,13 @@ static const struct inode_operations xfs
> >  	.unlink			= xfs_vn_unlink,
> >  	.symlink		= xfs_vn_symlink,
> >  	.mkdir			= xfs_vn_mkdir,
> > -	.rmdir			= xfs_vn_rmdir,
> > +	/*
> > +	 * Yes, XFS uses the same method for rmdir and unlink.
> > +	 *
> > +	 * There are some subtile differences deeper in the code,
> > +	 * but we use S_ISDIR to check for those.
> > +	 */
> > +	.rmdir			= xfs_vn_unlink,
> >  	.mknod			= xfs_vn_mknod,
> >  	.rename			= xfs_vn_rename,
> >  	.permission		= xfs_vn_permission,
> > @@ -869,7 +845,13 @@ static const struct inode_operations xfs
> >  	.unlink			= xfs_vn_unlink,
> >  	.symlink		= xfs_vn_symlink,
> >  	.mkdir			= xfs_vn_mkdir,
> > -	.rmdir			= xfs_vn_rmdir,
> > +	/*
> > +	 * Yes, XFS uses the same method for rmdir and unlink.
> > +	 *
> > +	 * There are some subtile differences deeper in the code,
> > +	 * but we use S_ISDIR to check for those.
> > +	 */
> > +	.rmdir			= xfs_vn_unlink,
> >  	.mknod			= xfs_vn_mknod,
> >  	.rename			= xfs_vn_rename,
> >  	.permission		= xfs_vn_permission,
> > Index: linux-2.6-xfs/fs/xfs/xfs_vnodeops.h
> > ===================================================================
> > --- linux-2.6-xfs.orig/fs/xfs/xfs_vnodeops.h	2008-06-16 08:11:12.000000000 +0200
> > +++ linux-2.6-xfs/fs/xfs/xfs_vnodeops.h	2008-06-16 08:14:16.000000000 +0200
> > @@ -31,8 +31,6 @@ int xfs_link(struct xfs_inode *tdp, stru
> >  		struct xfs_name *target_name);
> >  int xfs_mkdir(struct xfs_inode *dp, struct xfs_name *dir_name,
> >  		mode_t mode, struct xfs_inode **ipp, struct cred *credp);
> > -int xfs_rmdir(struct xfs_inode *dp, struct xfs_name *name,
> > -		struct xfs_inode *cdp);
> >  int xfs_readdir(struct xfs_inode	*dp, void *dirent, size_t bufsize,
> >  		       xfs_off_t *offset, filldir_t filldir);
> >  int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,
> ---end quoted text---
---end quoted text---

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2008-07-23  8:11 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-02 10:57 [PATCH 1/2] merge xfs_rmdir into xfs_remove Christoph Hellwig
2008-05-20  6:36 ` Christoph Hellwig
2008-05-21  8:25 ` Christoph Hellwig
2008-06-16  6:18   ` Christoph Hellwig
2008-07-23  8:06     ` Christoph Hellwig
2008-07-23  8:12       ` Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox