diff options
Diffstat (limited to 'fs/xfs/xfs_inode_item.c')
-rw-r--r-- | fs/xfs/xfs_inode_item.c | 129 |
1 files changed, 32 insertions, 97 deletions
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index f38855d21ea5..d4dc063111f8 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -228,7 +228,7 @@ xfs_inode_item_format( | |||
228 | 228 | ||
229 | vecp->i_addr = (xfs_caddr_t)&iip->ili_format; | 229 | vecp->i_addr = (xfs_caddr_t)&iip->ili_format; |
230 | vecp->i_len = sizeof(xfs_inode_log_format_t); | 230 | vecp->i_len = sizeof(xfs_inode_log_format_t); |
231 | XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IFORMAT); | 231 | vecp->i_type = XLOG_REG_TYPE_IFORMAT; |
232 | vecp++; | 232 | vecp++; |
233 | nvecs = 1; | 233 | nvecs = 1; |
234 | 234 | ||
@@ -279,7 +279,7 @@ xfs_inode_item_format( | |||
279 | 279 | ||
280 | vecp->i_addr = (xfs_caddr_t)&ip->i_d; | 280 | vecp->i_addr = (xfs_caddr_t)&ip->i_d; |
281 | vecp->i_len = sizeof(struct xfs_icdinode); | 281 | vecp->i_len = sizeof(struct xfs_icdinode); |
282 | XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_ICORE); | 282 | vecp->i_type = XLOG_REG_TYPE_ICORE; |
283 | vecp++; | 283 | vecp++; |
284 | nvecs++; | 284 | nvecs++; |
285 | iip->ili_format.ilf_fields |= XFS_ILOG_CORE; | 285 | iip->ili_format.ilf_fields |= XFS_ILOG_CORE; |
@@ -336,7 +336,7 @@ xfs_inode_item_format( | |||
336 | vecp->i_addr = | 336 | vecp->i_addr = |
337 | (char *)(ip->i_df.if_u1.if_extents); | 337 | (char *)(ip->i_df.if_u1.if_extents); |
338 | vecp->i_len = ip->i_df.if_bytes; | 338 | vecp->i_len = ip->i_df.if_bytes; |
339 | XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IEXT); | 339 | vecp->i_type = XLOG_REG_TYPE_IEXT; |
340 | } else | 340 | } else |
341 | #endif | 341 | #endif |
342 | { | 342 | { |
@@ -355,7 +355,7 @@ xfs_inode_item_format( | |||
355 | vecp->i_addr = (xfs_caddr_t)ext_buffer; | 355 | vecp->i_addr = (xfs_caddr_t)ext_buffer; |
356 | vecp->i_len = xfs_iextents_copy(ip, ext_buffer, | 356 | vecp->i_len = xfs_iextents_copy(ip, ext_buffer, |
357 | XFS_DATA_FORK); | 357 | XFS_DATA_FORK); |
358 | XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IEXT); | 358 | vecp->i_type = XLOG_REG_TYPE_IEXT; |
359 | } | 359 | } |
360 | ASSERT(vecp->i_len <= ip->i_df.if_bytes); | 360 | ASSERT(vecp->i_len <= ip->i_df.if_bytes); |
361 | iip->ili_format.ilf_dsize = vecp->i_len; | 361 | iip->ili_format.ilf_dsize = vecp->i_len; |
@@ -373,7 +373,7 @@ xfs_inode_item_format( | |||
373 | ASSERT(ip->i_df.if_broot != NULL); | 373 | ASSERT(ip->i_df.if_broot != NULL); |
374 | vecp->i_addr = (xfs_caddr_t)ip->i_df.if_broot; | 374 | vecp->i_addr = (xfs_caddr_t)ip->i_df.if_broot; |
375 | vecp->i_len = ip->i_df.if_broot_bytes; | 375 | vecp->i_len = ip->i_df.if_broot_bytes; |
376 | XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IBROOT); | 376 | vecp->i_type = XLOG_REG_TYPE_IBROOT; |
377 | vecp++; | 377 | vecp++; |
378 | nvecs++; | 378 | nvecs++; |
379 | iip->ili_format.ilf_dsize = ip->i_df.if_broot_bytes; | 379 | iip->ili_format.ilf_dsize = ip->i_df.if_broot_bytes; |
@@ -399,7 +399,7 @@ xfs_inode_item_format( | |||
399 | ASSERT((ip->i_df.if_real_bytes == 0) || | 399 | ASSERT((ip->i_df.if_real_bytes == 0) || |
400 | (ip->i_df.if_real_bytes == data_bytes)); | 400 | (ip->i_df.if_real_bytes == data_bytes)); |
401 | vecp->i_len = (int)data_bytes; | 401 | vecp->i_len = (int)data_bytes; |
402 | XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_ILOCAL); | 402 | vecp->i_type = XLOG_REG_TYPE_ILOCAL; |
403 | vecp++; | 403 | vecp++; |
404 | nvecs++; | 404 | nvecs++; |
405 | iip->ili_format.ilf_dsize = (unsigned)data_bytes; | 405 | iip->ili_format.ilf_dsize = (unsigned)data_bytes; |
@@ -477,7 +477,7 @@ xfs_inode_item_format( | |||
477 | vecp->i_len = xfs_iextents_copy(ip, ext_buffer, | 477 | vecp->i_len = xfs_iextents_copy(ip, ext_buffer, |
478 | XFS_ATTR_FORK); | 478 | XFS_ATTR_FORK); |
479 | #endif | 479 | #endif |
480 | XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IATTR_EXT); | 480 | vecp->i_type = XLOG_REG_TYPE_IATTR_EXT; |
481 | iip->ili_format.ilf_asize = vecp->i_len; | 481 | iip->ili_format.ilf_asize = vecp->i_len; |
482 | vecp++; | 482 | vecp++; |
483 | nvecs++; | 483 | nvecs++; |
@@ -492,7 +492,7 @@ xfs_inode_item_format( | |||
492 | ASSERT(ip->i_afp->if_broot != NULL); | 492 | ASSERT(ip->i_afp->if_broot != NULL); |
493 | vecp->i_addr = (xfs_caddr_t)ip->i_afp->if_broot; | 493 | vecp->i_addr = (xfs_caddr_t)ip->i_afp->if_broot; |
494 | vecp->i_len = ip->i_afp->if_broot_bytes; | 494 | vecp->i_len = ip->i_afp->if_broot_bytes; |
495 | XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IATTR_BROOT); | 495 | vecp->i_type = XLOG_REG_TYPE_IATTR_BROOT; |
496 | vecp++; | 496 | vecp++; |
497 | nvecs++; | 497 | nvecs++; |
498 | iip->ili_format.ilf_asize = ip->i_afp->if_broot_bytes; | 498 | iip->ili_format.ilf_asize = ip->i_afp->if_broot_bytes; |
@@ -516,7 +516,7 @@ xfs_inode_item_format( | |||
516 | ASSERT((ip->i_afp->if_real_bytes == 0) || | 516 | ASSERT((ip->i_afp->if_real_bytes == 0) || |
517 | (ip->i_afp->if_real_bytes == data_bytes)); | 517 | (ip->i_afp->if_real_bytes == data_bytes)); |
518 | vecp->i_len = (int)data_bytes; | 518 | vecp->i_len = (int)data_bytes; |
519 | XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IATTR_LOCAL); | 519 | vecp->i_type = XLOG_REG_TYPE_IATTR_LOCAL; |
520 | vecp++; | 520 | vecp++; |
521 | nvecs++; | 521 | nvecs++; |
522 | iip->ili_format.ilf_asize = (unsigned)data_bytes; | 522 | iip->ili_format.ilf_asize = (unsigned)data_bytes; |
@@ -602,33 +602,20 @@ xfs_inode_item_trylock( | |||
602 | 602 | ||
603 | if (!xfs_iflock_nowait(ip)) { | 603 | if (!xfs_iflock_nowait(ip)) { |
604 | /* | 604 | /* |
605 | * If someone else isn't already trying to push the inode | 605 | * inode has already been flushed to the backing buffer, |
606 | * buffer, we get to do it. | 606 | * leave it locked in shared mode, pushbuf routine will |
607 | * unlock it. | ||
607 | */ | 608 | */ |
608 | if (iip->ili_pushbuf_flag == 0) { | 609 | return XFS_ITEM_PUSHBUF; |
609 | iip->ili_pushbuf_flag = 1; | ||
610 | #ifdef DEBUG | ||
611 | iip->ili_push_owner = current_pid(); | ||
612 | #endif | ||
613 | /* | ||
614 | * Inode is left locked in shared mode. | ||
615 | * Pushbuf routine gets to unlock it. | ||
616 | */ | ||
617 | return XFS_ITEM_PUSHBUF; | ||
618 | } else { | ||
619 | /* | ||
620 | * We hold the AIL lock, so we must specify the | ||
621 | * NONOTIFY flag so that we won't double trip. | ||
622 | */ | ||
623 | xfs_iunlock(ip, XFS_ILOCK_SHARED|XFS_IUNLOCK_NONOTIFY); | ||
624 | return XFS_ITEM_FLUSHING; | ||
625 | } | ||
626 | /* NOTREACHED */ | ||
627 | } | 610 | } |
628 | 611 | ||
629 | /* Stale items should force out the iclog */ | 612 | /* Stale items should force out the iclog */ |
630 | if (ip->i_flags & XFS_ISTALE) { | 613 | if (ip->i_flags & XFS_ISTALE) { |
631 | xfs_ifunlock(ip); | 614 | xfs_ifunlock(ip); |
615 | /* | ||
616 | * we hold the AIL lock - notify the unlock routine of this | ||
617 | * so it doesn't try to get the lock again. | ||
618 | */ | ||
632 | xfs_iunlock(ip, XFS_ILOCK_SHARED|XFS_IUNLOCK_NONOTIFY); | 619 | xfs_iunlock(ip, XFS_ILOCK_SHARED|XFS_IUNLOCK_NONOTIFY); |
633 | return XFS_ITEM_PINNED; | 620 | return XFS_ITEM_PINNED; |
634 | } | 621 | } |
@@ -746,11 +733,8 @@ xfs_inode_item_committed( | |||
746 | * This gets called by xfs_trans_push_ail(), when IOP_TRYLOCK | 733 | * This gets called by xfs_trans_push_ail(), when IOP_TRYLOCK |
747 | * failed to get the inode flush lock but did get the inode locked SHARED. | 734 | * failed to get the inode flush lock but did get the inode locked SHARED. |
748 | * Here we're trying to see if the inode buffer is incore, and if so whether it's | 735 | * Here we're trying to see if the inode buffer is incore, and if so whether it's |
749 | * marked delayed write. If that's the case, we'll initiate a bawrite on that | 736 | * marked delayed write. If that's the case, we'll promote it and that will |
750 | * buffer to expedite the process. | 737 | * allow the caller to write the buffer by triggering the xfsbufd to run. |
751 | * | ||
752 | * We aren't holding the AIL lock (or the flush lock) when this gets called, | ||
753 | * so it is inherently race-y. | ||
754 | */ | 738 | */ |
755 | STATIC void | 739 | STATIC void |
756 | xfs_inode_item_pushbuf( | 740 | xfs_inode_item_pushbuf( |
@@ -759,82 +743,30 @@ xfs_inode_item_pushbuf( | |||
759 | xfs_inode_t *ip; | 743 | xfs_inode_t *ip; |
760 | xfs_mount_t *mp; | 744 | xfs_mount_t *mp; |
761 | xfs_buf_t *bp; | 745 | xfs_buf_t *bp; |
762 | uint dopush; | ||
763 | 746 | ||
764 | ip = iip->ili_inode; | 747 | ip = iip->ili_inode; |
765 | |||
766 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED)); | 748 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED)); |
767 | 749 | ||
768 | /* | 750 | /* |
769 | * The ili_pushbuf_flag keeps others from | ||
770 | * trying to duplicate our effort. | ||
771 | */ | ||
772 | ASSERT(iip->ili_pushbuf_flag != 0); | ||
773 | ASSERT(iip->ili_push_owner == current_pid()); | ||
774 | |||
775 | /* | ||
776 | * If a flush is not in progress anymore, chances are that the | 751 | * If a flush is not in progress anymore, chances are that the |
777 | * inode was taken off the AIL. So, just get out. | 752 | * inode was taken off the AIL. So, just get out. |
778 | */ | 753 | */ |
779 | if (completion_done(&ip->i_flush) || | 754 | if (completion_done(&ip->i_flush) || |
780 | ((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0)) { | 755 | ((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0)) { |
781 | iip->ili_pushbuf_flag = 0; | ||
782 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 756 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
783 | return; | 757 | return; |
784 | } | 758 | } |
785 | 759 | ||
786 | mp = ip->i_mount; | 760 | mp = ip->i_mount; |
787 | bp = xfs_incore(mp->m_ddev_targp, iip->ili_format.ilf_blkno, | 761 | bp = xfs_incore(mp->m_ddev_targp, iip->ili_format.ilf_blkno, |
788 | iip->ili_format.ilf_len, XFS_INCORE_TRYLOCK); | 762 | iip->ili_format.ilf_len, XBF_TRYLOCK); |
789 | 763 | ||
790 | if (bp != NULL) { | ||
791 | if (XFS_BUF_ISDELAYWRITE(bp)) { | ||
792 | /* | ||
793 | * We were racing with iflush because we don't hold | ||
794 | * the AIL lock or the flush lock. However, at this point, | ||
795 | * we have the buffer, and we know that it's dirty. | ||
796 | * So, it's possible that iflush raced with us, and | ||
797 | * this item is already taken off the AIL. | ||
798 | * If not, we can flush it async. | ||
799 | */ | ||
800 | dopush = ((iip->ili_item.li_flags & XFS_LI_IN_AIL) && | ||
801 | !completion_done(&ip->i_flush)); | ||
802 | iip->ili_pushbuf_flag = 0; | ||
803 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
804 | |||
805 | trace_xfs_inode_item_push(bp, _RET_IP_); | ||
806 | |||
807 | if (XFS_BUF_ISPINNED(bp)) { | ||
808 | xfs_log_force(mp, (xfs_lsn_t)0, | ||
809 | XFS_LOG_FORCE); | ||
810 | } | ||
811 | if (dopush) { | ||
812 | int error; | ||
813 | error = xfs_bawrite(mp, bp); | ||
814 | if (error) | ||
815 | xfs_fs_cmn_err(CE_WARN, mp, | ||
816 | "xfs_inode_item_pushbuf: pushbuf error %d on iip %p, bp %p", | ||
817 | error, iip, bp); | ||
818 | } else { | ||
819 | xfs_buf_relse(bp); | ||
820 | } | ||
821 | } else { | ||
822 | iip->ili_pushbuf_flag = 0; | ||
823 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
824 | xfs_buf_relse(bp); | ||
825 | } | ||
826 | return; | ||
827 | } | ||
828 | /* | ||
829 | * We have to be careful about resetting pushbuf flag too early (above). | ||
830 | * Even though in theory we can do it as soon as we have the buflock, | ||
831 | * we don't want others to be doing work needlessly. They'll come to | ||
832 | * this function thinking that pushing the buffer is their | ||
833 | * responsibility only to find that the buffer is still locked by | ||
834 | * another doing the same thing | ||
835 | */ | ||
836 | iip->ili_pushbuf_flag = 0; | ||
837 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 764 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
765 | if (!bp) | ||
766 | return; | ||
767 | if (XFS_BUF_ISDELAYWRITE(bp)) | ||
768 | xfs_buf_delwri_promote(bp); | ||
769 | xfs_buf_relse(bp); | ||
838 | return; | 770 | return; |
839 | } | 771 | } |
840 | 772 | ||
@@ -867,10 +799,14 @@ xfs_inode_item_push( | |||
867 | iip->ili_format.ilf_fields != 0); | 799 | iip->ili_format.ilf_fields != 0); |
868 | 800 | ||
869 | /* | 801 | /* |
870 | * Write out the inode. The completion routine ('iflush_done') will | 802 | * Push the inode to it's backing buffer. This will not remove the |
871 | * pull it from the AIL, mark it clean, unlock the flush lock. | 803 | * inode from the AIL - a further push will be required to trigger a |
804 | * buffer push. However, this allows all the dirty inodes to be pushed | ||
805 | * to the buffer before it is pushed to disk. THe buffer IO completion | ||
806 | * will pull th einode from the AIL, mark it clean and unlock the flush | ||
807 | * lock. | ||
872 | */ | 808 | */ |
873 | (void) xfs_iflush(ip, XFS_IFLUSH_ASYNC); | 809 | (void) xfs_iflush(ip, 0); |
874 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 810 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
875 | 811 | ||
876 | return; | 812 | return; |
@@ -934,7 +870,6 @@ xfs_inode_item_init( | |||
934 | /* | 870 | /* |
935 | We have zeroed memory. No need ... | 871 | We have zeroed memory. No need ... |
936 | iip->ili_extents_buf = NULL; | 872 | iip->ili_extents_buf = NULL; |
937 | iip->ili_pushbuf_flag = 0; | ||
938 | */ | 873 | */ |
939 | 874 | ||
940 | iip->ili_format.ilf_type = XFS_LI_INODE; | 875 | iip->ili_format.ilf_type = XFS_LI_INODE; |