summaryrefslogtreecommitdiffstats
path: root/fs/ceph
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2019-05-17 23:18:44 -0400
committerIlya Dryomov <idryomov@gmail.com>2019-06-05 14:34:39 -0400
commit1cf89a8dee5e6e9d4fcb81b571a54d40068dfbb7 (patch)
tree7b6efc6b2c66d905c9c9be2842ba4d3a7bbf67f0 /fs/ceph
parentf2c7c76c5d0a443053e94adb9f0918fa2fb85c3a (diff)
ceph: single workqueue for inode related works
We have three workqueue for inode works. Later patch will introduce one more work for inode. It's not good to introcuce more workqueue and add more 'struct work_struct' to 'struct ceph_inode_info'. Signed-off-by: "Yan, Zheng" <zyan@redhat.com> Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/file.c2
-rw-r--r--fs/ceph/inode.c124
-rw-r--r--fs/ceph/super.c28
-rw-r--r--fs/ceph/super.h17
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
34static const struct inode_operations ceph_symlink_iops; 34static const struct inode_operations ceph_symlink_iops;
35 35
36static void ceph_invalidate_work(struct work_struct *work); 36static void ceph_inode_work(struct work_struct *work);
37static void ceph_writeback_work(struct work_struct *work);
38static 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 */
1747void ceph_queue_writeback(struct inode *inode) 1743void 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
1759static 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 */
1773void ceph_queue_invalidate(struct inode *inode) 1762void 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 */
1789static void ceph_invalidate_work(struct work_struct *work) 1782void 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
1798static 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)
1842out: 1849out:
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 */
1854static 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 */
1869void 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
1915static 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
698fail_cap_wq: 692fail_cap_wq:
699 destroy_workqueue(fsc->cap_wq); 693 destroy_workqueue(fsc->cap_wq);
700fail_trunc_wq: 694fail_inode_wq:
701 destroy_workqueue(fsc->trunc_wq); 695 destroy_workqueue(fsc->inode_wq);
702fail_pg_inv_wq:
703 destroy_workqueue(fsc->pg_inv_wq);
704fail_wb_wq:
705 destroy_workqueue(fsc->wb_wq);
706fail_client: 696fail_client:
707 ceph_destroy_client(fsc->client); 697 ceph_destroy_client(fsc->client);
708fail: 698fail:
@@ -715,9 +705,7 @@ fail:
715 705
716static void flush_fs_workqueues(struct ceph_fs_client *fsc) 706static 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.