diff options
author | Christoph Hellwig <hch@lst.de> | 2016-11-29 22:33:25 -0500 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2016-11-29 22:33:25 -0500 |
commit | 6552321831dce87ff5c466a55b58d472732caadc (patch) | |
tree | 84f3de7b89690c84fd13e2efa7a85d4918d342e3 /fs/xfs/xfs_file.c | |
parent | f8319483f57f1ca22370f4150bb990aca7728a67 (diff) |
xfs: remove i_iolock and use i_rwsem in the VFS inode instead
This patch drops the XFS-own i_iolock and uses the VFS i_rwsem which
recently replaced i_mutex instead. This means we only have to take
one lock instead of two in many fast path operations, and we can
also shrink the xfs_inode structure. Thanks to the xfs_ilock family
there is very little churn, the only thing of note is that we need
to switch to use the lock_two_directory helper for taking the i_rwsem
on two inodes in a few places to make sure our lock order matches
the one used in the VFS.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Tested-by: Jens Axboe <axboe@fb.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/xfs_file.c')
-rw-r--r-- | fs/xfs/xfs_file.c | 79 |
1 files changed, 23 insertions, 56 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index d818c160451f..d054b73b56fb 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -48,40 +48,6 @@ | |||
48 | static const struct vm_operations_struct xfs_file_vm_ops; | 48 | static const struct vm_operations_struct xfs_file_vm_ops; |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * Locking primitives for read and write IO paths to ensure we consistently use | ||
52 | * and order the inode->i_mutex, ip->i_lock and ip->i_iolock. | ||
53 | */ | ||
54 | static inline void | ||
55 | xfs_rw_ilock( | ||
56 | struct xfs_inode *ip, | ||
57 | int type) | ||
58 | { | ||
59 | if (type & XFS_IOLOCK_EXCL) | ||
60 | inode_lock(VFS_I(ip)); | ||
61 | xfs_ilock(ip, type); | ||
62 | } | ||
63 | |||
64 | static inline void | ||
65 | xfs_rw_iunlock( | ||
66 | struct xfs_inode *ip, | ||
67 | int type) | ||
68 | { | ||
69 | xfs_iunlock(ip, type); | ||
70 | if (type & XFS_IOLOCK_EXCL) | ||
71 | inode_unlock(VFS_I(ip)); | ||
72 | } | ||
73 | |||
74 | static inline void | ||
75 | xfs_rw_ilock_demote( | ||
76 | struct xfs_inode *ip, | ||
77 | int type) | ||
78 | { | ||
79 | xfs_ilock_demote(ip, type); | ||
80 | if (type & XFS_IOLOCK_EXCL) | ||
81 | inode_unlock(VFS_I(ip)); | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | * Clear the specified ranges to zero through either the pagecache or DAX. | 51 | * Clear the specified ranges to zero through either the pagecache or DAX. |
86 | * Holes and unwritten extents will be left as-is as they already are zeroed. | 52 | * Holes and unwritten extents will be left as-is as they already are zeroed. |
87 | */ | 53 | */ |
@@ -273,7 +239,7 @@ xfs_file_dio_aio_read( | |||
273 | 239 | ||
274 | file_accessed(iocb->ki_filp); | 240 | file_accessed(iocb->ki_filp); |
275 | 241 | ||
276 | xfs_rw_ilock(ip, XFS_IOLOCK_SHARED); | 242 | xfs_ilock(ip, XFS_IOLOCK_SHARED); |
277 | if (mapping->nrpages) { | 243 | if (mapping->nrpages) { |
278 | ret = filemap_write_and_wait_range(mapping, iocb->ki_pos, end); | 244 | ret = filemap_write_and_wait_range(mapping, iocb->ki_pos, end); |
279 | if (ret) | 245 | if (ret) |
@@ -299,7 +265,7 @@ xfs_file_dio_aio_read( | |||
299 | } | 265 | } |
300 | 266 | ||
301 | out_unlock: | 267 | out_unlock: |
302 | xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); | 268 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); |
303 | return ret; | 269 | return ret; |
304 | } | 270 | } |
305 | 271 | ||
@@ -317,9 +283,9 @@ xfs_file_dax_read( | |||
317 | if (!count) | 283 | if (!count) |
318 | return 0; /* skip atime */ | 284 | return 0; /* skip atime */ |
319 | 285 | ||
320 | xfs_rw_ilock(ip, XFS_IOLOCK_SHARED); | 286 | xfs_ilock(ip, XFS_IOLOCK_SHARED); |
321 | ret = dax_iomap_rw(iocb, to, &xfs_iomap_ops); | 287 | ret = dax_iomap_rw(iocb, to, &xfs_iomap_ops); |
322 | xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); | 288 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); |
323 | 289 | ||
324 | file_accessed(iocb->ki_filp); | 290 | file_accessed(iocb->ki_filp); |
325 | return ret; | 291 | return ret; |
@@ -335,9 +301,9 @@ xfs_file_buffered_aio_read( | |||
335 | 301 | ||
336 | trace_xfs_file_buffered_read(ip, iov_iter_count(to), iocb->ki_pos); | 302 | trace_xfs_file_buffered_read(ip, iov_iter_count(to), iocb->ki_pos); |
337 | 303 | ||
338 | xfs_rw_ilock(ip, XFS_IOLOCK_SHARED); | 304 | xfs_ilock(ip, XFS_IOLOCK_SHARED); |
339 | ret = generic_file_read_iter(iocb, to); | 305 | ret = generic_file_read_iter(iocb, to); |
340 | xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); | 306 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); |
341 | 307 | ||
342 | return ret; | 308 | return ret; |
343 | } | 309 | } |
@@ -418,15 +384,18 @@ restart: | |||
418 | if (error <= 0) | 384 | if (error <= 0) |
419 | return error; | 385 | return error; |
420 | 386 | ||
421 | error = xfs_break_layouts(inode, iolock, true); | 387 | error = xfs_break_layouts(inode, iolock); |
422 | if (error) | 388 | if (error) |
423 | return error; | 389 | return error; |
424 | 390 | ||
425 | /* For changing security info in file_remove_privs() we need i_mutex */ | 391 | /* |
392 | * For changing security info in file_remove_privs() we need i_rwsem | ||
393 | * exclusively. | ||
394 | */ | ||
426 | if (*iolock == XFS_IOLOCK_SHARED && !IS_NOSEC(inode)) { | 395 | if (*iolock == XFS_IOLOCK_SHARED && !IS_NOSEC(inode)) { |
427 | xfs_rw_iunlock(ip, *iolock); | 396 | xfs_iunlock(ip, *iolock); |
428 | *iolock = XFS_IOLOCK_EXCL; | 397 | *iolock = XFS_IOLOCK_EXCL; |
429 | xfs_rw_ilock(ip, *iolock); | 398 | xfs_ilock(ip, *iolock); |
430 | goto restart; | 399 | goto restart; |
431 | } | 400 | } |
432 | /* | 401 | /* |
@@ -451,9 +420,9 @@ restart: | |||
451 | spin_unlock(&ip->i_flags_lock); | 420 | spin_unlock(&ip->i_flags_lock); |
452 | if (!drained_dio) { | 421 | if (!drained_dio) { |
453 | if (*iolock == XFS_IOLOCK_SHARED) { | 422 | if (*iolock == XFS_IOLOCK_SHARED) { |
454 | xfs_rw_iunlock(ip, *iolock); | 423 | xfs_iunlock(ip, *iolock); |
455 | *iolock = XFS_IOLOCK_EXCL; | 424 | *iolock = XFS_IOLOCK_EXCL; |
456 | xfs_rw_ilock(ip, *iolock); | 425 | xfs_ilock(ip, *iolock); |
457 | iov_iter_reexpand(from, count); | 426 | iov_iter_reexpand(from, count); |
458 | } | 427 | } |
459 | /* | 428 | /* |
@@ -559,7 +528,7 @@ xfs_file_dio_aio_write( | |||
559 | iolock = XFS_IOLOCK_SHARED; | 528 | iolock = XFS_IOLOCK_SHARED; |
560 | } | 529 | } |
561 | 530 | ||
562 | xfs_rw_ilock(ip, iolock); | 531 | xfs_ilock(ip, iolock); |
563 | 532 | ||
564 | ret = xfs_file_aio_write_checks(iocb, from, &iolock); | 533 | ret = xfs_file_aio_write_checks(iocb, from, &iolock); |
565 | if (ret) | 534 | if (ret) |
@@ -591,7 +560,7 @@ xfs_file_dio_aio_write( | |||
591 | if (unaligned_io) | 560 | if (unaligned_io) |
592 | inode_dio_wait(inode); | 561 | inode_dio_wait(inode); |
593 | else if (iolock == XFS_IOLOCK_EXCL) { | 562 | else if (iolock == XFS_IOLOCK_EXCL) { |
594 | xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); | 563 | xfs_ilock_demote(ip, XFS_IOLOCK_EXCL); |
595 | iolock = XFS_IOLOCK_SHARED; | 564 | iolock = XFS_IOLOCK_SHARED; |
596 | } | 565 | } |
597 | 566 | ||
@@ -621,7 +590,7 @@ xfs_file_dio_aio_write( | |||
621 | iov_iter_advance(from, ret); | 590 | iov_iter_advance(from, ret); |
622 | } | 591 | } |
623 | out: | 592 | out: |
624 | xfs_rw_iunlock(ip, iolock); | 593 | xfs_iunlock(ip, iolock); |
625 | 594 | ||
626 | /* | 595 | /* |
627 | * No fallback to buffered IO on errors for XFS, direct IO will either | 596 | * No fallback to buffered IO on errors for XFS, direct IO will either |
@@ -643,7 +612,7 @@ xfs_file_dax_write( | |||
643 | size_t count; | 612 | size_t count; |
644 | loff_t pos; | 613 | loff_t pos; |
645 | 614 | ||
646 | xfs_rw_ilock(ip, iolock); | 615 | xfs_ilock(ip, iolock); |
647 | ret = xfs_file_aio_write_checks(iocb, from, &iolock); | 616 | ret = xfs_file_aio_write_checks(iocb, from, &iolock); |
648 | if (ret) | 617 | if (ret) |
649 | goto out; | 618 | goto out; |
@@ -652,15 +621,13 @@ xfs_file_dax_write( | |||
652 | count = iov_iter_count(from); | 621 | count = iov_iter_count(from); |
653 | 622 | ||
654 | trace_xfs_file_dax_write(ip, count, pos); | 623 | trace_xfs_file_dax_write(ip, count, pos); |
655 | |||
656 | ret = dax_iomap_rw(iocb, from, &xfs_iomap_ops); | 624 | ret = dax_iomap_rw(iocb, from, &xfs_iomap_ops); |
657 | if (ret > 0 && iocb->ki_pos > i_size_read(inode)) { | 625 | if (ret > 0 && iocb->ki_pos > i_size_read(inode)) { |
658 | i_size_write(inode, iocb->ki_pos); | 626 | i_size_write(inode, iocb->ki_pos); |
659 | error = xfs_setfilesize(ip, pos, ret); | 627 | error = xfs_setfilesize(ip, pos, ret); |
660 | } | 628 | } |
661 | |||
662 | out: | 629 | out: |
663 | xfs_rw_iunlock(ip, iolock); | 630 | xfs_iunlock(ip, iolock); |
664 | return error ? error : ret; | 631 | return error ? error : ret; |
665 | } | 632 | } |
666 | 633 | ||
@@ -677,7 +644,7 @@ xfs_file_buffered_aio_write( | |||
677 | int enospc = 0; | 644 | int enospc = 0; |
678 | int iolock = XFS_IOLOCK_EXCL; | 645 | int iolock = XFS_IOLOCK_EXCL; |
679 | 646 | ||
680 | xfs_rw_ilock(ip, iolock); | 647 | xfs_ilock(ip, iolock); |
681 | 648 | ||
682 | ret = xfs_file_aio_write_checks(iocb, from, &iolock); | 649 | ret = xfs_file_aio_write_checks(iocb, from, &iolock); |
683 | if (ret) | 650 | if (ret) |
@@ -721,7 +688,7 @@ write_retry: | |||
721 | 688 | ||
722 | current->backing_dev_info = NULL; | 689 | current->backing_dev_info = NULL; |
723 | out: | 690 | out: |
724 | xfs_rw_iunlock(ip, iolock); | 691 | xfs_iunlock(ip, iolock); |
725 | return ret; | 692 | return ret; |
726 | } | 693 | } |
727 | 694 | ||
@@ -797,7 +764,7 @@ xfs_file_fallocate( | |||
797 | return -EOPNOTSUPP; | 764 | return -EOPNOTSUPP; |
798 | 765 | ||
799 | xfs_ilock(ip, iolock); | 766 | xfs_ilock(ip, iolock); |
800 | error = xfs_break_layouts(inode, &iolock, false); | 767 | error = xfs_break_layouts(inode, &iolock); |
801 | if (error) | 768 | if (error) |
802 | goto out_unlock; | 769 | goto out_unlock; |
803 | 770 | ||