aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_file.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2016-11-29 22:33:25 -0500
committerDave Chinner <david@fromorbit.com>2016-11-29 22:33:25 -0500
commit6552321831dce87ff5c466a55b58d472732caadc (patch)
tree84f3de7b89690c84fd13e2efa7a85d4918d342e3 /fs/xfs/xfs_file.c
parentf8319483f57f1ca22370f4150bb990aca7728a67 (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.c79
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 @@
48static const struct vm_operations_struct xfs_file_vm_ops; 48static 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 */
54static inline void
55xfs_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
64static inline void
65xfs_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
74static inline void
75xfs_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
301out_unlock: 267out_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 }
623out: 592out:
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
662out: 629out:
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;
723out: 690out:
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