diff options
-rw-r--r-- | fs/xfs/xfs_bmap_util.c | 27 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.c | 34 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.h | 1 |
3 files changed, 41 insertions, 21 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 460aeb87c04e..374ba050942f 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c | |||
@@ -617,22 +617,27 @@ xfs_getbmap( | |||
617 | return XFS_ERROR(ENOMEM); | 617 | return XFS_ERROR(ENOMEM); |
618 | 618 | ||
619 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | 619 | xfs_ilock(ip, XFS_IOLOCK_SHARED); |
620 | if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) { | 620 | if (whichfork == XFS_DATA_FORK) { |
621 | if (ip->i_delayed_blks || XFS_ISIZE(ip) > ip->i_d.di_size) { | 621 | if (!(iflags & BMV_IF_DELALLOC) && |
622 | (ip->i_delayed_blks || XFS_ISIZE(ip) > ip->i_d.di_size)) { | ||
622 | error = -filemap_write_and_wait(VFS_I(ip)->i_mapping); | 623 | error = -filemap_write_and_wait(VFS_I(ip)->i_mapping); |
623 | if (error) | 624 | if (error) |
624 | goto out_unlock_iolock; | 625 | goto out_unlock_iolock; |
626 | |||
627 | /* | ||
628 | * Even after flushing the inode, there can still be | ||
629 | * delalloc blocks on the inode beyond EOF due to | ||
630 | * speculative preallocation. These are not removed | ||
631 | * until the release function is called or the inode | ||
632 | * is inactivated. Hence we cannot assert here that | ||
633 | * ip->i_delayed_blks == 0. | ||
634 | */ | ||
625 | } | 635 | } |
626 | /* | ||
627 | * even after flushing the inode, there can still be delalloc | ||
628 | * blocks on the inode beyond EOF due to speculative | ||
629 | * preallocation. These are not removed until the release | ||
630 | * function is called or the inode is inactivated. Hence we | ||
631 | * cannot assert here that ip->i_delayed_blks == 0. | ||
632 | */ | ||
633 | } | ||
634 | 636 | ||
635 | lock = xfs_ilock_data_map_shared(ip); | 637 | lock = xfs_ilock_data_map_shared(ip); |
638 | } else { | ||
639 | lock = xfs_ilock_attr_map_shared(ip); | ||
640 | } | ||
636 | 641 | ||
637 | /* | 642 | /* |
638 | * Don't let nex be bigger than the number of extents | 643 | * Don't let nex be bigger than the number of extents |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index fdd483783365..e655bb07e8bb 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -77,17 +77,18 @@ xfs_get_extsz_hint( | |||
77 | } | 77 | } |
78 | 78 | ||
79 | /* | 79 | /* |
80 | * This is a wrapper routine around the xfs_ilock() routine used to centralize | 80 | * These two are wrapper routines around the xfs_ilock() routine used to |
81 | * some grungy code. It is used in places that wish to lock the inode solely | 81 | * centralize some grungy code. They are used in places that wish to lock the |
82 | * for reading the extents. The reason these places can't just call | 82 | * inode solely for reading the extents. The reason these places can't just |
83 | * xfs_ilock(SHARED) is that the inode lock also guards to bringing in of the | 83 | * call xfs_ilock(ip, XFS_ILOCK_SHARED) is that the inode lock also guards to |
84 | * extents from disk for a file in b-tree format. If the inode is in b-tree | 84 | * bringing in of the extents from disk for a file in b-tree format. If the |
85 | * format, then we need to lock the inode exclusively until the extents are read | 85 | * inode is in b-tree format, then we need to lock the inode exclusively until |
86 | * in. Locking it exclusively all the time would limit our parallelism | 86 | * the extents are read in. Locking it exclusively all the time would limit |
87 | * unnecessarily, though. What we do instead is check to see if the extents | 87 | * our parallelism unnecessarily, though. What we do instead is check to see |
88 | * have been read in yet, and only lock the inode exclusively if they have not. | 88 | * if the extents have been read in yet, and only lock the inode exclusively |
89 | * if they have not. | ||
89 | * | 90 | * |
90 | * The function returns a value which should be given to the corresponding | 91 | * The functions return a value which should be given to the corresponding |
91 | * xfs_iunlock() call. | 92 | * xfs_iunlock() call. |
92 | */ | 93 | */ |
93 | uint | 94 | uint |
@@ -103,6 +104,19 @@ xfs_ilock_data_map_shared( | |||
103 | return lock_mode; | 104 | return lock_mode; |
104 | } | 105 | } |
105 | 106 | ||
107 | uint | ||
108 | xfs_ilock_attr_map_shared( | ||
109 | struct xfs_inode *ip) | ||
110 | { | ||
111 | uint lock_mode = XFS_ILOCK_SHARED; | ||
112 | |||
113 | if (ip->i_d.di_aformat == XFS_DINODE_FMT_BTREE && | ||
114 | (ip->i_afp->if_flags & XFS_IFEXTENTS) == 0) | ||
115 | lock_mode = XFS_ILOCK_EXCL; | ||
116 | xfs_ilock(ip, lock_mode); | ||
117 | return lock_mode; | ||
118 | } | ||
119 | |||
106 | /* | 120 | /* |
107 | * The xfs inode contains 2 locks: a multi-reader lock called the | 121 | * The xfs inode contains 2 locks: a multi-reader lock called the |
108 | * i_iolock and a multi-reader lock called the i_lock. This routine | 122 | * i_iolock and a multi-reader lock called the i_lock. This routine |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index fde368624ea7..65e2350f449c 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -338,6 +338,7 @@ void xfs_iunlock(xfs_inode_t *, uint); | |||
338 | void xfs_ilock_demote(xfs_inode_t *, uint); | 338 | void xfs_ilock_demote(xfs_inode_t *, uint); |
339 | int xfs_isilocked(xfs_inode_t *, uint); | 339 | int xfs_isilocked(xfs_inode_t *, uint); |
340 | uint xfs_ilock_data_map_shared(struct xfs_inode *); | 340 | uint xfs_ilock_data_map_shared(struct xfs_inode *); |
341 | uint xfs_ilock_attr_map_shared(struct xfs_inode *); | ||
341 | int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, umode_t, | 342 | int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, umode_t, |
342 | xfs_nlink_t, xfs_dev_t, prid_t, int, | 343 | xfs_nlink_t, xfs_dev_t, prid_t, int, |
343 | struct xfs_buf **, xfs_inode_t **); | 344 | struct xfs_buf **, xfs_inode_t **); |