aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/libxfs/xfs_attr_leaf.c8
-rw-r--r--fs/xfs/libxfs/xfs_attr_leaf.h2
-rw-r--r--fs/xfs/xfs_attr_inactive.c83
-rw-r--r--fs/xfs/xfs_inode.c12
4 files changed, 58 insertions, 47 deletions
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index 04e79d57bca6..e9d401ce93bb 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -574,8 +574,8 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)
574 * After the last attribute is removed revert to original inode format, 574 * After the last attribute is removed revert to original inode format,
575 * making all literal area available to the data fork once more. 575 * making all literal area available to the data fork once more.
576 */ 576 */
577STATIC void 577void
578xfs_attr_fork_reset( 578xfs_attr_fork_remove(
579 struct xfs_inode *ip, 579 struct xfs_inode *ip,
580 struct xfs_trans *tp) 580 struct xfs_trans *tp)
581{ 581{
@@ -641,7 +641,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
641 (mp->m_flags & XFS_MOUNT_ATTR2) && 641 (mp->m_flags & XFS_MOUNT_ATTR2) &&
642 (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) && 642 (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
643 !(args->op_flags & XFS_DA_OP_ADDNAME)) { 643 !(args->op_flags & XFS_DA_OP_ADDNAME)) {
644 xfs_attr_fork_reset(dp, args->trans); 644 xfs_attr_fork_remove(dp, args->trans);
645 } else { 645 } else {
646 xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); 646 xfs_idata_realloc(dp, -size, XFS_ATTR_FORK);
647 dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); 647 dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize);
@@ -905,7 +905,7 @@ xfs_attr3_leaf_to_shortform(
905 if (forkoff == -1) { 905 if (forkoff == -1) {
906 ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2); 906 ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2);
907 ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE); 907 ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE);
908 xfs_attr_fork_reset(dp, args->trans); 908 xfs_attr_fork_remove(dp, args->trans);
909 goto out; 909 goto out;
910 } 910 }
911 911
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.h b/fs/xfs/libxfs/xfs_attr_leaf.h
index 025c4b820c03..882c8d338891 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.h
+++ b/fs/xfs/libxfs/xfs_attr_leaf.h
@@ -53,7 +53,7 @@ int xfs_attr_shortform_remove(struct xfs_da_args *args);
53int xfs_attr_shortform_list(struct xfs_attr_list_context *context); 53int xfs_attr_shortform_list(struct xfs_attr_list_context *context);
54int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp); 54int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp);
55int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes); 55int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes);
56 56void xfs_attr_fork_remove(struct xfs_inode *ip, struct xfs_trans *tp);
57 57
58/* 58/*
59 * Internal routines when attribute fork size == XFS_LBSIZE(mp). 59 * Internal routines when attribute fork size == XFS_LBSIZE(mp).
diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c
index f9c1c64782d3..3fbf167cfb4c 100644
--- a/fs/xfs/xfs_attr_inactive.c
+++ b/fs/xfs/xfs_attr_inactive.c
@@ -380,23 +380,31 @@ xfs_attr3_root_inactive(
380 return error; 380 return error;
381} 381}
382 382
383/*
384 * xfs_attr_inactive kills all traces of an attribute fork on an inode. It
385 * removes both the on-disk and in-memory inode fork. Note that this also has to
386 * handle the condition of inodes without attributes but with an attribute fork
387 * configured, so we can't use xfs_inode_hasattr() here.
388 *
389 * The in-memory attribute fork is removed even on error.
390 */
383int 391int
384xfs_attr_inactive(xfs_inode_t *dp) 392xfs_attr_inactive(
393 struct xfs_inode *dp)
385{ 394{
386 xfs_trans_t *trans; 395 struct xfs_trans *trans;
387 xfs_mount_t *mp; 396 struct xfs_mount *mp;
388 int error; 397 int cancel_flags = 0;
398 int lock_mode = XFS_ILOCK_SHARED;
399 int error = 0;
389 400
390 mp = dp->i_mount; 401 mp = dp->i_mount;
391 ASSERT(! XFS_NOT_DQATTACHED(mp, dp)); 402 ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
392 403
393 xfs_ilock(dp, XFS_ILOCK_SHARED); 404 xfs_ilock(dp, lock_mode);
394 if (!xfs_inode_hasattr(dp) || 405 if (!XFS_IFORK_Q(dp))
395 dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { 406 goto out_destroy_fork;
396 xfs_iunlock(dp, XFS_ILOCK_SHARED); 407 xfs_iunlock(dp, lock_mode);
397 return 0;
398 }
399 xfs_iunlock(dp, XFS_ILOCK_SHARED);
400 408
401 /* 409 /*
402 * Start our first transaction of the day. 410 * Start our first transaction of the day.
@@ -408,13 +416,18 @@ xfs_attr_inactive(xfs_inode_t *dp)
408 * the inode in every transaction to let it float upward through 416 * the inode in every transaction to let it float upward through
409 * the log. 417 * the log.
410 */ 418 */
419 lock_mode = 0;
411 trans = xfs_trans_alloc(mp, XFS_TRANS_ATTRINVAL); 420 trans = xfs_trans_alloc(mp, XFS_TRANS_ATTRINVAL);
412 error = xfs_trans_reserve(trans, &M_RES(mp)->tr_attrinval, 0, 0); 421 error = xfs_trans_reserve(trans, &M_RES(mp)->tr_attrinval, 0, 0);
413 if (error) { 422 if (error)
414 xfs_trans_cancel(trans, 0); 423 goto out_cancel;
415 return error; 424
416 } 425 lock_mode = XFS_ILOCK_EXCL;
417 xfs_ilock(dp, XFS_ILOCK_EXCL); 426 cancel_flags = XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT;
427 xfs_ilock(dp, lock_mode);
428
429 if (!XFS_IFORK_Q(dp))
430 goto out_cancel;
418 431
419 /* 432 /*
420 * No need to make quota reservations here. We expect to release some 433 * No need to make quota reservations here. We expect to release some
@@ -422,29 +435,31 @@ xfs_attr_inactive(xfs_inode_t *dp)
422 */ 435 */
423 xfs_trans_ijoin(trans, dp, 0); 436 xfs_trans_ijoin(trans, dp, 0);
424 437
425 /* 438 /* invalidate and truncate the attribute fork extents */
426 * Decide on what work routines to call based on the inode size. 439 if (dp->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) {
427 */ 440 error = xfs_attr3_root_inactive(&trans, dp);
428 if (!xfs_inode_hasattr(dp) || 441 if (error)
429 dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { 442 goto out_cancel;
430 error = 0; 443
431 goto out; 444 error = xfs_itruncate_extents(&trans, dp, XFS_ATTR_FORK, 0);
445 if (error)
446 goto out_cancel;
432 } 447 }
433 error = xfs_attr3_root_inactive(&trans, dp);
434 if (error)
435 goto out;
436 448
437 error = xfs_itruncate_extents(&trans, dp, XFS_ATTR_FORK, 0); 449 /* Reset the attribute fork - this also destroys the in-core fork */
438 if (error) 450 xfs_attr_fork_remove(dp, trans);
439 goto out;
440 451
441 error = xfs_trans_commit(trans, XFS_TRANS_RELEASE_LOG_RES); 452 error = xfs_trans_commit(trans, XFS_TRANS_RELEASE_LOG_RES);
442 xfs_iunlock(dp, XFS_ILOCK_EXCL); 453 xfs_iunlock(dp, lock_mode);
443
444 return error; 454 return error;
445 455
446out: 456out_cancel:
447 xfs_trans_cancel(trans, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); 457 xfs_trans_cancel(trans, cancel_flags);
448 xfs_iunlock(dp, XFS_ILOCK_EXCL); 458out_destroy_fork:
459 /* kill the in-core attr fork before we drop the inode lock */
460 if (dp->i_afp)
461 xfs_idestroy_fork(dp, XFS_ATTR_FORK);
462 if (lock_mode)
463 xfs_iunlock(dp, lock_mode);
449 return error; 464 return error;
450} 465}
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index d6ebc85192b7..1117dd3ba123 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1946,21 +1946,17 @@ xfs_inactive(
1946 /* 1946 /*
1947 * If there are attributes associated with the file then blow them away 1947 * If there are attributes associated with the file then blow them away
1948 * now. The code calls a routine that recursively deconstructs the 1948 * now. The code calls a routine that recursively deconstructs the
1949 * attribute fork. We need to just commit the current transaction 1949 * attribute fork. If also blows away the in-core attribute fork.
1950 * because we can't use it for xfs_attr_inactive().
1951 */ 1950 */
1952 if (ip->i_d.di_anextents > 0) { 1951 if (XFS_IFORK_Q(ip)) {
1953 ASSERT(ip->i_d.di_forkoff != 0);
1954
1955 error = xfs_attr_inactive(ip); 1952 error = xfs_attr_inactive(ip);
1956 if (error) 1953 if (error)
1957 return; 1954 return;
1958 } 1955 }
1959 1956
1960 if (ip->i_afp) 1957 ASSERT(!ip->i_afp);
1961 xfs_idestroy_fork(ip, XFS_ATTR_FORK);
1962
1963 ASSERT(ip->i_d.di_anextents == 0); 1958 ASSERT(ip->i_d.di_anextents == 0);
1959 ASSERT(ip->i_d.di_forkoff == 0);
1964 1960
1965 /* 1961 /*
1966 * Free the inode. 1962 * Free the inode.