diff options
| -rw-r--r-- | fs/ceph/file.c | 2 | ||||
| -rw-r--r-- | fs/ceph/inode.c | 124 | ||||
| -rw-r--r-- | fs/ceph/super.c | 28 | ||||
| -rw-r--r-- | fs/ceph/super.h | 17 |
4 files changed, 74 insertions, 97 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 305daf043eb0..183c37c0a8fc 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
| @@ -791,7 +791,7 @@ static void ceph_aio_complete_req(struct ceph_osd_request *req) | |||
| 791 | if (aio_work) { | 791 | if (aio_work) { |
| 792 | INIT_WORK(&aio_work->work, ceph_aio_retry_work); | 792 | INIT_WORK(&aio_work->work, ceph_aio_retry_work); |
| 793 | aio_work->req = req; | 793 | aio_work->req = req; |
| 794 | queue_work(ceph_inode_to_client(inode)->wb_wq, | 794 | queue_work(ceph_inode_to_client(inode)->inode_wq, |
| 795 | &aio_work->work); | 795 | &aio_work->work); |
| 796 | return; | 796 | return; |
| 797 | } | 797 | } |
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 | */ |
diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 01be7c1bc4c6..d57fa60dcd43 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c | |||
| @@ -672,18 +672,12 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt, | |||
| 672 | * The number of concurrent works can be high but they don't need | 672 | * The number of concurrent works can be high but they don't need |
| 673 | * to be processed in parallel, limit concurrency. | 673 | * to be processed in parallel, limit concurrency. |
| 674 | */ | 674 | */ |
| 675 | fsc->wb_wq = alloc_workqueue("ceph-writeback", 0, 1); | 675 | fsc->inode_wq = alloc_workqueue("ceph-inode", WQ_UNBOUND, 0); |
| 676 | if (!fsc->wb_wq) | 676 | if (!fsc->inode_wq) |
| 677 | goto fail_client; | 677 | goto fail_client; |
| 678 | fsc->pg_inv_wq = alloc_workqueue("ceph-pg-invalid", 0, 1); | ||
| 679 | if (!fsc->pg_inv_wq) | ||
| 680 | goto fail_wb_wq; | ||
| 681 | fsc->trunc_wq = alloc_workqueue("ceph-trunc", 0, 1); | ||
| 682 | if (!fsc->trunc_wq) | ||
| 683 | goto fail_pg_inv_wq; | ||
| 684 | fsc->cap_wq = alloc_workqueue("ceph-cap", 0, 1); | 678 | fsc->cap_wq = alloc_workqueue("ceph-cap", 0, 1); |
| 685 | if (!fsc->cap_wq) | 679 | if (!fsc->cap_wq) |
| 686 | goto fail_trunc_wq; | 680 | goto fail_inode_wq; |
| 687 | 681 | ||
| 688 | /* set up mempools */ | 682 | /* set up mempools */ |
| 689 | err = -ENOMEM; | 683 | err = -ENOMEM; |
| @@ -697,12 +691,8 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt, | |||
| 697 | 691 | ||
| 698 | fail_cap_wq: | 692 | fail_cap_wq: |
| 699 | destroy_workqueue(fsc->cap_wq); | 693 | destroy_workqueue(fsc->cap_wq); |
| 700 | fail_trunc_wq: | 694 | fail_inode_wq: |
| 701 | destroy_workqueue(fsc->trunc_wq); | 695 | destroy_workqueue(fsc->inode_wq); |
| 702 | fail_pg_inv_wq: | ||
| 703 | destroy_workqueue(fsc->pg_inv_wq); | ||
| 704 | fail_wb_wq: | ||
| 705 | destroy_workqueue(fsc->wb_wq); | ||
| 706 | fail_client: | 696 | fail_client: |
| 707 | ceph_destroy_client(fsc->client); | 697 | ceph_destroy_client(fsc->client); |
| 708 | fail: | 698 | fail: |
| @@ -715,9 +705,7 @@ fail: | |||
| 715 | 705 | ||
| 716 | static void flush_fs_workqueues(struct ceph_fs_client *fsc) | 706 | static void flush_fs_workqueues(struct ceph_fs_client *fsc) |
| 717 | { | 707 | { |
| 718 | flush_workqueue(fsc->wb_wq); | 708 | flush_workqueue(fsc->inode_wq); |
| 719 | flush_workqueue(fsc->pg_inv_wq); | ||
| 720 | flush_workqueue(fsc->trunc_wq); | ||
| 721 | flush_workqueue(fsc->cap_wq); | 709 | flush_workqueue(fsc->cap_wq); |
| 722 | } | 710 | } |
| 723 | 711 | ||
| @@ -725,9 +713,7 @@ static void destroy_fs_client(struct ceph_fs_client *fsc) | |||
| 725 | { | 713 | { |
| 726 | dout("destroy_fs_client %p\n", fsc); | 714 | dout("destroy_fs_client %p\n", fsc); |
| 727 | 715 | ||
| 728 | destroy_workqueue(fsc->wb_wq); | 716 | destroy_workqueue(fsc->inode_wq); |
| 729 | destroy_workqueue(fsc->pg_inv_wq); | ||
| 730 | destroy_workqueue(fsc->trunc_wq); | ||
| 731 | destroy_workqueue(fsc->cap_wq); | 717 | destroy_workqueue(fsc->cap_wq); |
| 732 | 718 | ||
| 733 | mempool_destroy(fsc->wb_pagevec_pool); | 719 | mempool_destroy(fsc->wb_pagevec_pool); |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 6edab9a750f8..3fb866a979ce 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
| @@ -109,9 +109,7 @@ struct ceph_fs_client { | |||
| 109 | mempool_t *wb_pagevec_pool; | 109 | mempool_t *wb_pagevec_pool; |
| 110 | atomic_long_t writeback_count; | 110 | atomic_long_t writeback_count; |
| 111 | 111 | ||
| 112 | struct workqueue_struct *wb_wq; | 112 | struct workqueue_struct *inode_wq; |
| 113 | struct workqueue_struct *pg_inv_wq; | ||
| 114 | struct workqueue_struct *trunc_wq; | ||
| 115 | struct workqueue_struct *cap_wq; | 113 | struct workqueue_struct *cap_wq; |
| 116 | 114 | ||
| 117 | #ifdef CONFIG_DEBUG_FS | 115 | #ifdef CONFIG_DEBUG_FS |
| @@ -387,10 +385,8 @@ struct ceph_inode_info { | |||
| 387 | struct list_head i_snap_realm_item; | 385 | struct list_head i_snap_realm_item; |
| 388 | struct list_head i_snap_flush_item; | 386 | struct list_head i_snap_flush_item; |
| 389 | 387 | ||
| 390 | struct work_struct i_wb_work; /* writeback work */ | 388 | struct work_struct i_work; |
| 391 | struct work_struct i_pg_inv_work; /* page invalidation work */ | 389 | unsigned long i_work_mask; |
| 392 | |||
| 393 | struct work_struct i_vmtruncate_work; | ||
| 394 | 390 | ||
| 395 | #ifdef CONFIG_CEPH_FSCACHE | 391 | #ifdef CONFIG_CEPH_FSCACHE |
| 396 | struct fscache_cookie *fscache; | 392 | struct fscache_cookie *fscache; |
| @@ -513,6 +509,13 @@ static inline struct inode *ceph_find_inode(struct super_block *sb, | |||
| 513 | 509 | ||
| 514 | 510 | ||
| 515 | /* | 511 | /* |
| 512 | * Masks of ceph inode work. | ||
| 513 | */ | ||
| 514 | #define CEPH_I_WORK_WRITEBACK 0 /* writeback */ | ||
| 515 | #define CEPH_I_WORK_INVALIDATE_PAGES 1 /* invalidate pages */ | ||
| 516 | #define CEPH_I_WORK_VMTRUNCATE 2 /* vmtruncate */ | ||
| 517 | |||
| 518 | /* | ||
| 516 | * We set the ERROR_WRITE bit when we start seeing write errors on an inode | 519 | * We set the ERROR_WRITE bit when we start seeing write errors on an inode |
| 517 | * and then clear it when they start succeeding. Note that we do a lockless | 520 | * and then clear it when they start succeeding. Note that we do a lockless |
| 518 | * check first, and only take the lock if it looks like it needs to be changed. | 521 | * check first, and only take the lock if it looks like it needs to be changed. |
