Commit 210c7c17 authored by Benjamin Coddington's avatar Benjamin Coddington Committed by Trond Myklebust

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: default avatarBenjamin Coddington <bcodding@redhat.com>
[Trond: Fix up conflict with existing function nfs_wait_atomic_killable()]
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent 942e3d72
...@@ -756,7 +756,7 @@ do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) ...@@ -756,7 +756,7 @@ do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
l_ctx = nfs_get_lock_context(nfs_file_open_context(filp)); l_ctx = nfs_get_lock_context(nfs_file_open_context(filp));
if (!IS_ERR(l_ctx)) { if (!IS_ERR(l_ctx)) {
status = nfs_iocounter_wait(&l_ctx->io_count); status = nfs_iocounter_wait(l_ctx);
nfs_put_lock_context(l_ctx); nfs_put_lock_context(l_ctx);
if (status < 0) if (status < 0)
return status; return status;
......
...@@ -71,19 +71,25 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr) ...@@ -71,19 +71,25 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
return nfs_fileid_to_ino_t(fattr->fileid); return nfs_fileid_to_ino_t(fattr->fileid);
} }
/** static int nfs_wait_killable(int mode)
* nfs_wait_bit_killable - helper for functions that are sleeping on bit locks
* @word: long word containing the bit lock
*/
int nfs_wait_bit_killable(struct wait_bit_key *key, int mode)
{ {
freezable_schedule_unsafe(); freezable_schedule_unsafe();
if (signal_pending_state(mode, current)) if (signal_pending_state(mode, current))
return -ERESTARTSYS; return -ERESTARTSYS;
return 0; return 0;
} }
int nfs_wait_bit_killable(struct wait_bit_key *key, int mode)
{
return nfs_wait_killable(mode);
}
EXPORT_SYMBOL_GPL(nfs_wait_bit_killable); EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
int nfs_wait_atomic_killable(atomic_t *p)
{
return nfs_wait_killable(TASK_KILLABLE);
}
/** /**
* nfs_compat_user_ino64 - returns the user-visible inode number * nfs_compat_user_ino64 - returns the user-visible inode number
* @fileid: 64-bit fileid * @fileid: 64-bit fileid
...@@ -699,7 +705,7 @@ static void nfs_init_lock_context(struct nfs_lock_context *l_ctx) ...@@ -699,7 +705,7 @@ static void nfs_init_lock_context(struct nfs_lock_context *l_ctx)
l_ctx->lockowner.l_owner = current->files; l_ctx->lockowner.l_owner = current->files;
l_ctx->lockowner.l_pid = current->tgid; l_ctx->lockowner.l_pid = current->tgid;
INIT_LIST_HEAD(&l_ctx->list); INIT_LIST_HEAD(&l_ctx->list);
nfs_iocounter_init(&l_ctx->io_count); atomic_set(&l_ctx->io_count, 0);
} }
static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context *ctx) static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context *ctx)
......
...@@ -238,7 +238,7 @@ extern void nfs_pgheader_init(struct nfs_pageio_descriptor *desc, ...@@ -238,7 +238,7 @@ extern void nfs_pgheader_init(struct nfs_pageio_descriptor *desc,
struct nfs_pgio_header *hdr, struct nfs_pgio_header *hdr,
void (*release)(struct nfs_pgio_header *hdr)); void (*release)(struct nfs_pgio_header *hdr));
void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos); void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos);
int nfs_iocounter_wait(struct nfs_io_counter *c); int nfs_iocounter_wait(struct nfs_lock_context *l_ctx);
extern const struct nfs_pageio_ops nfs_pgio_rw_ops; extern const struct nfs_pageio_ops nfs_pgio_rw_ops;
struct nfs_pgio_header *nfs_pgio_header_alloc(const struct nfs_rw_ops *); struct nfs_pgio_header *nfs_pgio_header_alloc(const struct nfs_rw_ops *);
...@@ -252,12 +252,6 @@ void nfs_free_request(struct nfs_page *req); ...@@ -252,12 +252,6 @@ void nfs_free_request(struct nfs_page *req);
struct nfs_pgio_mirror * struct nfs_pgio_mirror *
nfs_pgio_current_mirror(struct nfs_pageio_descriptor *desc); nfs_pgio_current_mirror(struct nfs_pageio_descriptor *desc);
static inline void nfs_iocounter_init(struct nfs_io_counter *c)
{
c->flags = 0;
atomic_set(&c->io_count, 0);
}
static inline bool nfs_pgio_has_mirroring(struct nfs_pageio_descriptor *desc) static inline bool nfs_pgio_has_mirroring(struct nfs_pageio_descriptor *desc)
{ {
WARN_ON_ONCE(desc->pg_mirror_count < 1); WARN_ON_ONCE(desc->pg_mirror_count < 1);
...@@ -386,6 +380,7 @@ extern void nfs_clear_inode(struct inode *); ...@@ -386,6 +380,7 @@ extern void nfs_clear_inode(struct inode *);
extern void nfs_evict_inode(struct inode *); extern void nfs_evict_inode(struct inode *);
void nfs_zap_acl_cache(struct inode *inode); void nfs_zap_acl_cache(struct inode *inode);
extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode); extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode);
extern int nfs_wait_atomic_killable(atomic_t *p);
/* super.c */ /* super.c */
extern const struct super_operations nfs_sops; extern const struct super_operations nfs_sops;
......
...@@ -101,53 +101,18 @@ nfs_page_free(struct nfs_page *p) ...@@ -101,53 +101,18 @@ nfs_page_free(struct nfs_page *p)
kmem_cache_free(nfs_page_cachep, p); kmem_cache_free(nfs_page_cachep, p);
} }
static void
nfs_iocounter_inc(struct nfs_io_counter *c)
{
atomic_inc(&c->io_count);
}
static void
nfs_iocounter_dec(struct nfs_io_counter *c)
{
if (atomic_dec_and_test(&c->io_count)) {
clear_bit(NFS_IO_INPROGRESS, &c->flags);
smp_mb__after_atomic();
wake_up_bit(&c->flags, NFS_IO_INPROGRESS);
}
}
static int
__nfs_iocounter_wait(struct nfs_io_counter *c)
{
wait_queue_head_t *wq = bit_waitqueue(&c->flags, NFS_IO_INPROGRESS);
DEFINE_WAIT_BIT(q, &c->flags, NFS_IO_INPROGRESS);
int ret = 0;
do {
prepare_to_wait(wq, &q.wait, TASK_KILLABLE);
set_bit(NFS_IO_INPROGRESS, &c->flags);
if (atomic_read(&c->io_count) == 0)
break;
ret = nfs_wait_bit_killable(&q.key, TASK_KILLABLE);
} while (atomic_read(&c->io_count) != 0 && !ret);
finish_wait(wq, &q.wait);
return ret;
}
/** /**
* nfs_iocounter_wait - wait for i/o to complete * nfs_iocounter_wait - wait for i/o to complete
* @c: nfs_io_counter to use * @l_ctx: nfs_lock_context with io_counter to use
* *
* returns -ERESTARTSYS if interrupted by a fatal signal. * returns -ERESTARTSYS if interrupted by a fatal signal.
* Otherwise returns 0 once the io_count hits 0. * Otherwise returns 0 once the io_count hits 0.
*/ */
int int
nfs_iocounter_wait(struct nfs_io_counter *c) nfs_iocounter_wait(struct nfs_lock_context *l_ctx)
{ {
if (atomic_read(&c->io_count) == 0) return wait_on_atomic_t(&l_ctx->io_count, nfs_wait_atomic_killable,
return 0; TASK_KILLABLE);
return __nfs_iocounter_wait(c);
} }
/* /*
...@@ -370,7 +335,7 @@ nfs_create_request(struct nfs_open_context *ctx, struct page *page, ...@@ -370,7 +335,7 @@ nfs_create_request(struct nfs_open_context *ctx, struct page *page,
return ERR_CAST(l_ctx); return ERR_CAST(l_ctx);
} }
req->wb_lock_context = l_ctx; req->wb_lock_context = l_ctx;
nfs_iocounter_inc(&l_ctx->io_count); atomic_inc(&l_ctx->io_count);
/* Initialize the request struct. Initially, we assume a /* Initialize the request struct. Initially, we assume a
* long write-back delay. This will be adjusted in * long write-back delay. This will be adjusted in
...@@ -431,7 +396,8 @@ static void nfs_clear_request(struct nfs_page *req) ...@@ -431,7 +396,8 @@ static void nfs_clear_request(struct nfs_page *req)
req->wb_page = NULL; req->wb_page = NULL;
} }
if (l_ctx != NULL) { if (l_ctx != NULL) {
nfs_iocounter_dec(&l_ctx->io_count); if (atomic_dec_and_test(&l_ctx->io_count))
wake_up_atomic_t(&l_ctx->io_count);
nfs_put_lock_context(l_ctx); nfs_put_lock_context(l_ctx);
req->wb_lock_context = NULL; req->wb_lock_context = NULL;
} }
......
...@@ -1565,14 +1565,6 @@ static void nfs_writeback_result(struct rpc_task *task, ...@@ -1565,14 +1565,6 @@ static void nfs_writeback_result(struct rpc_task *task,
} }
} }
static int nfs_wait_atomic_killable(atomic_t *key)
{
if (fatal_signal_pending(current))
return -ERESTARTSYS;
freezable_schedule_unsafe();
return 0;
}
static int wait_on_commit(struct nfs_mds_commit_info *cinfo) static int wait_on_commit(struct nfs_mds_commit_info *cinfo)
{ {
return wait_on_atomic_t(&cinfo->rpcs_out, return wait_on_atomic_t(&cinfo->rpcs_out,
......
...@@ -60,18 +60,12 @@ struct nfs_lockowner { ...@@ -60,18 +60,12 @@ struct nfs_lockowner {
pid_t l_pid; pid_t l_pid;
}; };
#define NFS_IO_INPROGRESS 0
struct nfs_io_counter {
unsigned long flags;
atomic_t io_count;
};
struct nfs_lock_context { struct nfs_lock_context {
atomic_t count; atomic_t count;
struct list_head list; struct list_head list;
struct nfs_open_context *open_context; struct nfs_open_context *open_context;
struct nfs_lockowner lockowner; struct nfs_lockowner lockowner;
struct nfs_io_counter io_count; atomic_t io_count;
}; };
struct nfs4_state; struct nfs4_state;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment