aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Coddington <bcodding@redhat.com>2016-01-06 10:40:18 -0500
committerTrond Myklebust <trond.myklebust@primarydata.com>2016-01-07 18:42:51 -0500
commit210c7c1750fdf769647d1d526c9ea34c412c9eee (patch)
treed3e6e91f525fad7ab5fb23f38075af32184cc87c
parent942e3d72a62dcfe5bf1569b179174718bbbcfbc3 (diff)
NFS: Use wait_on_atomic_t() for unlock after readahead
The use of wait_on_atomic_t() for waiting on I/O to complete before unlocking allows us to git rid of the NFS_IO_INPROGRESS flag, and thus the nfs_iocounter's flags member, and finally the nfs_iocounter altogether. The count of I/O is moved to the lock context, and the counter increment/decrement functions become simple enough to open-code. Signed-off-by: Benjamin Coddington <bcodding@redhat.com> [Trond: Fix up conflict with existing function nfs_wait_atomic_killable()] Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r--fs/nfs/file.c2
-rw-r--r--fs/nfs/inode.c18
-rw-r--r--fs/nfs/internal.h9
-rw-r--r--fs/nfs/pagelist.c48
-rw-r--r--fs/nfs/write.c8
-rw-r--r--include/linux/nfs_fs.h8
6 files changed, 23 insertions, 70 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 178ec8da028f..4ef8f5addcad 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -756,7 +756,7 @@ do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
756 756
757 l_ctx = nfs_get_lock_context(nfs_file_open_context(filp)); 757 l_ctx = nfs_get_lock_context(nfs_file_open_context(filp));
758 if (!IS_ERR(l_ctx)) { 758 if (!IS_ERR(l_ctx)) {
759 status = nfs_iocounter_wait(&l_ctx->io_count); 759 status = nfs_iocounter_wait(l_ctx);
760 nfs_put_lock_context(l_ctx); 760 nfs_put_lock_context(l_ctx);
761 if (status < 0) 761 if (status < 0)
762 return status; 762 return status;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 74fb1223c2f5..4b63d1bd5820 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -71,19 +71,25 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
71 return nfs_fileid_to_ino_t(fattr->fileid); 71 return nfs_fileid_to_ino_t(fattr->fileid);
72} 72}
73 73
74/** 74static int nfs_wait_killable(int mode)
75 * nfs_wait_bit_killable - helper for functions that are sleeping on bit locks
76 * @word: long word containing the bit lock
77 */
78int nfs_wait_bit_killable(struct wait_bit_key *key, int mode)
79{ 75{
80 freezable_schedule_unsafe(); 76 freezable_schedule_unsafe();
81 if (signal_pending_state(mode, current)) 77 if (signal_pending_state(mode, current))
82 return -ERESTARTSYS; 78 return -ERESTARTSYS;
83 return 0; 79 return 0;
84} 80}
81
82int nfs_wait_bit_killable(struct wait_bit_key *key, int mode)
83{
84 return nfs_wait_killable(mode);
85}
85EXPORT_SYMBOL_GPL(nfs_wait_bit_killable); 86EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
86 87
88int nfs_wait_atomic_killable(atomic_t *p)
89{
90 return nfs_wait_killable(TASK_KILLABLE);
91}
92
87/** 93/**
88 * nfs_compat_user_ino64 - returns the user-visible inode number 94 * nfs_compat_user_ino64 - returns the user-visible inode number
89 * @fileid: 64-bit fileid 95 * @fileid: 64-bit fileid
@@ -699,7 +705,7 @@ static void nfs_init_lock_context(struct nfs_lock_context *l_ctx)
699 l_ctx->lockowner.l_owner = current->files; 705 l_ctx->lockowner.l_owner = current->files;
700 l_ctx->lockowner.l_pid = current->tgid; 706 l_ctx->lockowner.l_pid = current->tgid;
701 INIT_LIST_HEAD(&l_ctx->list); 707 INIT_LIST_HEAD(&l_ctx->list);
702 nfs_iocounter_init(&l_ctx->io_count); 708 atomic_set(&l_ctx->io_count, 0);
703} 709}
704 710
705static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context *ctx) 711static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context *ctx)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index ee81792d2886..4e8cc942336c 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -238,7 +238,7 @@ extern void nfs_pgheader_init(struct nfs_pageio_descriptor *desc,
238 struct nfs_pgio_header *hdr, 238 struct nfs_pgio_header *hdr,
239 void (*release)(struct nfs_pgio_header *hdr)); 239 void (*release)(struct nfs_pgio_header *hdr));
240void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos); 240void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos);
241int nfs_iocounter_wait(struct nfs_io_counter *c); 241int nfs_iocounter_wait(struct nfs_lock_context *l_ctx);
242 242
243extern const struct nfs_pageio_ops nfs_pgio_rw_ops; 243extern const struct nfs_pageio_ops nfs_pgio_rw_ops;
244struct nfs_pgio_header *nfs_pgio_header_alloc(const struct nfs_rw_ops *); 244struct nfs_pgio_header *nfs_pgio_header_alloc(const struct nfs_rw_ops *);
@@ -252,12 +252,6 @@ void nfs_free_request(struct nfs_page *req);
252struct nfs_pgio_mirror * 252struct nfs_pgio_mirror *
253nfs_pgio_current_mirror(struct nfs_pageio_descriptor *desc); 253nfs_pgio_current_mirror(struct nfs_pageio_descriptor *desc);
254 254
255static inline void nfs_iocounter_init(struct nfs_io_counter *c)
256{
257 c->flags = 0;
258 atomic_set(&c->io_count, 0);
259}
260
261static inline bool nfs_pgio_has_mirroring(struct nfs_pageio_descriptor *desc) 255static inline bool nfs_pgio_has_mirroring(struct nfs_pageio_descriptor *desc)
262{ 256{
263 WARN_ON_ONCE(desc->pg_mirror_count < 1); 257 WARN_ON_ONCE(desc->pg_mirror_count < 1);
@@ -386,6 +380,7 @@ extern void nfs_clear_inode(struct inode *);
386extern void nfs_evict_inode(struct inode *); 380extern void nfs_evict_inode(struct inode *);
387void nfs_zap_acl_cache(struct inode *inode); 381void nfs_zap_acl_cache(struct inode *inode);
388extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode); 382extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode);
383extern int nfs_wait_atomic_killable(atomic_t *p);
389 384
390/* super.c */ 385/* super.c */
391extern const struct super_operations nfs_sops; 386extern const struct super_operations nfs_sops;
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index eeddbf0bf4c4..cb7e73ba059c 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -101,53 +101,18 @@ nfs_page_free(struct nfs_page *p)
101 kmem_cache_free(nfs_page_cachep, p); 101 kmem_cache_free(nfs_page_cachep, p);
102} 102}
103 103
104static void
105nfs_iocounter_inc(struct nfs_io_counter *c)
106{
107 atomic_inc(&c->io_count);
108}
109
110static void
111nfs_iocounter_dec(struct nfs_io_counter *c)
112{
113 if (atomic_dec_and_test(&c->io_count)) {
114 clear_bit(NFS_IO_INPROGRESS, &c->flags);
115 smp_mb__after_atomic();
116 wake_up_bit(&c->flags, NFS_IO_INPROGRESS);
117 }
118}
119
120static int
121__nfs_iocounter_wait(struct nfs_io_counter *c)
122{
123 wait_queue_head_t *wq = bit_waitqueue(&c->flags, NFS_IO_INPROGRESS);
124 DEFINE_WAIT_BIT(q, &c->flags, NFS_IO_INPROGRESS);
125 int ret = 0;
126
127 do {
128 prepare_to_wait(wq, &q.wait, TASK_KILLABLE);
129 set_bit(NFS_IO_INPROGRESS, &c->flags);
130 if (atomic_read(&c->io_count) == 0)
131 break;
132 ret = nfs_wait_bit_killable(&q.key, TASK_KILLABLE);
133 } while (atomic_read(&c->io_count) != 0 && !ret);
134 finish_wait(wq, &q.wait);
135 return ret;
136}
137
138/** 104/**
139 * nfs_iocounter_wait - wait for i/o to complete 105 * nfs_iocounter_wait - wait for i/o to complete
140 * @c: nfs_io_counter to use 106 * @l_ctx: nfs_lock_context with io_counter to use
141 * 107 *
142 * returns -ERESTARTSYS if interrupted by a fatal signal. 108 * returns -ERESTARTSYS if interrupted by a fatal signal.
143 * Otherwise returns 0 once the io_count hits 0. 109 * Otherwise returns 0 once the io_count hits 0.
144 */ 110 */
145int 111int
146nfs_iocounter_wait(struct nfs_io_counter *c) 112nfs_iocounter_wait(struct nfs_lock_context *l_ctx)
147{ 113{
148 if (atomic_read(&c->io_count) == 0) 114 return wait_on_atomic_t(&l_ctx->io_count, nfs_wait_atomic_killable,
149 return 0; 115 TASK_KILLABLE);
150 return __nfs_iocounter_wait(c);
151} 116}
152 117
153/* 118/*
@@ -370,7 +335,7 @@ nfs_create_request(struct nfs_open_context *ctx, struct page *page,
370 return ERR_CAST(l_ctx); 335 return ERR_CAST(l_ctx);
371 } 336 }
372 req->wb_lock_context = l_ctx; 337 req->wb_lock_context = l_ctx;
373 nfs_iocounter_inc(&l_ctx->io_count); 338 atomic_inc(&l_ctx->io_count);
374 339
375 /* Initialize the request struct. Initially, we assume a 340 /* Initialize the request struct. Initially, we assume a
376 * long write-back delay. This will be adjusted in 341 * long write-back delay. This will be adjusted in
@@ -431,7 +396,8 @@ static void nfs_clear_request(struct nfs_page *req)
431 req->wb_page = NULL; 396 req->wb_page = NULL;
432 } 397 }
433 if (l_ctx != NULL) { 398 if (l_ctx != NULL) {
434 nfs_iocounter_dec(&l_ctx->io_count); 399 if (atomic_dec_and_test(&l_ctx->io_count))
400 wake_up_atomic_t(&l_ctx->io_count);
435 nfs_put_lock_context(l_ctx); 401 nfs_put_lock_context(l_ctx);
436 req->wb_lock_context = NULL; 402 req->wb_lock_context = NULL;
437 } 403 }
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 94828b3f8c95..8ba4f717b413 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1565,14 +1565,6 @@ static void nfs_writeback_result(struct rpc_task *task,
1565 } 1565 }
1566} 1566}
1567 1567
1568static int nfs_wait_atomic_killable(atomic_t *key)
1569{
1570 if (fatal_signal_pending(current))
1571 return -ERESTARTSYS;
1572 freezable_schedule_unsafe();
1573 return 0;
1574}
1575
1576static int wait_on_commit(struct nfs_mds_commit_info *cinfo) 1568static int wait_on_commit(struct nfs_mds_commit_info *cinfo)
1577{ 1569{
1578 return wait_on_atomic_t(&cinfo->rpcs_out, 1570 return wait_on_atomic_t(&cinfo->rpcs_out,
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 9eee972863a7..196aaceafda7 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -60,18 +60,12 @@ struct nfs_lockowner {
60 pid_t l_pid; 60 pid_t l_pid;
61}; 61};
62 62
63#define NFS_IO_INPROGRESS 0
64struct nfs_io_counter {
65 unsigned long flags;
66 atomic_t io_count;
67};
68
69struct nfs_lock_context { 63struct nfs_lock_context {
70 atomic_t count; 64 atomic_t count;
71 struct list_head list; 65 struct list_head list;
72 struct nfs_open_context *open_context; 66 struct nfs_open_context *open_context;
73 struct nfs_lockowner lockowner; 67 struct nfs_lockowner lockowner;
74 struct nfs_io_counter io_count; 68 atomic_t io_count;
75}; 69};
76 70
77struct nfs4_state; 71struct nfs4_state;