diff options
Diffstat (limited to 'fs/ceph/inode.c')
-rw-r--r-- | fs/ceph/inode.c | 124 |
1 files changed, 56 insertions, 68 deletions
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index f85355bf49c4..3acdd3cc6039 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -33,9 +33,7 @@ | |||
33 | 33 | ||
34 | static const struct inode_operations ceph_symlink_iops; | 34 | static const struct inode_operations ceph_symlink_iops; |
35 | 35 | ||
36 | static void ceph_invalidate_work(struct work_struct *work); | 36 | static void ceph_inode_work(struct work_struct *work); |
37 | static void ceph_writeback_work(struct work_struct *work); | ||
38 | static void ceph_vmtruncate_work(struct work_struct *work); | ||
39 | 37 | ||
40 | /* | 38 | /* |
41 | * find or create an inode, given the ceph ino number | 39 | * find or create an inode, given the ceph ino number |
@@ -509,10 +507,8 @@ struct inode *ceph_alloc_inode(struct super_block *sb) | |||
509 | INIT_LIST_HEAD(&ci->i_snap_realm_item); | 507 | INIT_LIST_HEAD(&ci->i_snap_realm_item); |
510 | INIT_LIST_HEAD(&ci->i_snap_flush_item); | 508 | INIT_LIST_HEAD(&ci->i_snap_flush_item); |
511 | 509 | ||
512 | INIT_WORK(&ci->i_wb_work, ceph_writeback_work); | 510 | INIT_WORK(&ci->i_work, ceph_inode_work); |
513 | INIT_WORK(&ci->i_pg_inv_work, ceph_invalidate_work); | 511 | ci->i_work_mask = 0; |
514 | |||
515 | INIT_WORK(&ci->i_vmtruncate_work, ceph_vmtruncate_work); | ||
516 | 512 | ||
517 | ceph_fscache_inode_init(ci); | 513 | ceph_fscache_inode_init(ci); |
518 | 514 | ||
@@ -1746,51 +1742,62 @@ bool ceph_inode_set_size(struct inode *inode, loff_t size) | |||
1746 | */ | 1742 | */ |
1747 | void ceph_queue_writeback(struct inode *inode) | 1743 | void ceph_queue_writeback(struct inode *inode) |
1748 | { | 1744 | { |
1745 | struct ceph_inode_info *ci = ceph_inode(inode); | ||
1746 | set_bit(CEPH_I_WORK_WRITEBACK, &ci->i_work_mask); | ||
1747 | |||
1749 | ihold(inode); | 1748 | ihold(inode); |
1750 | if (queue_work(ceph_inode_to_client(inode)->wb_wq, | 1749 | if (queue_work(ceph_inode_to_client(inode)->inode_wq, |
1751 | &ceph_inode(inode)->i_wb_work)) { | 1750 | &ci->i_work)) { |
1752 | dout("ceph_queue_writeback %p\n", inode); | 1751 | dout("ceph_queue_writeback %p\n", inode); |
1753 | } else { | 1752 | } else { |
1754 | dout("ceph_queue_writeback %p failed\n", inode); | 1753 | dout("ceph_queue_writeback %p already queued, mask=%lx\n", |
1754 | inode, ci->i_work_mask); | ||
1755 | iput(inode); | 1755 | iput(inode); |
1756 | } | 1756 | } |
1757 | } | 1757 | } |
1758 | 1758 | ||
1759 | static void ceph_writeback_work(struct work_struct *work) | ||
1760 | { | ||
1761 | struct ceph_inode_info *ci = container_of(work, struct ceph_inode_info, | ||
1762 | i_wb_work); | ||
1763 | struct inode *inode = &ci->vfs_inode; | ||
1764 | |||
1765 | dout("writeback %p\n", inode); | ||
1766 | filemap_fdatawrite(&inode->i_data); | ||
1767 | iput(inode); | ||
1768 | } | ||
1769 | |||
1770 | /* | 1759 | /* |
1771 | * queue an async invalidation | 1760 | * queue an async invalidation |
1772 | */ | 1761 | */ |
1773 | void ceph_queue_invalidate(struct inode *inode) | 1762 | void ceph_queue_invalidate(struct inode *inode) |
1774 | { | 1763 | { |
1764 | struct ceph_inode_info *ci = ceph_inode(inode); | ||
1765 | set_bit(CEPH_I_WORK_INVALIDATE_PAGES, &ci->i_work_mask); | ||
1766 | |||
1775 | ihold(inode); | 1767 | ihold(inode); |
1776 | if (queue_work(ceph_inode_to_client(inode)->pg_inv_wq, | 1768 | if (queue_work(ceph_inode_to_client(inode)->inode_wq, |
1777 | &ceph_inode(inode)->i_pg_inv_work)) { | 1769 | &ceph_inode(inode)->i_work)) { |
1778 | dout("ceph_queue_invalidate %p\n", inode); | 1770 | dout("ceph_queue_invalidate %p\n", inode); |
1779 | } else { | 1771 | } else { |
1780 | dout("ceph_queue_invalidate %p failed\n", inode); | 1772 | dout("ceph_queue_invalidate %p already queued, mask=%lx\n", |
1773 | inode, ci->i_work_mask); | ||
1781 | iput(inode); | 1774 | iput(inode); |
1782 | } | 1775 | } |
1783 | } | 1776 | } |
1784 | 1777 | ||
1785 | /* | 1778 | /* |
1786 | * Invalidate inode pages in a worker thread. (This can't be done | 1779 | * Queue an async vmtruncate. If we fail to queue work, we will handle |
1787 | * in the message handler context.) | 1780 | * the truncation the next time we call __ceph_do_pending_vmtruncate. |
1788 | */ | 1781 | */ |
1789 | static void ceph_invalidate_work(struct work_struct *work) | 1782 | void ceph_queue_vmtruncate(struct inode *inode) |
1790 | { | 1783 | { |
1791 | struct ceph_inode_info *ci = container_of(work, struct ceph_inode_info, | 1784 | struct ceph_inode_info *ci = ceph_inode(inode); |
1792 | i_pg_inv_work); | 1785 | set_bit(CEPH_I_WORK_VMTRUNCATE, &ci->i_work_mask); |
1793 | struct inode *inode = &ci->vfs_inode; | 1786 | |
1787 | ihold(inode); | ||
1788 | if (queue_work(ceph_inode_to_client(inode)->inode_wq, | ||
1789 | &ci->i_work)) { | ||
1790 | dout("ceph_queue_vmtruncate %p\n", inode); | ||
1791 | } else { | ||
1792 | dout("ceph_queue_vmtruncate %p already queued, mask=%lx\n", | ||
1793 | inode, ci->i_work_mask); | ||
1794 | iput(inode); | ||
1795 | } | ||
1796 | } | ||
1797 | |||
1798 | static void ceph_do_invalidate_pages(struct inode *inode) | ||
1799 | { | ||
1800 | struct ceph_inode_info *ci = ceph_inode(inode); | ||
1794 | struct ceph_fs_client *fsc = ceph_inode_to_client(inode); | 1801 | struct ceph_fs_client *fsc = ceph_inode_to_client(inode); |
1795 | u32 orig_gen; | 1802 | u32 orig_gen; |
1796 | int check = 0; | 1803 | int check = 0; |
@@ -1842,44 +1849,6 @@ static void ceph_invalidate_work(struct work_struct *work) | |||
1842 | out: | 1849 | out: |
1843 | if (check) | 1850 | if (check) |
1844 | ceph_check_caps(ci, 0, NULL); | 1851 | ceph_check_caps(ci, 0, NULL); |
1845 | iput(inode); | ||
1846 | } | ||
1847 | |||
1848 | |||
1849 | /* | ||
1850 | * called by trunc_wq; | ||
1851 | * | ||
1852 | * We also truncate in a separate thread as well. | ||
1853 | */ | ||
1854 | static void ceph_vmtruncate_work(struct work_struct *work) | ||
1855 | { | ||
1856 | struct ceph_inode_info *ci = container_of(work, struct ceph_inode_info, | ||
1857 | i_vmtruncate_work); | ||
1858 | struct inode *inode = &ci->vfs_inode; | ||
1859 | |||
1860 | dout("vmtruncate_work %p\n", inode); | ||
1861 | __ceph_do_pending_vmtruncate(inode); | ||
1862 | iput(inode); | ||
1863 | } | ||
1864 | |||
1865 | /* | ||
1866 | * Queue an async vmtruncate. If we fail to queue work, we will handle | ||
1867 | * the truncation the next time we call __ceph_do_pending_vmtruncate. | ||
1868 | */ | ||
1869 | void ceph_queue_vmtruncate(struct inode *inode) | ||
1870 | { | ||
1871 | struct ceph_inode_info *ci = ceph_inode(inode); | ||
1872 | |||
1873 | ihold(inode); | ||
1874 | |||
1875 | if (queue_work(ceph_sb_to_client(inode->i_sb)->trunc_wq, | ||
1876 | &ci->i_vmtruncate_work)) { | ||
1877 | dout("ceph_queue_vmtruncate %p\n", inode); | ||
1878 | } else { | ||
1879 | dout("ceph_queue_vmtruncate %p failed, pending=%d\n", | ||
1880 | inode, ci->i_truncate_pending); | ||
1881 | iput(inode); | ||
1882 | } | ||
1883 | } | 1852 | } |
1884 | 1853 | ||
1885 | /* | 1854 | /* |
@@ -1943,6 +1912,25 @@ retry: | |||
1943 | wake_up_all(&ci->i_cap_wq); | 1912 | wake_up_all(&ci->i_cap_wq); |
1944 | } | 1913 | } |
1945 | 1914 | ||
1915 | static void ceph_inode_work(struct work_struct *work) | ||
1916 | { | ||
1917 | struct ceph_inode_info *ci = container_of(work, struct ceph_inode_info, | ||
1918 | i_work); | ||
1919 | struct inode *inode = &ci->vfs_inode; | ||
1920 | |||
1921 | if (test_and_clear_bit(CEPH_I_WORK_WRITEBACK, &ci->i_work_mask)) { | ||
1922 | dout("writeback %p\n", inode); | ||
1923 | filemap_fdatawrite(&inode->i_data); | ||
1924 | } | ||
1925 | if (test_and_clear_bit(CEPH_I_WORK_INVALIDATE_PAGES, &ci->i_work_mask)) | ||
1926 | ceph_do_invalidate_pages(inode); | ||
1927 | |||
1928 | if (test_and_clear_bit(CEPH_I_WORK_VMTRUNCATE, &ci->i_work_mask)) | ||
1929 | __ceph_do_pending_vmtruncate(inode); | ||
1930 | |||
1931 | iput(inode); | ||
1932 | } | ||
1933 | |||
1946 | /* | 1934 | /* |
1947 | * symlinks | 1935 | * symlinks |
1948 | */ | 1936 | */ |