diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 6c187450f1c8..9b6c94e7546e 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -2315,17 +2315,33 @@ xfs_change_file_space( | |||
2315 | case XFS_IOC_ALLOCSP64: | 2315 | case XFS_IOC_ALLOCSP64: |
2316 | case XFS_IOC_FREESP: | 2316 | case XFS_IOC_FREESP: |
2317 | case XFS_IOC_FREESP64: | 2317 | case XFS_IOC_FREESP64: |
2318 | /* | ||
2319 | * These operations actually do IO when extending the file, but | ||
2320 | * the allocation is done seperately to the zeroing that is | ||
2321 | * done. This set of operations need to be serialised against | ||
2322 | * other IO operations, such as truncate and buffered IO. We | ||
2323 | * need to take the IOLOCK here to serialise the allocation and | ||
2324 | * zeroing IO to prevent other IOLOCK holders (e.g. getbmap, | ||
2325 | * truncate, direct IO) from racing against the transient | ||
2326 | * allocated but not written state we can have here. | ||
2327 | */ | ||
2328 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | ||
2318 | if (startoffset > fsize) { | 2329 | if (startoffset > fsize) { |
2319 | error = xfs_alloc_file_space(ip, fsize, | 2330 | error = xfs_alloc_file_space(ip, fsize, |
2320 | startoffset - fsize, 0, attr_flags); | 2331 | startoffset - fsize, 0, |
2321 | if (error) | 2332 | attr_flags | XFS_ATTR_NOLOCK); |
2333 | if (error) { | ||
2334 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
2322 | break; | 2335 | break; |
2336 | } | ||
2323 | } | 2337 | } |
2324 | 2338 | ||
2325 | iattr.ia_valid = ATTR_SIZE; | 2339 | iattr.ia_valid = ATTR_SIZE; |
2326 | iattr.ia_size = startoffset; | 2340 | iattr.ia_size = startoffset; |
2327 | 2341 | ||
2328 | error = xfs_setattr_size(ip, &iattr, attr_flags); | 2342 | error = xfs_setattr_size(ip, &iattr, |
2343 | attr_flags | XFS_ATTR_NOLOCK); | ||
2344 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
2329 | 2345 | ||
2330 | if (error) | 2346 | if (error) |
2331 | return error; | 2347 | return error; |