diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2013-02-28 21:57:54 -0500 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-05-02 00:16:11 -0400 |
commit | 3f99969f42300e52779ae0656678c2534097f2ea (patch) | |
tree | b3b07bc105f3c966c8a50e0d2e3bac5e5f3b4eeb /fs | |
parent | 6070e0c1e2b515ad5edc2f8224031b051bd08109 (diff) |
ceph: acquire i_mutex in __ceph_do_pending_vmtruncate
make __ceph_do_pending_vmtruncate() acquire the i_mutex if the caller
does not hold the i_mutex, so ceph_aio_read() can call safely.
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Reviewed-by: Greg Farnum <greg@inktank.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/file.c | 6 | ||||
-rw-r--r-- | fs/ceph/inode.c | 18 | ||||
-rw-r--r-- | fs/ceph/super.h | 2 |
3 files changed, 13 insertions, 13 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 3d1aefeee948..dd47026c6064 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -653,7 +653,7 @@ static ssize_t ceph_aio_read(struct kiocb *iocb, const struct iovec *iov, | |||
653 | dout("aio_read %p %llx.%llx %llu~%u trying to get caps on %p\n", | 653 | dout("aio_read %p %llx.%llx %llu~%u trying to get caps on %p\n", |
654 | inode, ceph_vinop(inode), pos, (unsigned)len, inode); | 654 | inode, ceph_vinop(inode), pos, (unsigned)len, inode); |
655 | again: | 655 | again: |
656 | __ceph_do_pending_vmtruncate(inode); | 656 | __ceph_do_pending_vmtruncate(inode, true); |
657 | if (fi->fmode & CEPH_FILE_MODE_LAZY) | 657 | if (fi->fmode & CEPH_FILE_MODE_LAZY) |
658 | want = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO; | 658 | want = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO; |
659 | else | 659 | else |
@@ -730,7 +730,7 @@ retry_snap: | |||
730 | ret = -ENOSPC; | 730 | ret = -ENOSPC; |
731 | goto out; | 731 | goto out; |
732 | } | 732 | } |
733 | __ceph_do_pending_vmtruncate(inode); | 733 | __ceph_do_pending_vmtruncate(inode, true); |
734 | dout("aio_write %p %llx.%llx %llu~%u getting caps. i_size %llu\n", | 734 | dout("aio_write %p %llx.%llx %llu~%u getting caps. i_size %llu\n", |
735 | inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len, | 735 | inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len, |
736 | inode->i_size); | 736 | inode->i_size); |
@@ -801,7 +801,7 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int whence) | |||
801 | int ret; | 801 | int ret; |
802 | 802 | ||
803 | mutex_lock(&inode->i_mutex); | 803 | mutex_lock(&inode->i_mutex); |
804 | __ceph_do_pending_vmtruncate(inode); | 804 | __ceph_do_pending_vmtruncate(inode, false); |
805 | 805 | ||
806 | if (whence == SEEK_END || whence == SEEK_DATA || whence == SEEK_HOLE) { | 806 | if (whence == SEEK_END || whence == SEEK_DATA || whence == SEEK_HOLE) { |
807 | ret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE); | 807 | ret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE); |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index be2f262b822d..eeac43dd04eb 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -1453,7 +1453,7 @@ out: | |||
1453 | 1453 | ||
1454 | 1454 | ||
1455 | /* | 1455 | /* |
1456 | * called by trunc_wq; take i_mutex ourselves | 1456 | * called by trunc_wq; |
1457 | * | 1457 | * |
1458 | * We also truncate in a separate thread as well. | 1458 | * We also truncate in a separate thread as well. |
1459 | */ | 1459 | */ |
@@ -1464,9 +1464,7 @@ static void ceph_vmtruncate_work(struct work_struct *work) | |||
1464 | struct inode *inode = &ci->vfs_inode; | 1464 | struct inode *inode = &ci->vfs_inode; |
1465 | 1465 | ||
1466 | dout("vmtruncate_work %p\n", inode); | 1466 | dout("vmtruncate_work %p\n", inode); |
1467 | mutex_lock(&inode->i_mutex); | 1467 | __ceph_do_pending_vmtruncate(inode, true); |
1468 | __ceph_do_pending_vmtruncate(inode); | ||
1469 | mutex_unlock(&inode->i_mutex); | ||
1470 | iput(inode); | 1468 | iput(inode); |
1471 | } | 1469 | } |
1472 | 1470 | ||
@@ -1490,12 +1488,10 @@ void ceph_queue_vmtruncate(struct inode *inode) | |||
1490 | } | 1488 | } |
1491 | 1489 | ||
1492 | /* | 1490 | /* |
1493 | * called with i_mutex held. | ||
1494 | * | ||
1495 | * Make sure any pending truncation is applied before doing anything | 1491 | * Make sure any pending truncation is applied before doing anything |
1496 | * that may depend on it. | 1492 | * that may depend on it. |
1497 | */ | 1493 | */ |
1498 | void __ceph_do_pending_vmtruncate(struct inode *inode) | 1494 | void __ceph_do_pending_vmtruncate(struct inode *inode, bool needlock) |
1499 | { | 1495 | { |
1500 | struct ceph_inode_info *ci = ceph_inode(inode); | 1496 | struct ceph_inode_info *ci = ceph_inode(inode); |
1501 | u64 to; | 1497 | u64 to; |
@@ -1528,7 +1524,11 @@ retry: | |||
1528 | ci->i_truncate_pending, to); | 1524 | ci->i_truncate_pending, to); |
1529 | spin_unlock(&ci->i_ceph_lock); | 1525 | spin_unlock(&ci->i_ceph_lock); |
1530 | 1526 | ||
1527 | if (needlock) | ||
1528 | mutex_lock(&inode->i_mutex); | ||
1531 | truncate_inode_pages(inode->i_mapping, to); | 1529 | truncate_inode_pages(inode->i_mapping, to); |
1530 | if (needlock) | ||
1531 | mutex_unlock(&inode->i_mutex); | ||
1532 | 1532 | ||
1533 | spin_lock(&ci->i_ceph_lock); | 1533 | spin_lock(&ci->i_ceph_lock); |
1534 | if (to == ci->i_truncate_size) { | 1534 | if (to == ci->i_truncate_size) { |
@@ -1581,7 +1581,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) | |||
1581 | if (ceph_snap(inode) != CEPH_NOSNAP) | 1581 | if (ceph_snap(inode) != CEPH_NOSNAP) |
1582 | return -EROFS; | 1582 | return -EROFS; |
1583 | 1583 | ||
1584 | __ceph_do_pending_vmtruncate(inode); | 1584 | __ceph_do_pending_vmtruncate(inode, false); |
1585 | 1585 | ||
1586 | err = inode_change_ok(inode, attr); | 1586 | err = inode_change_ok(inode, attr); |
1587 | if (err != 0) | 1587 | if (err != 0) |
@@ -1763,7 +1763,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) | |||
1763 | ceph_cap_string(dirtied), mask); | 1763 | ceph_cap_string(dirtied), mask); |
1764 | 1764 | ||
1765 | ceph_mdsc_put_request(req); | 1765 | ceph_mdsc_put_request(req); |
1766 | __ceph_do_pending_vmtruncate(inode); | 1766 | __ceph_do_pending_vmtruncate(inode, false); |
1767 | return err; | 1767 | return err; |
1768 | out: | 1768 | out: |
1769 | spin_unlock(&ci->i_ceph_lock); | 1769 | spin_unlock(&ci->i_ceph_lock); |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 20dd1ee3c4f0..a04eda714df4 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -694,7 +694,7 @@ extern int ceph_readdir_prepopulate(struct ceph_mds_request *req, | |||
694 | extern int ceph_inode_holds_cap(struct inode *inode, int mask); | 694 | extern int ceph_inode_holds_cap(struct inode *inode, int mask); |
695 | 695 | ||
696 | extern int ceph_inode_set_size(struct inode *inode, loff_t size); | 696 | extern int ceph_inode_set_size(struct inode *inode, loff_t size); |
697 | extern void __ceph_do_pending_vmtruncate(struct inode *inode); | 697 | extern void __ceph_do_pending_vmtruncate(struct inode *inode, bool needlock); |
698 | extern void ceph_queue_vmtruncate(struct inode *inode); | 698 | extern void ceph_queue_vmtruncate(struct inode *inode); |
699 | 699 | ||
700 | extern void ceph_queue_invalidate(struct inode *inode); | 700 | extern void ceph_queue_invalidate(struct inode *inode); |