From acee478afc6ff7e1b8852d9a4dca1ff36021414d Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 22 Jan 2008 17:13:07 -0500 Subject: NFS: Clean up the write request locking. Ensure that we set/clear NFS_PAGE_TAG_LOCKED when the nfs_page is hashed. Signed-off-by: Trond Myklebust --- include/linux/nfs_page.h | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'include/linux') diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index 30dbcc185e69..a1676e19e491 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h @@ -83,6 +83,7 @@ extern void nfs_pageio_complete(struct nfs_pageio_descriptor *desc); extern void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *, pgoff_t); extern int nfs_wait_on_request(struct nfs_page *); extern void nfs_unlock_request(struct nfs_page *req); +extern int nfs_set_page_tag_locked(struct nfs_page *req); extern void nfs_clear_page_tag_locked(struct nfs_page *req); @@ -95,18 +96,6 @@ nfs_lock_request_dontget(struct nfs_page *req) return !test_and_set_bit(PG_BUSY, &req->wb_flags); } -/* - * Lock the page of an asynchronous request and take a reference - */ -static inline int -nfs_lock_request(struct nfs_page *req) -{ - if (test_and_set_bit(PG_BUSY, &req->wb_flags)) - return 0; - kref_get(&req->wb_kref); - return 1; -} - /** * nfs_list_add_request - Insert a request into a list * @req: request -- cgit v1.2.3 From ef818a28fac9bd214e676986d8301db0582b92a9 Mon Sep 17 00:00:00 2001 From: Steve Dickson Date: Thu, 8 Nov 2007 04:05:04 -0500 Subject: NFS: Stop sillyname renames and unmounts from racing Added an active/deactive mechanism to the nfs_server structure allowing async operations to hold off umount until the operations are done. Signed-off-by: Steve Dickson Signed-off-by: Trond Myklebust --- fs/nfs/client.c | 3 +++ fs/nfs/internal.h | 2 ++ fs/nfs/super.c | 24 ++++++++++++++++++++++++ fs/nfs/unlink.c | 4 ++++ include/linux/nfs_fs_sb.h | 6 ++++++ 5 files changed, 39 insertions(+) (limited to 'include/linux') diff --git a/fs/nfs/client.c b/fs/nfs/client.c index a6f625497612..c3740f5ab978 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -729,6 +729,9 @@ static struct nfs_server *nfs_alloc_server(void) INIT_LIST_HEAD(&server->client_link); INIT_LIST_HEAD(&server->master_link); + init_waitqueue_head(&server->active_wq); + atomic_set(&server->active, 0); + server->io_stats = nfs_alloc_iostats(); if (!server->io_stats) { kfree(server); diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index f3acf48412be..75793794aefe 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -160,6 +160,8 @@ extern struct rpc_stat nfs_rpcstat; extern int __init register_nfs_fs(void); extern void __exit unregister_nfs_fs(void); +extern void nfs_sb_active(struct nfs_server *server); +extern void nfs_sb_deactive(struct nfs_server *server); /* namespace.c */ extern char *nfs_path(const char *base, diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 0b0c72a072ff..fda1635dd133 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -202,6 +202,7 @@ static int nfs_get_sb(struct file_system_type *, int, const char *, void *, stru static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); static void nfs_kill_super(struct super_block *); +static void nfs_put_super(struct super_block *); static struct file_system_type nfs_fs_type = { .owner = THIS_MODULE, @@ -223,6 +224,7 @@ static const struct super_operations nfs_sops = { .alloc_inode = nfs_alloc_inode, .destroy_inode = nfs_destroy_inode, .write_inode = nfs_write_inode, + .put_super = nfs_put_super, .statfs = nfs_statfs, .clear_inode = nfs_clear_inode, .umount_begin = nfs_umount_begin, @@ -325,6 +327,28 @@ void __exit unregister_nfs_fs(void) unregister_filesystem(&nfs_fs_type); } +void nfs_sb_active(struct nfs_server *server) +{ + atomic_inc(&server->active); +} + +void nfs_sb_deactive(struct nfs_server *server) +{ + if (atomic_dec_and_test(&server->active)) + wake_up(&server->active_wq); +} + +static void nfs_put_super(struct super_block *sb) +{ + struct nfs_server *server = NFS_SB(sb); + /* + * Make sure there are no outstanding ops to this server. + * If so, wait for them to finish before allowing the + * unmount to continue. + */ + wait_event(server->active_wq, atomic_read(&server->active) == 0); +} + /* * Deliver file system statistics to userspace */ diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 431981d0265f..8e5428e0b86f 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -14,6 +14,8 @@ #include #include +#include "internal.h" + struct nfs_unlinkdata { struct hlist_node list; struct nfs_removeargs args; @@ -113,6 +115,7 @@ static void nfs_async_unlink_release(void *calldata) struct nfs_unlinkdata *data = calldata; nfs_dec_sillycount(data->dir); + nfs_sb_deactive(NFS_SERVER(data->dir)); nfs_free_unlinkdata(data); } @@ -153,6 +156,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n nfs_dec_sillycount(dir); return 0; } + nfs_sb_active(NFS_SERVER(dir)); data->args.fh = NFS_FH(dir); nfs_fattr_init(&data->res.dir_attr); diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 0cac49bc0955..9f949b587684 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -3,6 +3,9 @@ #include #include +#include + +#include struct nfs_iostats; @@ -110,6 +113,9 @@ struct nfs_server { filesystem */ #endif void (*destroy)(struct nfs_server *); + + atomic_t active; /* Keep trace of any activity to this server */ + wait_queue_head_t active_wq; /* Wait for any activity to stop */ }; /* Server capabilities */ -- cgit v1.2.3 From 66af1e558538137080615e7ad6d1f2f80862de01 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 6 Nov 2007 10:18:36 -0500 Subject: SUNRPC: Fix a race in xs_tcp_state_change() When scheduling the autoclose RPC call, we want to ensure that we don't race against the test_bit() call in xprt_clear_locked(). Signed-off-by: Trond Myklebust --- include/linux/sunrpc/xprt.h | 1 + net/sunrpc/xprt.c | 20 ++++++++++++++++++++ net/sunrpc/xprtsock.c | 5 +---- 3 files changed, 22 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index 30b17b3bc1a9..6f524a9e7fd0 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -246,6 +246,7 @@ struct rpc_rqst * xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid); void xprt_complete_rqst(struct rpc_task *task, int copied); void xprt_release_rqst_cong(struct rpc_task *task); void xprt_disconnect(struct rpc_xprt *xprt); +void xprt_force_disconnect(struct rpc_xprt *xprt); /* * Reserved bit positions in xprt->state diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index fb92f51405c5..a3af02168af1 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -570,6 +570,7 @@ static void xprt_autoclose(struct work_struct *work) xprt_disconnect(xprt); xprt->ops->close(xprt); + clear_bit(XPRT_CLOSE_WAIT, &xprt->state); xprt_release_write(xprt, NULL); } @@ -588,6 +589,25 @@ void xprt_disconnect(struct rpc_xprt *xprt) } EXPORT_SYMBOL_GPL(xprt_disconnect); +/** + * xprt_force_disconnect - force a transport to disconnect + * @xprt: transport to disconnect + * + */ +void xprt_force_disconnect(struct rpc_xprt *xprt) +{ + /* Don't race with the test_bit() in xprt_clear_locked() */ + spin_lock_bh(&xprt->transport_lock); + set_bit(XPRT_CLOSE_WAIT, &xprt->state); + /* Try to schedule an autoclose RPC call */ + if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) + queue_work(rpciod_workqueue, &xprt->task_cleanup); + else if (xprt->snd_task != NULL) + rpc_wake_up_task(xprt->snd_task); + spin_unlock_bh(&xprt->transport_lock); +} +EXPORT_SYMBOL_GPL(xprt_force_disconnect); + static void xprt_init_autodisconnect(unsigned long data) { diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 6fa52f44de0f..abb40c140738 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1122,10 +1122,7 @@ static void xs_tcp_state_change(struct sock *sk) case TCP_SYN_RECV: break; case TCP_CLOSE_WAIT: - /* Try to schedule an autoclose RPC calls */ - set_bit(XPRT_CLOSE_WAIT, &xprt->state); - if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) - queue_work(rpciod_workqueue, &xprt->task_cleanup); + xprt_force_disconnect(xprt); default: xprt_disconnect(xprt); } -- cgit v1.2.3 From 3b948ae5be5e22532584113e2e02029519bbad8f Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 5 Nov 2007 17:42:39 -0500 Subject: SUNRPC: Allow the client to detect if the TCP connection is closed Add an xprt->state bit to enable the TCP ->state_change() method to signal whether or not the TCP connection is in the process of closing down. This will to be used by the reconnection logic in a separate patch. Signed-off-by: Trond Myklebust --- include/linux/sunrpc/xprt.h | 1 + net/sunrpc/xprtsock.c | 24 +++++++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index 6f524a9e7fd0..afb9e6ad7fe0 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -257,6 +257,7 @@ void xprt_force_disconnect(struct rpc_xprt *xprt); #define XPRT_CLOSE_WAIT (3) #define XPRT_BOUND (4) #define XPRT_BINDING (5) +#define XPRT_CLOSING (6) static inline void xprt_set_connected(struct rpc_xprt *xprt) { diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index b5544514ee57..721c5419765e 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -758,7 +758,9 @@ static void xs_close(struct rpc_xprt *xprt) sock_release(sock); clear_close_wait: smp_mb__before_clear_bit(); + clear_bit(XPRT_CONNECTED, &xprt->state); clear_bit(XPRT_CLOSE_WAIT, &xprt->state); + clear_bit(XPRT_CLOSING, &xprt->state); smp_mb__after_clear_bit(); } @@ -1118,12 +1120,28 @@ static void xs_tcp_state_change(struct sock *sk) } spin_unlock_bh(&xprt->transport_lock); break; - case TCP_SYN_SENT: - case TCP_SYN_RECV: + case TCP_FIN_WAIT1: + /* The client initiated a shutdown of the socket */ + set_bit(XPRT_CLOSING, &xprt->state); + smp_mb__before_clear_bit(); + clear_bit(XPRT_CONNECTED, &xprt->state); + smp_mb__after_clear_bit(); break; case TCP_CLOSE_WAIT: + /* The server initiated a shutdown of the socket */ + set_bit(XPRT_CLOSING, &xprt->state); xprt_force_disconnect(xprt); - default: + break; + case TCP_LAST_ACK: + smp_mb__before_clear_bit(); + clear_bit(XPRT_CONNECTED, &xprt->state); + smp_mb__after_clear_bit(); + break; + case TCP_CLOSE: + smp_mb__before_clear_bit(); + clear_bit(XPRT_CLOSING, &xprt->state); + smp_mb__after_clear_bit(); + /* Mark transport as closed and wake up all pending tasks */ xprt_disconnect(xprt); } out: -- cgit v1.2.3 From 62da3b24880bccd4ffc32cf8d9a7e23fab475bdd Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 6 Nov 2007 18:44:20 -0500 Subject: SUNRPC: Rename xprt_disconnect() xprt_disconnect() should really only be called when the transport shutdown is completed, and it is time to wake up any pending tasks. Rename it to xprt_disconnect_done() in order to reflect the semantical change. Signed-off-by: Trond Myklebust --- include/linux/sunrpc/xprt.h | 2 +- net/sunrpc/xprt.c | 6 +++--- net/sunrpc/xprtrdma/transport.c | 4 ++-- net/sunrpc/xprtsock.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index afb9e6ad7fe0..2554cd2b016f 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -245,7 +245,7 @@ void xprt_adjust_cwnd(struct rpc_task *task, int result); struct rpc_rqst * xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid); void xprt_complete_rqst(struct rpc_task *task, int copied); void xprt_release_rqst_cong(struct rpc_task *task); -void xprt_disconnect(struct rpc_xprt *xprt); +void xprt_disconnect_done(struct rpc_xprt *xprt); void xprt_force_disconnect(struct rpc_xprt *xprt); /* diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 80742995e02e..592c2ee63e0f 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -574,11 +574,11 @@ static void xprt_autoclose(struct work_struct *work) } /** - * xprt_disconnect - mark a transport as disconnected + * xprt_disconnect_done - mark a transport as disconnected * @xprt: transport to flag for disconnect * */ -void xprt_disconnect(struct rpc_xprt *xprt) +void xprt_disconnect_done(struct rpc_xprt *xprt) { dprintk("RPC: disconnected transport %p\n", xprt); spin_lock_bh(&xprt->transport_lock); @@ -586,7 +586,7 @@ void xprt_disconnect(struct rpc_xprt *xprt) xprt_wake_pending_tasks(xprt, -ENOTCONN); spin_unlock_bh(&xprt->transport_lock); } -EXPORT_SYMBOL_GPL(xprt_disconnect); +EXPORT_SYMBOL_GPL(xprt_disconnect_done); /** * xprt_force_disconnect - force a transport to disconnect diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 6f2112dd9f78..73033d824eed 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -449,7 +449,7 @@ xprt_rdma_close(struct rpc_xprt *xprt) struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); dprintk("RPC: %s: closing\n", __func__); - xprt_disconnect(xprt); + xprt_disconnect_done(xprt); (void) rpcrdma_ep_disconnect(&r_xprt->rx_ep, &r_xprt->rx_ia); } @@ -682,7 +682,7 @@ xprt_rdma_send_request(struct rpc_task *task) } if (rpcrdma_ep_post(&r_xprt->rx_ia, &r_xprt->rx_ep, req)) { - xprt_disconnect(xprt); + xprt_disconnect_done(xprt); return -ENOTCONN; /* implies disconnect */ } diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 8c9af3d92c67..741ab8ad1f3a 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -777,7 +777,7 @@ clear_close_wait: clear_bit(XPRT_CLOSE_WAIT, &xprt->state); clear_bit(XPRT_CLOSING, &xprt->state); smp_mb__after_clear_bit(); - xprt_disconnect(xprt); + xprt_disconnect_done(xprt); } /** @@ -1159,7 +1159,7 @@ static void xs_tcp_state_change(struct sock *sk) clear_bit(XPRT_CLOSING, &xprt->state); smp_mb__after_clear_bit(); /* Mark transport as closed and wake up all pending tasks */ - xprt_disconnect(xprt); + xprt_disconnect_done(xprt); } out: read_unlock(&sk->sk_callback_lock); -- cgit v1.2.3 From 84115e1cd4a3614c4e566d4cce31381dce3dbef9 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 14 Jul 2007 15:39:59 -0400 Subject: SUNRPC: Cleanup of rpc_task initialisation Signed-off-by: Trond Myklebust --- fs/nfs/direct.c | 36 ++++++++++++++++++++++++------- fs/nfs/read.c | 15 ++++++++----- fs/nfs/write.c | 30 ++++++++++++++++---------- include/linux/sunrpc/clnt.h | 2 +- include/linux/sunrpc/sched.h | 14 +++++++----- net/sunrpc/clnt.c | 51 ++++++++++++++++++++++++++++++++------------ net/sunrpc/sched.c | 27 +++++++++++------------ 7 files changed, 117 insertions(+), 58 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 3c9d16b4f80c..f9f5fc13dc7d 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -272,6 +272,11 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, unsigned long user_addr = (unsigned long)iov->iov_base; size_t count = iov->iov_len; size_t rsize = NFS_SERVER(inode)->rsize; + struct rpc_task_setup task_setup_data = { + .rpc_client = NFS_CLIENT(inode), + .callback_ops = &nfs_read_direct_ops, + .flags = RPC_TASK_ASYNC, + }; unsigned int pgbase; int result; ssize_t started = 0; @@ -322,8 +327,8 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, data->res.eof = 0; data->res.count = bytes; - rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, - &nfs_read_direct_ops, data); + task_setup_data.callback_data = data; + rpc_init_task(&data->task, &task_setup_data); NFS_PROTO(inode)->read_setup(data); data->task.tk_cookie = (unsigned long) inode; @@ -431,6 +436,11 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) struct inode *inode = dreq->inode; struct list_head *p; struct nfs_write_data *data; + struct rpc_task_setup task_setup_data = { + .rpc_client = NFS_CLIENT(inode), + .callback_ops = &nfs_write_direct_ops, + .flags = RPC_TASK_ASYNC, + }; dreq->count = 0; get_dreq(dreq); @@ -451,8 +461,8 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) * Reuse data->task; data->args should not have changed * since the original request was sent. */ - rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, - &nfs_write_direct_ops, data); + task_setup_data.callback_data = data; + rpc_init_task(&data->task, &task_setup_data); NFS_PROTO(inode)->write_setup(data, FLUSH_STABLE); data->task.tk_priority = RPC_PRIORITY_NORMAL; @@ -504,6 +514,12 @@ static const struct rpc_call_ops nfs_commit_direct_ops = { static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) { struct nfs_write_data *data = dreq->commit_data; + struct rpc_task_setup task_setup_data = { + .rpc_client = NFS_CLIENT(dreq->inode), + .callback_ops = &nfs_commit_direct_ops, + .callback_data = data, + .flags = RPC_TASK_ASYNC, + }; data->inode = dreq->inode; data->cred = dreq->ctx->cred; @@ -515,8 +531,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) data->res.fattr = &data->fattr; data->res.verf = &data->verf; - rpc_init_task(&data->task, NFS_CLIENT(dreq->inode), RPC_TASK_ASYNC, - &nfs_commit_direct_ops, data); + rpc_init_task(&data->task, &task_setup_data); NFS_PROTO(data->inode)->commit_setup(data, 0); data->task.tk_priority = RPC_PRIORITY_NORMAL; @@ -641,6 +656,11 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, struct inode *inode = ctx->path.dentry->d_inode; unsigned long user_addr = (unsigned long)iov->iov_base; size_t count = iov->iov_len; + struct rpc_task_setup task_setup_data = { + .rpc_client = NFS_CLIENT(inode), + .callback_ops = &nfs_write_direct_ops, + .flags = RPC_TASK_ASYNC, + }; size_t wsize = NFS_SERVER(inode)->wsize; unsigned int pgbase; int result; @@ -694,8 +714,8 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, data->res.count = bytes; data->res.verf = &data->verf; - rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, - &nfs_write_direct_ops, data); + task_setup_data.callback_data = data; + rpc_init_task(&data->task, &task_setup_data); NFS_PROTO(inode)->write_setup(data, sync); data->task.tk_priority = RPC_PRIORITY_NORMAL; diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 4587a86adaac..c7f0d5ebd451 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -160,11 +160,17 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, const struct rpc_call_ops *call_ops, unsigned int count, unsigned int offset) { - struct inode *inode; - int flags; + struct inode *inode = req->wb_context->path.dentry->d_inode; + int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0; + struct rpc_task_setup task_setup_data = { + .rpc_client = NFS_CLIENT(inode), + .callback_ops = call_ops, + .callback_data = data, + .flags = RPC_TASK_ASYNC | swap_flags, + }; data->req = req; - data->inode = inode = req->wb_context->path.dentry->d_inode; + data->inode = inode; data->cred = req->wb_context->cred; data->args.fh = NFS_FH(inode); @@ -180,8 +186,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, nfs_fattr_init(&data->fattr); /* Set up the initial task struct. */ - flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); - rpc_init_task(&data->task, NFS_CLIENT(inode), flags, call_ops, data); + rpc_init_task(&data->task, &task_setup_data); NFS_PROTO(inode)->read_setup(data); data->task.tk_cookie = (unsigned long)inode; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 092e79c6d962..c4376606f106 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -773,8 +773,14 @@ static void nfs_write_rpcsetup(struct nfs_page *req, unsigned int count, unsigned int offset, int how) { - struct inode *inode; - int flags; + struct inode *inode = req->wb_context->path.dentry->d_inode; + int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; + struct rpc_task_setup task_setup_data = { + .rpc_client = NFS_CLIENT(inode), + .callback_ops = call_ops, + .callback_data = data, + .flags = flags, + }; /* Set up the RPC argument and reply structs * NB: take care not to mess about with data->commit et al. */ @@ -796,8 +802,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req, nfs_fattr_init(&data->fattr); /* Set up the initial task struct. */ - flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; - rpc_init_task(&data->task, NFS_CLIENT(inode), flags, call_ops, data); + rpc_init_task(&data->task, &task_setup_data); NFS_PROTO(inode)->write_setup(data, how); data->task.tk_priority = flush_task_priority(how); @@ -1144,16 +1149,20 @@ static void nfs_commit_rpcsetup(struct list_head *head, struct nfs_write_data *data, int how) { - struct nfs_page *first; - struct inode *inode; - int flags; + struct nfs_page *first = nfs_list_entry(head->next); + struct inode *inode = first->wb_context->path.dentry->d_inode; + int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; + struct rpc_task_setup task_setup_data = { + .rpc_client = NFS_CLIENT(inode), + .callback_ops = &nfs_commit_ops, + .callback_data = data, + .flags = flags, + }; /* Set up the RPC argument and reply structs * NB: take care not to mess about with data->commit et al. */ list_splice_init(head, &data->pages); - first = nfs_list_entry(data->pages.next); - inode = first->wb_context->path.dentry->d_inode; data->inode = inode; data->cred = first->wb_context->cred; @@ -1168,8 +1177,7 @@ static void nfs_commit_rpcsetup(struct list_head *head, nfs_fattr_init(&data->fattr); /* Set up the initial task struct. */ - flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; - rpc_init_task(&data->task, NFS_CLIENT(inode), flags, &nfs_commit_ops, data); + rpc_init_task(&data->task, &task_setup_data); NFS_PROTO(inode)->commit_setup(data, how); data->task.tk_priority = flush_task_priority(how); diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index d9d5c5ad826c..ec9704181f94 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h @@ -126,7 +126,7 @@ int rpcb_register(u32, u32, int, unsigned short, int *); int rpcb_getport_sync(struct sockaddr_in *, __u32, __u32, int); void rpcb_getport_async(struct rpc_task *); -void rpc_call_setup(struct rpc_task *, struct rpc_message *, int); +void rpc_call_setup(struct rpc_task *, const struct rpc_message *, int); int rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, const struct rpc_call_ops *tk_ops, diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 8ea077db0099..9efe045fc376 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h @@ -117,6 +117,13 @@ struct rpc_call_ops { void (*rpc_release)(void *); }; +struct rpc_task_setup { + struct rpc_clnt *rpc_client; + const struct rpc_message *rpc_message; + const struct rpc_call_ops *callback_ops; + void *callback_data; + unsigned short flags; +}; /* * RPC task flags @@ -236,13 +243,10 @@ struct rpc_wait_queue { /* * Function prototypes */ -struct rpc_task *rpc_new_task(struct rpc_clnt *, int flags, - const struct rpc_call_ops *ops, void *data); +struct rpc_task *rpc_new_task(const struct rpc_task_setup *); struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *ops, void *data); -void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, - int flags, const struct rpc_call_ops *ops, - void *data); +void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *); void rpc_put_task(struct rpc_task *); void rpc_exit_task(struct rpc_task *); void rpc_release_calldata(const struct rpc_call_ops *, void *); diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 22092b91dd85..7c80abd9263f 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -524,25 +524,22 @@ void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset) EXPORT_SYMBOL_GPL(rpc_clnt_sigunmask); static -struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt, - struct rpc_message *msg, - int flags, - const struct rpc_call_ops *ops, - void *data) +struct rpc_task *rpc_do_run_task(const struct rpc_task_setup *task_setup_data) { struct rpc_task *task, *ret; sigset_t oldset; - task = rpc_new_task(clnt, flags, ops, data); + task = rpc_new_task(task_setup_data); if (task == NULL) { - rpc_release_calldata(ops, data); + rpc_release_calldata(task_setup_data->callback_ops, + task_setup_data->callback_data); return ERR_PTR(-ENOMEM); } /* Mask signals on synchronous RPC calls and RPCSEC_GSS upcalls */ rpc_task_sigmask(task, &oldset); - if (msg != NULL) { - rpc_call_setup(task, msg, 0); + if (task_setup_data->rpc_message != NULL) { + rpc_call_setup(task, task_setup_data->rpc_message, 0); if (task->tk_status != 0) { ret = ERR_PTR(task->tk_status); rpc_put_task(task); @@ -566,11 +563,17 @@ out: int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) { struct rpc_task *task; + struct rpc_task_setup task_setup_data = { + .rpc_client = clnt, + .rpc_message = msg, + .callback_ops = &rpc_default_ops, + .flags = flags, + }; int status; BUG_ON(flags & RPC_TASK_ASYNC); - task = rpc_do_run_task(clnt, msg, flags, &rpc_default_ops, NULL); + task = rpc_do_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); status = task->tk_status; @@ -592,8 +595,15 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, const struct rpc_call_ops *tk_ops, void *data) { struct rpc_task *task; + struct rpc_task_setup task_setup_data = { + .rpc_client = clnt, + .rpc_message = msg, + .callback_ops = tk_ops, + .callback_data = data, + .flags = flags|RPC_TASK_ASYNC, + }; - task = rpc_do_run_task(clnt, msg, flags|RPC_TASK_ASYNC, tk_ops, data); + task = rpc_do_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); rpc_put_task(task); @@ -612,12 +622,19 @@ struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *data) { - return rpc_do_run_task(clnt, NULL, flags, tk_ops, data); + struct rpc_task_setup task_setup_data = { + .rpc_client = clnt, + .callback_ops = tk_ops, + .callback_data = data, + .flags = flags, + }; + + return rpc_do_run_task(&task_setup_data); } EXPORT_SYMBOL_GPL(rpc_run_task); void -rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags) +rpc_call_setup(struct rpc_task *task, const struct rpc_message *msg, int flags) { task->tk_msg = *msg; task->tk_flags |= flags; @@ -1527,7 +1544,13 @@ struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int .rpc_proc = &rpcproc_null, .rpc_cred = cred, }; - return rpc_do_run_task(clnt, &msg, flags, &rpc_default_ops, NULL); + struct rpc_task_setup task_setup_data = { + .rpc_client = clnt, + .rpc_message = &msg, + .callback_ops = &rpc_default_ops, + .flags = flags, + }; + return rpc_do_run_task(&task_setup_data); } EXPORT_SYMBOL_GPL(rpc_call_null); diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index d0b4c7e11e06..10216989309c 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -815,18 +815,15 @@ EXPORT_SYMBOL_GPL(rpc_free); /* * Creation and deletion of RPC task structures */ -void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata) +void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *task_setup_data) { memset(task, 0, sizeof(*task)); setup_timer(&task->tk_timer, (void (*)(unsigned long))rpc_run_timer, (unsigned long)task); atomic_set(&task->tk_count, 1); - task->tk_client = clnt; - task->tk_flags = flags; - task->tk_ops = tk_ops; - if (tk_ops->rpc_call_prepare != NULL) - task->tk_action = rpc_prepare_task; - task->tk_calldata = calldata; + task->tk_flags = task_setup_data->flags; + task->tk_ops = task_setup_data->callback_ops; + task->tk_calldata = task_setup_data->callback_data; INIT_LIST_HEAD(&task->tk_task); /* Initialize retry counters */ @@ -839,15 +836,17 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons /* Initialize workqueue for async tasks */ task->tk_workqueue = rpciod_workqueue; - if (clnt) { - kref_get(&clnt->cl_kref); - if (clnt->cl_softrtry) + task->tk_client = task_setup_data->rpc_client; + if (task->tk_client != NULL) { + kref_get(&task->tk_client->cl_kref); + if (task->tk_client->cl_softrtry) task->tk_flags |= RPC_TASK_SOFT; - if (!clnt->cl_intr) + if (!task->tk_client->cl_intr) task->tk_flags |= RPC_TASK_NOINTR; } - BUG_ON(task->tk_ops == NULL); + if (task->tk_ops->rpc_call_prepare != NULL) + task->tk_action = rpc_prepare_task; /* starting timestamp */ task->tk_start = jiffies; @@ -873,7 +872,7 @@ static void rpc_free_task(struct rcu_head *rcu) /* * Create a new task for the specified client. */ -struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata) +struct rpc_task *rpc_new_task(const struct rpc_task_setup *setup_data) { struct rpc_task *task; @@ -881,7 +880,7 @@ struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc if (!task) goto out; - rpc_init_task(task, clnt, flags, tk_ops, calldata); + rpc_init_task(task, setup_data); dprintk("RPC: allocated task %p\n", task); task->tk_flags |= RPC_TASK_DYNAMIC; -- cgit v1.2.3 From c970aa85e71bd581726c42df843f6f129db275ac Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 14 Jul 2007 15:39:59 -0400 Subject: SUNRPC: Clean up rpc_run_task Make it use the new task initialiser structure instead of acting as a wrapper. Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 49 +++++++++++++++++++++++++++++++++++++------- fs/nfs/unlink.c | 9 +++++++- include/linux/sunrpc/sched.h | 3 +-- net/sunrpc/clnt.c | 36 ++++++++------------------------ net/sunrpc/rpcb_clnt.c | 8 +++++++- 5 files changed, 67 insertions(+), 38 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index a51a7537f3f6..ff2c5f83ce87 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -779,12 +779,18 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) { struct nfs_server *server = NFS_SERVER(data->dir->d_inode); struct rpc_task *task; + struct rpc_task_setup task_setup_data = { + .rpc_client = server->client, + .callback_ops = &nfs4_open_confirm_ops, + .callback_data = data, + .flags = RPC_TASK_ASYNC, + }; int status; kref_get(&data->kref); data->rpc_done = 0; data->rpc_status = 0; - task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data); + task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); status = nfs4_wait_for_completion_rpc_task(task); @@ -908,13 +914,19 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) struct nfs_openargs *o_arg = &data->o_arg; struct nfs_openres *o_res = &data->o_res; struct rpc_task *task; + struct rpc_task_setup task_setup_data = { + .rpc_client = server->client, + .callback_ops = &nfs4_open_ops, + .callback_data = data, + .flags = RPC_TASK_ASYNC, + }; int status; kref_get(&data->kref); data->rpc_done = 0; data->rpc_status = 0; data->cancelled = 0; - task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_ops, data); + task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); status = nfs4_wait_for_completion_rpc_task(task); @@ -1309,6 +1321,11 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) struct nfs4_closedata *calldata; struct nfs4_state_owner *sp = state->owner; struct rpc_task *task; + struct rpc_task_setup task_setup_data = { + .rpc_client = server->client, + .callback_ops = &nfs4_close_ops, + .flags = RPC_TASK_ASYNC, + }; int status = -ENOMEM; calldata = kmalloc(sizeof(*calldata), GFP_KERNEL); @@ -1328,7 +1345,8 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) calldata->path.mnt = mntget(path->mnt); calldata->path.dentry = dget(path->dentry); - task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata); + task_setup_data.callback_data = calldata; + task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); status = 0; @@ -3027,6 +3045,11 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co struct nfs4_delegreturndata *data; struct nfs_server *server = NFS_SERVER(inode); struct rpc_task *task; + struct rpc_task_setup task_setup_data = { + .rpc_client = server->client, + .callback_ops = &nfs4_delegreturn_ops, + .flags = RPC_TASK_ASYNC, + }; int status; data = kmalloc(sizeof(*data), GFP_KERNEL); @@ -3043,7 +3066,8 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co data->timestamp = jiffies; data->rpc_status = 0; - task = rpc_run_task(NFS_CLIENT(inode), RPC_TASK_ASYNC, &nfs4_delegreturn_ops, data); + task_setup_data.callback_data = data; + task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); status = nfs4_wait_for_completion_rpc_task(task); @@ -3260,6 +3284,11 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, struct nfs_seqid *seqid) { struct nfs4_unlockdata *data; + struct rpc_task_setup task_setup_data = { + .rpc_client = NFS_CLIENT(lsp->ls_state->inode), + .callback_ops = &nfs4_locku_ops, + .flags = RPC_TASK_ASYNC, + }; /* Ensure this is an unlock - when canceling a lock, the * canceled lock is passed in, and it won't be an unlock. @@ -3272,7 +3301,8 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, return ERR_PTR(-ENOMEM); } - return rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data); + task_setup_data.callback_data = data; + return rpc_run_task(&task_setup_data); } static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) @@ -3438,6 +3468,11 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f { struct nfs4_lockdata *data; struct rpc_task *task; + struct rpc_task_setup task_setup_data = { + .rpc_client = NFS_CLIENT(state->inode), + .callback_ops = &nfs4_lock_ops, + .flags = RPC_TASK_ASYNC, + }; int ret; dprintk("%s: begin!\n", __FUNCTION__); @@ -3449,8 +3484,8 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f data->arg.block = 1; if (reclaim != 0) data->arg.reclaim = 1; - task = rpc_run_task(NFS_CLIENT(state->inode), RPC_TASK_ASYNC, - &nfs4_lock_ops, data); + task_setup_data.callback_data = data; + task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); ret = nfs4_wait_for_completion_rpc_task(task); diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 8e5428e0b86f..6660d9a53345 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -127,6 +127,11 @@ static const struct rpc_call_ops nfs_unlink_ops = { static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data) { + struct rpc_task_setup task_setup_data = { + .callback_ops = &nfs_unlink_ops, + .callback_data = data, + .flags = RPC_TASK_ASYNC, + }; struct rpc_task *task; struct dentry *alias; @@ -160,7 +165,9 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n data->args.fh = NFS_FH(dir); nfs_fattr_init(&data->res.dir_attr); - task = rpc_run_task(NFS_CLIENT(dir), RPC_TASK_ASYNC, &nfs_unlink_ops, data); + task_setup_data.rpc_client = NFS_CLIENT(dir); + + task = rpc_run_task(&task_setup_data); if (!IS_ERR(task)) rpc_put_task(task); return 1; diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 9efe045fc376..d974421d7647 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h @@ -244,8 +244,7 @@ struct rpc_wait_queue { * Function prototypes */ struct rpc_task *rpc_new_task(const struct rpc_task_setup *); -struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, - const struct rpc_call_ops *ops, void *data); +struct rpc_task *rpc_run_task(const struct rpc_task_setup *); void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *); void rpc_put_task(struct rpc_task *); void rpc_exit_task(struct rpc_task *); diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 7c80abd9263f..9aad45946d32 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -523,8 +523,11 @@ void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset) } EXPORT_SYMBOL_GPL(rpc_clnt_sigunmask); -static -struct rpc_task *rpc_do_run_task(const struct rpc_task_setup *task_setup_data) +/** + * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it + * @task_setup_data: pointer to task initialisation data + */ +struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data) { struct rpc_task *task, *ret; sigset_t oldset; @@ -553,6 +556,7 @@ out: rpc_restore_sigmask(&oldset); return ret; } +EXPORT_SYMBOL_GPL(rpc_run_task); /** * rpc_call_sync - Perform a synchronous RPC call @@ -573,7 +577,7 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) BUG_ON(flags & RPC_TASK_ASYNC); - task = rpc_do_run_task(&task_setup_data); + task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); status = task->tk_status; @@ -603,7 +607,7 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, .flags = flags|RPC_TASK_ASYNC, }; - task = rpc_do_run_task(&task_setup_data); + task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); rpc_put_task(task); @@ -611,28 +615,6 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, } EXPORT_SYMBOL_GPL(rpc_call_async); -/** - * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it - * @clnt: pointer to RPC client - * @flags: RPC flags - * @ops: RPC call ops - * @data: user call data - */ -struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, - const struct rpc_call_ops *tk_ops, - void *data) -{ - struct rpc_task_setup task_setup_data = { - .rpc_client = clnt, - .callback_ops = tk_ops, - .callback_data = data, - .flags = flags, - }; - - return rpc_do_run_task(&task_setup_data); -} -EXPORT_SYMBOL_GPL(rpc_run_task); - void rpc_call_setup(struct rpc_task *task, const struct rpc_message *msg, int flags) { @@ -1550,7 +1532,7 @@ struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int .callback_ops = &rpc_default_ops, .flags = flags, }; - return rpc_do_run_task(&task_setup_data); + return rpc_run_task(&task_setup_data); } EXPORT_SYMBOL_GPL(rpc_call_null); diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index a05493aedb68..7c362e5f6e1b 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -310,6 +310,10 @@ void rpcb_getport_async(struct rpc_task *task) struct rpc_clnt *rpcb_clnt; static struct rpcbind_args *map; struct rpc_task *child; + struct rpc_task_setup task_setup_data = { + .callback_ops = &rpcb_getport_ops, + .flags = RPC_TASK_ASYNC, + }; struct sockaddr addr; int status; struct rpcb_info *info; @@ -395,7 +399,9 @@ void rpcb_getport_async(struct rpc_task *task) sizeof(map->r_addr)); map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ - child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map); + task_setup_data.rpc_client = rpcb_clnt; + task_setup_data.callback_data = map; + child = rpc_run_task(&task_setup_data); rpc_release_client(rpcb_clnt); if (IS_ERR(child)) { status = -EIO; -- cgit v1.2.3 From 3ff7576ddac06c3d07089e241b40826d24bbf1ac Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 14 Jul 2007 15:40:00 -0400 Subject: SUNRPC: Clean up the initialisation of priority queue scheduling info. We want the default scheduling priority (priority == 0) to remain RPC_PRIORITY_NORMAL. Also ensure that the priority wait queue scheduling is per process id instead of sometimes being per thread, and sometimes being per inode. Signed-off-by: Trond Myklebust --- fs/nfs/direct.c | 10 ---------- fs/nfs/read.c | 2 -- fs/nfs/write.c | 12 +++++------- include/linux/sunrpc/sched.h | 17 +++++++++-------- net/sunrpc/sched.c | 30 +++++++++++++++--------------- 5 files changed, 29 insertions(+), 42 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index f9f5fc13dc7d..5bcc764e501a 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -331,8 +331,6 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, rpc_init_task(&data->task, &task_setup_data); NFS_PROTO(inode)->read_setup(data); - data->task.tk_cookie = (unsigned long) inode; - rpc_execute(&data->task); dprintk("NFS: %5u initiated direct read call " @@ -465,9 +463,6 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) rpc_init_task(&data->task, &task_setup_data); NFS_PROTO(inode)->write_setup(data, FLUSH_STABLE); - data->task.tk_priority = RPC_PRIORITY_NORMAL; - data->task.tk_cookie = (unsigned long) inode; - /* * We're called via an RPC callback, so BKL is already held. */ @@ -534,8 +529,6 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) rpc_init_task(&data->task, &task_setup_data); NFS_PROTO(data->inode)->commit_setup(data, 0); - data->task.tk_priority = RPC_PRIORITY_NORMAL; - data->task.tk_cookie = (unsigned long)data->inode; /* Note: task.tk_ops->rpc_release will free dreq->commit_data */ dreq->commit_data = NULL; @@ -718,9 +711,6 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, rpc_init_task(&data->task, &task_setup_data); NFS_PROTO(inode)->write_setup(data, sync); - data->task.tk_priority = RPC_PRIORITY_NORMAL; - data->task.tk_cookie = (unsigned long) inode; - rpc_execute(&data->task); dprintk("NFS: %5u initiated direct write call " diff --git a/fs/nfs/read.c b/fs/nfs/read.c index c7f0d5ebd451..8f1eb08ccffa 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -189,8 +189,6 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, rpc_init_task(&data->task, &task_setup_data); NFS_PROTO(inode)->read_setup(data); - data->task.tk_cookie = (unsigned long)inode; - dprintk("NFS: %5u initiated read call (req %s/%Ld, %u bytes @ offset %Lu)\n", data->task.tk_pid, inode->i_sb->s_id, diff --git a/fs/nfs/write.c b/fs/nfs/write.c index c4376606f106..8d90e90ccd47 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -753,7 +753,7 @@ static void nfs_writepage_release(struct nfs_page *req) nfs_clear_page_tag_locked(req); } -static inline int flush_task_priority(int how) +static int flush_task_priority(int how) { switch (how & (FLUSH_HIGHPRI|FLUSH_LOWPRI)) { case FLUSH_HIGHPRI: @@ -775,11 +775,13 @@ static void nfs_write_rpcsetup(struct nfs_page *req, { struct inode *inode = req->wb_context->path.dentry->d_inode; int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; + int priority = flush_task_priority(how); struct rpc_task_setup task_setup_data = { .rpc_client = NFS_CLIENT(inode), .callback_ops = call_ops, .callback_data = data, .flags = flags, + .priority = priority, }; /* Set up the RPC argument and reply structs @@ -805,9 +807,6 @@ static void nfs_write_rpcsetup(struct nfs_page *req, rpc_init_task(&data->task, &task_setup_data); NFS_PROTO(inode)->write_setup(data, how); - data->task.tk_priority = flush_task_priority(how); - data->task.tk_cookie = (unsigned long)inode; - dprintk("NFS: %5u initiated write call " "(req %s/%Ld, %u bytes @ offset %Lu)\n", data->task.tk_pid, @@ -1152,11 +1151,13 @@ static void nfs_commit_rpcsetup(struct list_head *head, struct nfs_page *first = nfs_list_entry(head->next); struct inode *inode = first->wb_context->path.dentry->d_inode; int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; + int priority = flush_task_priority(how); struct rpc_task_setup task_setup_data = { .rpc_client = NFS_CLIENT(inode), .callback_ops = &nfs_commit_ops, .callback_data = data, .flags = flags, + .priority = priority, }; /* Set up the RPC argument and reply structs @@ -1180,9 +1181,6 @@ static void nfs_commit_rpcsetup(struct list_head *head, rpc_init_task(&data->task, &task_setup_data); NFS_PROTO(inode)->commit_setup(data, how); - data->task.tk_priority = flush_task_priority(how); - data->task.tk_cookie = (unsigned long)inode; - dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); } diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index d974421d7647..c9444fdc23ac 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h @@ -56,8 +56,6 @@ struct rpc_task { __u8 tk_garb_retry; __u8 tk_cred_retry; - unsigned long tk_cookie; /* Cookie for batching tasks */ - /* * timeout_fn to be executed by timer bottom half * callback to be executed after waking up @@ -78,7 +76,6 @@ struct rpc_task { struct timer_list tk_timer; /* kernel timer */ unsigned long tk_timeout; /* timeout for rpc_sleep() */ unsigned short tk_flags; /* misc flags */ - unsigned char tk_priority : 2;/* Task priority */ unsigned long tk_runstate; /* Task run status */ struct workqueue_struct *tk_workqueue; /* Normally rpciod, but could * be any workqueue @@ -94,6 +91,9 @@ struct rpc_task { unsigned long tk_start; /* RPC task init timestamp */ long tk_rtt; /* round-trip time (jiffies) */ + pid_t tk_owner; /* Process id for batching tasks */ + unsigned char tk_priority : 2;/* Task priority */ + #ifdef RPC_DEBUG unsigned short tk_pid; /* debugging aid */ #endif @@ -123,6 +123,7 @@ struct rpc_task_setup { const struct rpc_call_ops *callback_ops; void *callback_data; unsigned short flags; + signed char priority; }; /* @@ -187,10 +188,10 @@ struct rpc_task_setup { * Note: if you change these, you must also change * the task initialization definitions below. */ -#define RPC_PRIORITY_LOW 0 -#define RPC_PRIORITY_NORMAL 1 -#define RPC_PRIORITY_HIGH 2 -#define RPC_NR_PRIORITY (RPC_PRIORITY_HIGH+1) +#define RPC_PRIORITY_LOW (-1) +#define RPC_PRIORITY_NORMAL (0) +#define RPC_PRIORITY_HIGH (1) +#define RPC_NR_PRIORITY (1 + RPC_PRIORITY_HIGH - RPC_PRIORITY_LOW) /* * RPC synchronization objects @@ -198,7 +199,7 @@ struct rpc_task_setup { struct rpc_wait_queue { spinlock_t lock; struct list_head tasks[RPC_NR_PRIORITY]; /* task queue for each priority level */ - unsigned long cookie; /* cookie of last task serviced */ + pid_t owner; /* process id of last task serviced */ unsigned char maxpriority; /* maximum priority (0 if queue is not a priority queue) */ unsigned char priority; /* current priority */ unsigned char count; /* # task groups remaining serviced so far */ diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 10216989309c..b9061bcf6fc1 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -135,7 +135,7 @@ static void __rpc_add_wait_queue_priority(struct rpc_wait_queue *queue, struct r if (unlikely(task->tk_priority > queue->maxpriority)) q = &queue->tasks[queue->maxpriority]; list_for_each_entry(t, q, u.tk_wait.list) { - if (t->tk_cookie == task->tk_cookie) { + if (t->tk_owner == task->tk_owner) { list_add_tail(&task->u.tk_wait.list, &t->u.tk_wait.links); return; } @@ -208,26 +208,26 @@ static inline void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int queue->count = 1 << (priority * 2); } -static inline void rpc_set_waitqueue_cookie(struct rpc_wait_queue *queue, unsigned long cookie) +static inline void rpc_set_waitqueue_owner(struct rpc_wait_queue *queue, pid_t pid) { - queue->cookie = cookie; + queue->owner = pid; queue->nr = RPC_BATCH_COUNT; } static inline void rpc_reset_waitqueue_priority(struct rpc_wait_queue *queue) { rpc_set_waitqueue_priority(queue, queue->maxpriority); - rpc_set_waitqueue_cookie(queue, 0); + rpc_set_waitqueue_owner(queue, 0); } -static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname, int maxprio) +static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname, unsigned char nr_queues) { int i; spin_lock_init(&queue->lock); for (i = 0; i < ARRAY_SIZE(queue->tasks); i++) INIT_LIST_HEAD(&queue->tasks[i]); - queue->maxpriority = maxprio; + queue->maxpriority = nr_queues - 1; rpc_reset_waitqueue_priority(queue); #ifdef RPC_DEBUG queue->name = qname; @@ -236,12 +236,12 @@ static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const c void rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname) { - __rpc_init_priority_wait_queue(queue, qname, RPC_PRIORITY_HIGH); + __rpc_init_priority_wait_queue(queue, qname, RPC_NR_PRIORITY); } void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname) { - __rpc_init_priority_wait_queue(queue, qname, 0); + __rpc_init_priority_wait_queue(queue, qname, 1); } EXPORT_SYMBOL_GPL(rpc_init_wait_queue); @@ -456,12 +456,12 @@ static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queu struct rpc_task *task; /* - * Service a batch of tasks from a single cookie. + * Service a batch of tasks from a single owner. */ q = &queue->tasks[queue->priority]; if (!list_empty(q)) { task = list_entry(q->next, struct rpc_task, u.tk_wait.list); - if (queue->cookie == task->tk_cookie) { + if (queue->owner == task->tk_owner) { if (--queue->nr) goto out; list_move_tail(&task->u.tk_wait.list, q); @@ -470,7 +470,7 @@ static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queu * Check if we need to switch queues. */ if (--queue->count) - goto new_cookie; + goto new_owner; } /* @@ -492,8 +492,8 @@ static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queu new_queue: rpc_set_waitqueue_priority(queue, (unsigned int)(q - &queue->tasks[0])); -new_cookie: - rpc_set_waitqueue_cookie(queue, task->tk_cookie); +new_owner: + rpc_set_waitqueue_owner(queue, task->tk_owner); out: __rpc_wake_up_task(task); return task; @@ -830,8 +830,8 @@ void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *task_setu task->tk_garb_retry = 2; task->tk_cred_retry = 2; - task->tk_priority = RPC_PRIORITY_NORMAL; - task->tk_cookie = (unsigned long)current; + task->tk_priority = task_setup_data->priority - RPC_PRIORITY_LOW; + task->tk_owner = current->tgid; /* Initialize workqueue for async tasks */ task->tk_workqueue = rpciod_workqueue; -- cgit v1.2.3 From 77de2c590ec72828156d85fa13a96db87301cc68 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 25 Oct 2007 18:40:21 -0400 Subject: SUNRPC: Add a helper rpc_call_start() that initialises task->tk_action Signed-off-by: Trond Myklebust --- include/linux/sunrpc/clnt.h | 2 +- net/sunrpc/clnt.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index ec9704181f94..c79f2edf0323 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h @@ -127,7 +127,7 @@ int rpcb_getport_sync(struct sockaddr_in *, __u32, __u32, int); void rpcb_getport_async(struct rpc_task *); void rpc_call_setup(struct rpc_task *, const struct rpc_message *, int); - +void rpc_call_start(struct rpc_task *); int rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, const struct rpc_call_ops *tk_ops, void *calldata); diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index aefe3ae218f7..7aeffeebf42d 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -634,6 +634,13 @@ rpc_call_setup(struct rpc_task *task, const struct rpc_message *msg, int flags) } EXPORT_SYMBOL_GPL(rpc_call_setup); +void +rpc_call_start(struct rpc_task *task) +{ + task->tk_action = call_start; +} +EXPORT_SYMBOL_GPL(rpc_call_start); + /** * rpc_peeraddr - extract remote peer address from clnt's xprt * @clnt: RPC client structure -- cgit v1.2.3 From bdc7f021f3a1fade77adf3c2d7f65690566fddfe Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 14 Jul 2007 15:40:00 -0400 Subject: NFS: Clean up the (commit|read|write)_setup() callback routines Move the common code for setting up the nfs_write_data and nfs_read_data structures into fs/nfs/read.c, fs/nfs/write.c and fs/nfs/direct.c. Signed-off-by: Trond Myklebust --- fs/nfs/direct.c | 45 ++++++++++++++++++++++++++++++++++--------- fs/nfs/nfs3proc.c | 41 ++++++--------------------------------- fs/nfs/nfs4proc.c | 49 ++++++++--------------------------------------- fs/nfs/proc.c | 26 +++++-------------------- fs/nfs/read.c | 38 +++++++++++++++++++----------------- fs/nfs/write.c | 51 +++++++++++++++++++++++++++++++++---------------- include/linux/nfs_xdr.h | 6 +++--- 7 files changed, 113 insertions(+), 143 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 5bcc764e501a..244d1bd7002c 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -272,8 +272,12 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, unsigned long user_addr = (unsigned long)iov->iov_base; size_t count = iov->iov_len; size_t rsize = NFS_SERVER(inode)->rsize; + struct rpc_message msg = { + .rpc_cred = ctx->cred, + }; struct rpc_task_setup task_setup_data = { .rpc_client = NFS_CLIENT(inode), + .rpc_message = &msg, .callback_ops = &nfs_read_direct_ops, .flags = RPC_TASK_ASYNC, }; @@ -316,7 +320,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, data->req = (struct nfs_page *) dreq; data->inode = inode; - data->cred = ctx->cred; + data->cred = msg.rpc_cred; data->args.fh = NFS_FH(inode); data->args.context = ctx; data->args.offset = pos; @@ -326,10 +330,12 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, data->res.fattr = &data->fattr; data->res.eof = 0; data->res.count = bytes; + msg.rpc_argp = &data->args; + msg.rpc_resp = &data->res; task_setup_data.callback_data = data; + NFS_PROTO(inode)->read_setup(data, &msg); rpc_init_task(&data->task, &task_setup_data); - NFS_PROTO(inode)->read_setup(data); rpc_execute(&data->task); @@ -434,6 +440,9 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) struct inode *inode = dreq->inode; struct list_head *p; struct nfs_write_data *data; + struct rpc_message msg = { + .rpc_cred = dreq->ctx->cred, + }; struct rpc_task_setup task_setup_data = { .rpc_client = NFS_CLIENT(inode), .callback_ops = &nfs_write_direct_ops, @@ -448,6 +457,9 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) get_dreq(dreq); + /* Use stable writes */ + data->args.stable = NFS_FILE_SYNC; + /* * Reset data->res. */ @@ -460,8 +472,10 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) * since the original request was sent. */ task_setup_data.callback_data = data; + msg.rpc_argp = &data->args; + msg.rpc_resp = &data->res; + NFS_PROTO(inode)->write_setup(data, &msg); rpc_init_task(&data->task, &task_setup_data); - NFS_PROTO(inode)->write_setup(data, FLUSH_STABLE); /* * We're called via an RPC callback, so BKL is already held. @@ -509,15 +523,21 @@ static const struct rpc_call_ops nfs_commit_direct_ops = { static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) { struct nfs_write_data *data = dreq->commit_data; + struct rpc_message msg = { + .rpc_argp = &data->args, + .rpc_resp = &data->res, + .rpc_cred = dreq->ctx->cred, + }; struct rpc_task_setup task_setup_data = { .rpc_client = NFS_CLIENT(dreq->inode), + .rpc_message = &msg, .callback_ops = &nfs_commit_direct_ops, .callback_data = data, .flags = RPC_TASK_ASYNC, }; data->inode = dreq->inode; - data->cred = dreq->ctx->cred; + data->cred = msg.rpc_cred; data->args.fh = NFS_FH(data->inode); data->args.offset = 0; @@ -526,8 +546,8 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) data->res.fattr = &data->fattr; data->res.verf = &data->verf; + NFS_PROTO(data->inode)->commit_setup(data, &msg); rpc_init_task(&data->task, &task_setup_data); - NFS_PROTO(data->inode)->commit_setup(data, 0); /* Note: task.tk_ops->rpc_release will free dreq->commit_data */ dreq->commit_data = NULL; @@ -649,8 +669,12 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, struct inode *inode = ctx->path.dentry->d_inode; unsigned long user_addr = (unsigned long)iov->iov_base; size_t count = iov->iov_len; + struct rpc_message msg = { + .rpc_cred = ctx->cred, + }; struct rpc_task_setup task_setup_data = { .rpc_client = NFS_CLIENT(inode), + .rpc_message = &msg, .callback_ops = &nfs_write_direct_ops, .flags = RPC_TASK_ASYNC, }; @@ -696,20 +720,23 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, data->req = (struct nfs_page *) dreq; data->inode = inode; - data->cred = ctx->cred; + data->cred = msg.rpc_cred; data->args.fh = NFS_FH(inode); data->args.context = ctx; data->args.offset = pos; data->args.pgbase = pgbase; data->args.pages = data->pagevec; data->args.count = bytes; + data->args.stable = sync; data->res.fattr = &data->fattr; data->res.count = bytes; data->res.verf = &data->verf; task_setup_data.callback_data = data; + msg.rpc_argp = &data->args; + msg.rpc_resp = &data->res; + NFS_PROTO(inode)->write_setup(data, &msg); rpc_init_task(&data->task, &task_setup_data); - NFS_PROTO(inode)->write_setup(data, sync); rpc_execute(&data->task); @@ -782,7 +809,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, struct rpc_clnt *clnt = NFS_CLIENT(inode); struct nfs_direct_req *dreq; size_t wsize = NFS_SERVER(inode)->wsize; - int sync = 0; + int sync = NFS_UNSTABLE; dreq = nfs_direct_req_alloc(); if (!dreq) @@ -790,7 +817,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, nfs_alloc_commit_data(dreq); if (dreq->commit_data == NULL || count < wsize) - sync = FLUSH_STABLE; + sync = NFS_FILE_SYNC; dreq->inode = inode; dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 4cdc2361a669..e68580ebaa47 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -732,16 +732,9 @@ static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data) return 0; } -static void nfs3_proc_read_setup(struct nfs_read_data *data) +static void nfs3_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) { - struct rpc_message msg = { - .rpc_proc = &nfs3_procedures[NFS3PROC_READ], - .rpc_argp = &data->args, - .rpc_resp = &data->res, - .rpc_cred = data->cred, - }; - - rpc_call_setup(&data->task, &msg, 0); + msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ]; } static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data) @@ -753,24 +746,9 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data) return 0; } -static void nfs3_proc_write_setup(struct nfs_write_data *data, int how) +static void nfs3_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) { - struct rpc_message msg = { - .rpc_proc = &nfs3_procedures[NFS3PROC_WRITE], - .rpc_argp = &data->args, - .rpc_resp = &data->res, - .rpc_cred = data->cred, - }; - - data->args.stable = NFS_UNSTABLE; - if (how & FLUSH_STABLE) { - data->args.stable = NFS_FILE_SYNC; - if (NFS_I(data->inode)->ncommit) - data->args.stable = NFS_DATA_SYNC; - } - - /* Finalize the task. */ - rpc_call_setup(&data->task, &msg, 0); + msg->rpc_proc = &nfs3_procedures[NFS3PROC_WRITE]; } static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data) @@ -781,16 +759,9 @@ static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data) return 0; } -static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how) +static void nfs3_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) { - struct rpc_message msg = { - .rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT], - .rpc_argp = &data->args, - .rpc_resp = &data->res, - .rpc_cred = data->cred, - }; - - rpc_call_setup(&data->task, &msg, 0); + msg->rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT]; } static int diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index ff2c5f83ce87..7c0baf23abdc 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2432,18 +2432,10 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) return 0; } -static void nfs4_proc_read_setup(struct nfs_read_data *data) +static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) { - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ], - .rpc_argp = &data->args, - .rpc_resp = &data->res, - .rpc_cred = data->cred, - }; - data->timestamp = jiffies; - - rpc_call_setup(&data->task, &msg, 0); + msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; } static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) @@ -2461,33 +2453,15 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) return 0; } -static void nfs4_proc_write_setup(struct nfs_write_data *data, int how) +static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) { - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE], - .rpc_argp = &data->args, - .rpc_resp = &data->res, - .rpc_cred = data->cred, - }; - struct inode *inode = data->inode; - struct nfs_server *server = NFS_SERVER(inode); - int stable; - - if (how & FLUSH_STABLE) { - if (!NFS_I(inode)->ncommit) - stable = NFS_FILE_SYNC; - else - stable = NFS_DATA_SYNC; - } else - stable = NFS_UNSTABLE; - data->args.stable = stable; + struct nfs_server *server = NFS_SERVER(data->inode); + data->args.bitmask = server->attr_bitmask; data->res.server = server; - data->timestamp = jiffies; - /* Finalize the task. */ - rpc_call_setup(&data->task, &msg, 0); + msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; } static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) @@ -2502,20 +2476,13 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) return 0; } -static void nfs4_proc_commit_setup(struct nfs_write_data *data, int how) +static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) { - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT], - .rpc_argp = &data->args, - .rpc_resp = &data->res, - .rpc_cred = data->cred, - }; struct nfs_server *server = NFS_SERVER(data->inode); data->args.bitmask = server->attr_bitmask; data->res.server = server; - - rpc_call_setup(&data->task, &msg, 0); + msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; } /* diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 4f80d88e9fee..c9f46a24e75c 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -565,16 +565,9 @@ static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data) return 0; } -static void nfs_proc_read_setup(struct nfs_read_data *data) +static void nfs_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) { - struct rpc_message msg = { - .rpc_proc = &nfs_procedures[NFSPROC_READ], - .rpc_argp = &data->args, - .rpc_resp = &data->res, - .rpc_cred = data->cred, - }; - - rpc_call_setup(&data->task, &msg, 0); + msg->rpc_proc = &nfs_procedures[NFSPROC_READ]; } static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) @@ -584,24 +577,15 @@ static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) return 0; } -static void nfs_proc_write_setup(struct nfs_write_data *data, int how) +static void nfs_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) { - struct rpc_message msg = { - .rpc_proc = &nfs_procedures[NFSPROC_WRITE], - .rpc_argp = &data->args, - .rpc_resp = &data->res, - .rpc_cred = data->cred, - }; - /* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */ data->args.stable = NFS_FILE_SYNC; - - /* Finalize the task. */ - rpc_call_setup(&data->task, &msg, 0); + msg->rpc_proc = &nfs_procedures[NFSPROC_WRITE]; } static void -nfs_proc_commit_setup(struct nfs_write_data *data, int how) +nfs_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) { BUG(); } diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 8f1eb08ccffa..e9dbdc8eafe6 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -153,6 +153,16 @@ static void nfs_readpage_release(struct nfs_page *req) nfs_release_request(req); } +static void nfs_execute_read(struct nfs_read_data *data) +{ + struct rpc_clnt *clnt = NFS_CLIENT(data->inode); + sigset_t oldset; + + rpc_clnt_sigmask(clnt, &oldset); + rpc_execute(&data->task); + rpc_clnt_sigunmask(clnt, &oldset); +} + /* * Set up the NFS read request struct */ @@ -162,8 +172,14 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, { struct inode *inode = req->wb_context->path.dentry->d_inode; int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0; + struct rpc_message msg = { + .rpc_argp = &data->args, + .rpc_resp = &data->res, + .rpc_cred = req->wb_context->cred, + }; struct rpc_task_setup task_setup_data = { .rpc_client = NFS_CLIENT(inode), + .rpc_message = &msg, .callback_ops = call_ops, .callback_data = data, .flags = RPC_TASK_ASYNC | swap_flags, @@ -171,7 +187,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, data->req = req; data->inode = inode; - data->cred = req->wb_context->cred; + data->cred = msg.rpc_cred; data->args.fh = NFS_FH(inode); data->args.offset = req_offset(req) + offset; @@ -186,8 +202,8 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, nfs_fattr_init(&data->fattr); /* Set up the initial task struct. */ + NFS_PROTO(inode)->read_setup(data, &msg); rpc_init_task(&data->task, &task_setup_data); - NFS_PROTO(inode)->read_setup(data); dprintk("NFS: %5u initiated read call (req %s/%Ld, %u bytes @ offset %Lu)\n", data->task.tk_pid, @@ -195,6 +211,8 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, (long long)NFS_FILEID(inode), count, (unsigned long long)data->args.offset); + + nfs_execute_read(data); } static void @@ -210,19 +228,6 @@ nfs_async_read_error(struct list_head *head) } } -/* - * Start an async read operation - */ -static void nfs_execute_read(struct nfs_read_data *data) -{ - struct rpc_clnt *clnt = NFS_CLIENT(data->inode); - sigset_t oldset; - - rpc_clnt_sigmask(clnt, &oldset); - rpc_execute(&data->task); - rpc_clnt_sigunmask(clnt, &oldset); -} - /* * Generate multiple requests to fill a single page. * @@ -277,7 +282,6 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne rsize, offset); offset += rsize; nbytes -= rsize; - nfs_execute_read(data); } while (nbytes != 0); return 0; @@ -315,8 +319,6 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned req = nfs_list_entry(data->pages.next); nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0); - - nfs_execute_read(data); return 0; out_bad: nfs_async_read_error(head); diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 8d90e90ccd47..9a69469274ae 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -764,6 +764,16 @@ static int flush_task_priority(int how) return RPC_PRIORITY_NORMAL; } +static void nfs_execute_write(struct nfs_write_data *data) +{ + struct rpc_clnt *clnt = NFS_CLIENT(data->inode); + sigset_t oldset; + + rpc_clnt_sigmask(clnt, &oldset); + rpc_execute(&data->task); + rpc_clnt_sigunmask(clnt, &oldset); +} + /* * Set up the argument/result storage required for the RPC call. */ @@ -776,8 +786,14 @@ static void nfs_write_rpcsetup(struct nfs_page *req, struct inode *inode = req->wb_context->path.dentry->d_inode; int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; int priority = flush_task_priority(how); + struct rpc_message msg = { + .rpc_argp = &data->args, + .rpc_resp = &data->res, + .rpc_cred = req->wb_context->cred, + }; struct rpc_task_setup task_setup_data = { .rpc_client = NFS_CLIENT(inode), + .rpc_message = &msg, .callback_ops = call_ops, .callback_data = data, .flags = flags, @@ -789,7 +805,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req, data->req = req; data->inode = inode = req->wb_context->path.dentry->d_inode; - data->cred = req->wb_context->cred; + data->cred = msg.rpc_cred; data->args.fh = NFS_FH(inode); data->args.offset = req_offset(req) + offset; @@ -797,6 +813,12 @@ static void nfs_write_rpcsetup(struct nfs_page *req, data->args.pages = data->pagevec; data->args.count = count; data->args.context = req->wb_context; + data->args.stable = NFS_UNSTABLE; + if (how & FLUSH_STABLE) { + data->args.stable = NFS_DATA_SYNC; + if (!NFS_I(inode)->ncommit) + data->args.stable = NFS_FILE_SYNC; + } data->res.fattr = &data->fattr; data->res.count = count; @@ -804,8 +826,8 @@ static void nfs_write_rpcsetup(struct nfs_page *req, nfs_fattr_init(&data->fattr); /* Set up the initial task struct. */ + NFS_PROTO(inode)->write_setup(data, &msg); rpc_init_task(&data->task, &task_setup_data); - NFS_PROTO(inode)->write_setup(data, how); dprintk("NFS: %5u initiated write call " "(req %s/%Ld, %u bytes @ offset %Lu)\n", @@ -814,16 +836,8 @@ static void nfs_write_rpcsetup(struct nfs_page *req, (long long)NFS_FILEID(inode), count, (unsigned long long)data->args.offset); -} -static void nfs_execute_write(struct nfs_write_data *data) -{ - struct rpc_clnt *clnt = NFS_CLIENT(data->inode); - sigset_t oldset; - - rpc_clnt_sigmask(clnt, &oldset); - rpc_execute(&data->task); - rpc_clnt_sigunmask(clnt, &oldset); + nfs_execute_write(data); } /* @@ -870,7 +884,6 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned wsize, offset, how); offset += wsize; nbytes -= wsize; - nfs_execute_write(data); } while (nbytes != 0); return 0; @@ -918,7 +931,6 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i /* Set up the argument struct */ nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how); - nfs_execute_write(data); return 0; out_bad: while (!list_empty(head)) { @@ -1152,8 +1164,14 @@ static void nfs_commit_rpcsetup(struct list_head *head, struct inode *inode = first->wb_context->path.dentry->d_inode; int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; int priority = flush_task_priority(how); + struct rpc_message msg = { + .rpc_argp = &data->args, + .rpc_resp = &data->res, + .rpc_cred = first->wb_context->cred, + }; struct rpc_task_setup task_setup_data = { .rpc_client = NFS_CLIENT(inode), + .rpc_message = &msg, .callback_ops = &nfs_commit_ops, .callback_data = data, .flags = flags, @@ -1166,7 +1184,7 @@ static void nfs_commit_rpcsetup(struct list_head *head, list_splice_init(head, &data->pages); data->inode = inode; - data->cred = first->wb_context->cred; + data->cred = msg.rpc_cred; data->args.fh = NFS_FH(data->inode); /* Note: we always request a commit of the entire inode */ @@ -1178,10 +1196,12 @@ static void nfs_commit_rpcsetup(struct list_head *head, nfs_fattr_init(&data->fattr); /* Set up the initial task struct. */ + NFS_PROTO(inode)->commit_setup(data, &msg); rpc_init_task(&data->task, &task_setup_data); - NFS_PROTO(inode)->commit_setup(data, how); dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); + + nfs_execute_write(data); } /* @@ -1201,7 +1221,6 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) /* Set up the argument struct */ nfs_commit_rpcsetup(head, data, how); - nfs_execute_write(data); return 0; out_bad: while (!list_empty(head)) { diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index daab252f2e5c..6b213a64b15f 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -816,11 +816,11 @@ struct nfs_rpc_ops { struct nfs_pathconf *); int (*set_capabilities)(struct nfs_server *, struct nfs_fh *); __be32 *(*decode_dirent)(__be32 *, struct nfs_entry *, int plus); - void (*read_setup) (struct nfs_read_data *); + void (*read_setup) (struct nfs_read_data *, struct rpc_message *); int (*read_done) (struct rpc_task *, struct nfs_read_data *); - void (*write_setup) (struct nfs_write_data *, int how); + void (*write_setup) (struct nfs_write_data *, struct rpc_message *); int (*write_done) (struct rpc_task *, struct nfs_write_data *); - void (*commit_setup) (struct nfs_write_data *, int how); + void (*commit_setup) (struct nfs_write_data *, struct rpc_message *); int (*commit_done) (struct rpc_task *, struct nfs_write_data *); int (*file_open) (struct inode *, struct file *); int (*file_release) (struct inode *, struct file *); -- cgit v1.2.3 From b5627943ab6fabbc13a45d92683363a3d08a249f Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 25 Oct 2007 18:42:21 -0400 Subject: SUNRPC: Remove the now unused function rpc_call_setup() Signed-off-by: Trond Myklebust --- include/linux/sunrpc/clnt.h | 1 - net/sunrpc/clnt.c | 18 ------------------ 2 files changed, 19 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index c79f2edf0323..4fc268ab6f3e 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h @@ -126,7 +126,6 @@ int rpcb_register(u32, u32, int, unsigned short, int *); int rpcb_getport_sync(struct sockaddr_in *, __u32, __u32, int); void rpcb_getport_async(struct rpc_task *); -void rpc_call_setup(struct rpc_task *, const struct rpc_message *, int); void rpc_call_start(struct rpc_task *); int rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, const struct rpc_call_ops *tk_ops, diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 6eb79c49c937..e0a5e47a1d4b 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -613,24 +613,6 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, } EXPORT_SYMBOL_GPL(rpc_call_async); -void -rpc_call_setup(struct rpc_task *task, const struct rpc_message *msg, int flags) -{ - task->tk_msg = *msg; - task->tk_flags |= flags; - /* Bind the user cred */ - if (task->tk_msg.rpc_cred != NULL) - rpcauth_holdcred(task); - else - rpcauth_bindcred(task); - - if (task->tk_status == 0) - task->tk_action = call_start; - else - task->tk_action = rpc_exit_task; -} -EXPORT_SYMBOL_GPL(rpc_call_setup); - void rpc_call_start(struct rpc_task *task) { -- cgit v1.2.3 From e8f5d77c8029ff8f5dcd1dfc133aac0bbbffd92b Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 25 Oct 2007 18:42:53 -0400 Subject: SUNRPC: allow the caller of rpc_run_task to preallocate the struct rpc_task Signed-off-by: Trond Myklebust --- include/linux/sunrpc/sched.h | 1 + net/sunrpc/sched.c | 16 ++++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index c9444fdc23ac..60a05c71637e 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h @@ -118,6 +118,7 @@ struct rpc_call_ops { }; struct rpc_task_setup { + struct rpc_task *task; struct rpc_clnt *rpc_client; const struct rpc_message *rpc_message; const struct rpc_call_ops *callback_ops; diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index fa53a88b2c5b..c03e7bf6e9bc 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -885,16 +885,20 @@ static void rpc_free_task(struct rcu_head *rcu) */ struct rpc_task *rpc_new_task(const struct rpc_task_setup *setup_data) { - struct rpc_task *task; - - task = rpc_alloc_task(); - if (!task) - goto out; + struct rpc_task *task = setup_data->task; + unsigned short flags = 0; + + if (task == NULL) { + task = rpc_alloc_task(); + if (task == NULL) + goto out; + flags = RPC_TASK_DYNAMIC; + } rpc_init_task(task, setup_data); + task->tk_flags |= flags; dprintk("RPC: allocated task %p\n", task); - task->tk_flags |= RPC_TASK_DYNAMIC; out: return task; } -- cgit v1.2.3 From 47fe064831a2a949f6c1e0086f61a105e99ea867 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 25 Oct 2007 18:42:55 -0400 Subject: SUNRPC: Unexport rpc_init_task() and rpc_execute() Signed-off-by: Trond Myklebust --- include/linux/sunrpc/sched.h | 1 - net/sunrpc/sched.c | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 60a05c71637e..23481a5e1f53 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h @@ -247,7 +247,6 @@ struct rpc_wait_queue { */ struct rpc_task *rpc_new_task(const struct rpc_task_setup *); struct rpc_task *rpc_run_task(const struct rpc_task_setup *); -void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *); void rpc_put_task(struct rpc_task *); void rpc_exit_task(struct rpc_task *); void rpc_release_calldata(const struct rpc_call_ops *, void *); diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index c03e7bf6e9bc..ce6cfae91e88 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -737,7 +737,6 @@ void rpc_execute(struct rpc_task *task) rpc_set_running(task); __rpc_execute(task); } -EXPORT_SYMBOL_GPL(rpc_execute); static void rpc_async_schedule(struct work_struct *work) { @@ -815,7 +814,7 @@ EXPORT_SYMBOL_GPL(rpc_free); /* * Creation and deletion of RPC task structures */ -void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *task_setup_data) +static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *task_setup_data) { memset(task, 0, sizeof(*task)); setup_timer(&task->tk_timer, (void (*)(unsigned long))rpc_run_timer, @@ -865,7 +864,6 @@ void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *task_setu dprintk("RPC: new task initialized, procpid %u\n", task_pid_nr(current)); } -EXPORT_SYMBOL_GPL(rpc_init_task); static struct rpc_task * rpc_alloc_task(void) -- cgit v1.2.3 From c087567d3ffb2c7c61e091982e6ca45478394f1a Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 18 Jul 2007 18:32:38 -0400 Subject: SUNRPC: Remove the obsolete RPC_WAITQ macro Now that we've killed off all the users. Signed-off-by: Trond Myklebust --- include/linux/sunrpc/sched.h | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 23481a5e1f53..ce3d1b132729 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h @@ -217,29 +217,6 @@ struct rpc_wait_queue { * performance of NFS operations such as read/write. */ #define RPC_BATCH_COUNT 16 - -#ifndef RPC_DEBUG -# define RPC_WAITQ_INIT(var,qname) { \ - .lock = __SPIN_LOCK_UNLOCKED(var.lock), \ - .tasks = { \ - [0] = LIST_HEAD_INIT(var.tasks[0]), \ - [1] = LIST_HEAD_INIT(var.tasks[1]), \ - [2] = LIST_HEAD_INIT(var.tasks[2]), \ - }, \ - } -#else -# define RPC_WAITQ_INIT(var,qname) { \ - .lock = __SPIN_LOCK_UNLOCKED(var.lock), \ - .tasks = { \ - [0] = LIST_HEAD_INIT(var.tasks[0]), \ - [1] = LIST_HEAD_INIT(var.tasks[1]), \ - [2] = LIST_HEAD_INIT(var.tasks[2]), \ - }, \ - .name = qname, \ - } -#endif -# define RPC_WAITQ(var,qname) struct rpc_wait_queue var = RPC_WAITQ_INIT(var,qname) - #define RPC_IS_PRIORITY(q) ((q)->maxpriority > 0) /* -- cgit v1.2.3 From bfc69a456642a51c89dfd8e5184468857cb44f32 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 15 Oct 2007 18:18:29 -0400 Subject: NFS: define a function to update nfsi->cache_change_attribute Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 15 +++++++++++++++ fs/nfs/inode.c | 6 ++++-- fs/nfs/nfs4proc.c | 2 +- include/linux/nfs_fs.h | 1 + 4 files changed, 21 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 32c666c612a1..72d141a0dbd8 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -638,6 +638,21 @@ static int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync) return 0; } +/** + * nfs_force_lookup_revalidate - Mark the directory as having changed + * @dir - pointer to directory inode + * + * This forces the revalidation code in nfs_lookup_revalidate() to do a + * full lookup on all child dentries of 'dir' whenever a change occurs + * on the server that might have invalidated our dcache. + * + * The caller should be holding dir->i_lock + */ +void nfs_force_lookup_revalidate(struct inode *dir) +{ + NFS_I(dir)->cache_change_attribute = jiffies; +} + /* * A check for whether or not the parent directory has changed. * In the case it has, we assume that the dentries are untrustworthy diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index cc3a09db41a9..5747d49bdd76 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1029,7 +1029,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) dprintk("NFS: mtime change on server for file %s/%ld\n", inode->i_sb->s_id, inode->i_ino); invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; - nfsi->cache_change_attribute = now; + if (S_ISDIR(inode->i_mode)) + nfs_force_lookup_revalidate(inode); } /* If ctime has changed we should definitely clear access+acl caches */ if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) @@ -1038,7 +1039,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) dprintk("NFS: change_attr change on server for file %s/%ld\n", inode->i_sb->s_id, inode->i_ino); invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; - nfsi->cache_change_attribute = now; + if (S_ISDIR(inode->i_mode)) + nfs_force_lookup_revalidate(inode); } /* Check if our cached file size is stale */ diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 826b445b8c70..26192a703129 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -210,7 +210,7 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) spin_lock(&dir->i_lock); nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA; if (!cinfo->atomic || cinfo->before != nfsi->change_attr) - nfsi->cache_change_attribute = jiffies; + nfs_force_lookup_revalidate(dir); nfsi->change_attr = cinfo->after; spin_unlock(&dir->i_lock); } diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 2d15d4aac094..7095aaa087d8 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -366,6 +366,7 @@ extern const struct inode_operations nfs3_dir_inode_operations; extern const struct file_operations nfs_dir_operations; extern struct dentry_operations nfs_dentry_operations; +extern void nfs_force_lookup_revalidate(struct inode *dir); extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr); extern int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags); extern void nfs_access_zap_cache(struct inode *inode); -- cgit v1.2.3 From 40c553193df41920de659f0446e5d214c862e827 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 14 Dec 2007 14:56:07 -0500 Subject: NFS: Remove the redundant nfs_client->cl_nfsversion We can get the same information from the rpc_ops structure instead. Signed-off-by: Trond Myklebust --- fs/nfs/client.c | 41 ++++++++++++++++++----------------------- fs/nfs/namespace.c | 2 +- fs/nfs/super.c | 2 +- include/linux/nfs_fs_sb.h | 1 - 4 files changed, 20 insertions(+), 26 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/client.c b/fs/nfs/client.c index ff778ecee0bd..3b21731ae571 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -96,7 +96,7 @@ struct rpc_program nfsacl_program = { struct nfs_client_initdata { const char *hostname; const struct sockaddr_in *addr; - int version; + const struct nfs_rpc_ops *rpc_ops; }; /* @@ -112,7 +112,9 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) goto error_0; - if (cl_init->version == 4) { + clp->rpc_ops = cl_init->rpc_ops; + + if (cl_init->rpc_ops->version == 4) { if (nfs_callback_up() < 0) goto error_2; __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state); @@ -121,7 +123,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ atomic_set(&clp->cl_count, 1); clp->cl_cons_state = NFS_CS_INITING; - clp->cl_nfsversion = cl_init->version; memcpy(&clp->cl_addr, cl_init->addr, sizeof(clp->cl_addr)); if (cl_init->hostname) { @@ -170,7 +171,7 @@ static void nfs4_shutdown_client(struct nfs_client *clp) */ static void nfs_free_client(struct nfs_client *clp) { - dprintk("--> nfs_free_client(%d)\n", clp->cl_nfsversion); + dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version); nfs4_shutdown_client(clp); @@ -222,7 +223,7 @@ struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversio continue; /* Different NFS versions cannot share the same nfs_client */ - if (clp->cl_nfsversion != nfsversion) + if (clp->rpc_ops->version != nfsversion) continue; /* Match only the IP address, not the port number */ @@ -251,7 +252,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat continue; /* Different NFS versions cannot share the same nfs_client */ - if (clp->cl_nfsversion != data->version) + if (clp->rpc_ops != data->rpc_ops) continue; /* Match the full socket address */ @@ -273,9 +274,9 @@ static struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_in struct nfs_client *clp, *new = NULL; int error; - dprintk("--> nfs_get_client(%s,"NIPQUAD_FMT":%d,%d)\n", + dprintk("--> nfs_get_client(%s,"NIPQUAD_FMT":%d,%u)\n", cl_init->hostname ?: "", NIPQUAD(cl_init->addr->sin_addr), - cl_init->addr->sin_port, cl_init->version); + cl_init->addr->sin_port, cl_init->rpc_ops->version); /* see if the client already exists */ do { @@ -430,7 +431,7 @@ static int nfs_start_lockd(struct nfs_server *server) { int error = 0; - if (server->nfs_client->cl_nfsversion > 3) + if (server->nfs_client->rpc_ops->version > 3) goto out; if (server->flags & NFS_MOUNT_NONLM) goto out; @@ -450,7 +451,7 @@ out: #ifdef CONFIG_NFS_V3_ACL static void nfs_init_server_aclclient(struct nfs_server *server) { - if (server->nfs_client->cl_nfsversion != 3) + if (server->nfs_client->rpc_ops->version != 3) goto out_noacl; if (server->flags & NFS_MOUNT_NOACL) goto out_noacl; @@ -521,12 +522,6 @@ static int nfs_init_client(struct nfs_client *clp, return 0; } - /* Check NFS protocol revision and initialize RPC op vector */ - clp->rpc_ops = &nfs_v2_clientops; -#ifdef CONFIG_NFS_V3 - if (clp->cl_nfsversion == 3) - clp->rpc_ops = &nfs_v3_clientops; -#endif /* * Create a client RPC handle for doing FSSTAT with UNIX auth only * - RFC 2623, sec 2.3.2 @@ -553,7 +548,7 @@ static int nfs_init_server(struct nfs_server *server, struct nfs_client_initdata cl_init = { .hostname = data->nfs_server.hostname, .addr = &data->nfs_server.address, - .version = 2, + .rpc_ops = &nfs_v2_clientops, }; struct nfs_client *clp; int error; @@ -562,7 +557,7 @@ static int nfs_init_server(struct nfs_server *server, #ifdef CONFIG_NFS_V3 if (data->flags & NFS_MOUNT_VER3) - cl_init.version = 3; + cl_init.rpc_ops = &nfs_v3_clientops; #endif /* Allocate or find a client reference we can use */ @@ -906,7 +901,7 @@ static int nfs4_set_client(struct nfs_server *server, struct nfs_client_initdata cl_init = { .hostname = hostname, .addr = addr, - .version = 4, + .rpc_ops = &nfs_v4_clientops, }; struct nfs_client *clp; int error; @@ -1284,8 +1279,8 @@ static int nfs_server_list_show(struct seq_file *m, void *v) /* display one transport per line on subsequent lines */ clp = list_entry(v, struct nfs_client, cl_share_link); - seq_printf(m, "v%d %02x%02x%02x%02x %4hx %3d %s\n", - clp->cl_nfsversion, + seq_printf(m, "v%u %02x%02x%02x%02x %4hx %3d %s\n", + clp->rpc_ops->version, NIPQUAD(clp->cl_addr.sin_addr), ntohs(clp->cl_addr.sin_port), atomic_read(&clp->cl_count), @@ -1363,8 +1358,8 @@ static int nfs_volume_list_show(struct seq_file *m, void *v) (unsigned long long) server->fsid.major, (unsigned long long) server->fsid.minor); - seq_printf(m, "v%d %02x%02x%02x%02x %4hx %-7s %-17s\n", - clp->cl_nfsversion, + seq_printf(m, "v%u %02x%02x%02x%02x %4hx %-7s %-17s\n", + clp->rpc_ops->version, NIPQUAD(clp->cl_addr.sin_addr), ntohs(clp->cl_addr.sin_port), dev, diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index acfc56f9edc0..be4ce1c3a3d8 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -188,7 +188,7 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, { #ifdef CONFIG_NFS_V4 struct vfsmount *mnt = NULL; - switch (server->nfs_client->cl_nfsversion) { + switch (server->nfs_client->rpc_ops->version) { case 2: case 3: mnt = vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata); diff --git a/fs/nfs/super.c b/fs/nfs/super.c index a3492d6f8f9b..5608e6a4c1e1 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -529,7 +529,7 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt) seq_printf(m, ",namelen=%d", nfss->namelen); #ifdef CONFIG_NFS_V4 - if (nfss->nfs_client->cl_nfsversion == 4) { + if (nfss->nfs_client->rpc_ops->version == 4) { seq_printf(m, "\n\tnfsv4:\t"); seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 9f949b587684..97b325756667 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -17,7 +17,6 @@ struct nfs_client { int cl_cons_state; /* current construction state (-ve: init error) */ #define NFS_CS_READY 0 /* ready to be used */ #define NFS_CS_INITING 1 /* busy initialising */ - int cl_nfsversion; /* NFS protocol version */ unsigned long cl_res_state; /* NFS resources state */ #define NFS_CS_CALLBACK 1 /* - callback started */ #define NFS_CS_IDMAP 2 /* - idmap started */ -- cgit v1.2.3 From 0fb2b7e945f55a8317e5f58db7c068aab5b825a1 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 10 Dec 2007 14:56:46 -0500 Subject: SUNRPC: Move universal address definitions to global header Universal addresses are defined in RFC 1833 and clarified in RFC 3530. We need to use them in several places in the NFS and RPC clients, so move the relevant definition and block comment to an appropriate global include file. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- include/linux/sunrpc/msg_prot.h | 39 +++++++++++++++++++++++++++++++++++ net/sunrpc/rpcb_clnt.c | 45 +++-------------------------------------- 2 files changed, 42 insertions(+), 42 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/msg_prot.h b/include/linux/sunrpc/msg_prot.h index c4beb5775111..70df4f1d8847 100644 --- a/include/linux/sunrpc/msg_prot.h +++ b/include/linux/sunrpc/msg_prot.h @@ -152,5 +152,44 @@ typedef __be32 rpc_fraghdr; */ #define RPCBIND_MAXNETIDLEN (4u) +/* + * Universal addresses are introduced in RFC 1833 and further spelled + * out in RFC 3530. RPCBIND_MAXUADDRLEN defines a maximum byte length + * of a universal address for use in allocating buffers and character + * arrays. + * + * Quoting RFC 3530, section 2.2: + * + * For TCP over IPv4 and for UDP over IPv4, the format of r_addr is the + * US-ASCII string: + * + * h1.h2.h3.h4.p1.p2 + * + * The prefix, "h1.h2.h3.h4", is the standard textual form for + * representing an IPv4 address, which is always four octets long. + * Assuming big-endian ordering, h1, h2, h3, and h4, are respectively, + * the first through fourth octets each converted to ASCII-decimal. + * Assuming big-endian ordering, p1 and p2 are, respectively, the first + * and second octets each converted to ASCII-decimal. For example, if a + * host, in big-endian order, has an address of 0x0A010307 and there is + * a service listening on, in big endian order, port 0x020F (decimal + * 527), then the complete universal address is "10.1.3.7.2.15". + * + * ... + * + * For TCP over IPv6 and for UDP over IPv6, the format of r_addr is the + * US-ASCII string: + * + * x1:x2:x3:x4:x5:x6:x7:x8.p1.p2 + * + * The suffix "p1.p2" is the service port, and is computed the same way + * as with universal addresses for TCP and UDP over IPv4. The prefix, + * "x1:x2:x3:x4:x5:x6:x7:x8", is the standard textual form for + * representing an IPv6 address as defined in Section 2.2 of [RFC2373]. + * Additionally, the two alternative forms specified in Section 2.2 of + * [RFC2373] are also acceptable. + */ +#define RPCBIND_MAXUADDRLEN (56u) + #endif /* __KERNEL__ */ #endif /* _LINUX_SUNRPC_MSGPROT_H_ */ diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 9696b5127060..f494e58910ec 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -54,45 +54,6 @@ enum { #define RPCB_HIGHPROC_3 RPCBPROC_TADDR2UADDR #define RPCB_HIGHPROC_4 RPCBPROC_GETSTAT -/* - * r_addr - * - * Quoting RFC 3530, section 2.2: - * - * For TCP over IPv4 and for UDP over IPv4, the format of r_addr is the - * US-ASCII string: - * - * h1.h2.h3.h4.p1.p2 - * - * The prefix, "h1.h2.h3.h4", is the standard textual form for - * representing an IPv4 address, which is always four octets long. - * Assuming big-endian ordering, h1, h2, h3, and h4, are respectively, - * the first through fourth octets each converted to ASCII-decimal. - * Assuming big-endian ordering, p1 and p2 are, respectively, the first - * and second octets each converted to ASCII-decimal. For example, if a - * host, in big-endian order, has an address of 0x0A010307 and there is - * a service listening on, in big endian order, port 0x020F (decimal - * 527), then the complete universal address is "10.1.3.7.2.15". - * - * ... - * - * For TCP over IPv6 and for UDP over IPv6, the format of r_addr is the - * US-ASCII string: - * - * x1:x2:x3:x4:x5:x6:x7:x8.p1.p2 - * - * The suffix "p1.p2" is the service port, and is computed the same way - * as with universal addresses for TCP and UDP over IPv4. The prefix, - * "x1:x2:x3:x4:x5:x6:x7:x8", is the standard textual form for - * representing an IPv6 address as defined in Section 2.2 of [RFC2373]. - * Additionally, the two alternative forms specified in Section 2.2 of - * [RFC2373] are also acceptable. - * - * XXX: Currently this implementation does not explicitly convert the - * stored address to US-ASCII on non-ASCII systems. - */ -#define RPCB_MAXADDRLEN (128u) - /* * r_owner * @@ -113,7 +74,7 @@ struct rpcbind_args { u32 r_prot; unsigned short r_port; char * r_netid; - char r_addr[RPCB_MAXADDRLEN]; + char r_addr[RPCBIND_MAXUADDRLEN]; char * r_owner; }; @@ -526,7 +487,7 @@ static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p, * Simple sanity check. The smallest possible universal * address is an IPv4 address string containing 11 bytes. */ - if (addr_len < 11 || addr_len > RPCB_MAXADDRLEN) + if (addr_len < 11 || addr_len > RPCBIND_MAXUADDRLEN) goto out_err; /* @@ -577,7 +538,7 @@ out_err: #define RPCB_boolean_sz (1u) #define RPCB_netid_sz (1+XDR_QUADLEN(RPCBIND_MAXNETIDLEN)) -#define RPCB_addr_sz (1+XDR_QUADLEN(RPCB_MAXADDRLEN)) +#define RPCB_addr_sz (1+XDR_QUADLEN(RPCBIND_MAXUADDRLEN)) #define RPCB_ownerstring_sz (1+XDR_QUADLEN(RPCB_MAXOWNERLEN)) #define RPCB_mappingargs_sz RPCB_program_sz+RPCB_version_sz+ \ -- cgit v1.2.3 From cc38bac3a0093b3b7928efc6ff8e9faf9e75f41d Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 10 Dec 2007 14:56:54 -0500 Subject: NFS: Ensure NFSv4 SETCLIENTID send buffer is large enough Ensure that the RPC buffer size specified for NFSv4 SETCLIENTID procedures matches what we are encoding into the buffer. See the definition of struct nfs4_setclientid {} and the encode_setclientid() function. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- fs/nfs/nfs4xdr.c | 10 ++++++---- include/linux/nfs_xdr.h | 13 +++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index eae46f008da7..db1ed9c46ede 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -116,10 +116,12 @@ static int nfs4_stat_to_errno(int); #define decode_renew_maxsz (op_decode_hdr_maxsz) #define encode_setclientid_maxsz \ (op_encode_hdr_maxsz + \ - 4 /*server->ip_addr*/ + \ - 1 /*Netid*/ + \ - 6 /*uaddr*/ + \ - 6 + (NFS4_VERIFIER_SIZE >> 2)) + XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \ + XDR_QUADLEN(NFS4_SETCLIENTID_NAMELEN) + \ + 1 /* sc_prog */ + \ + XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \ + XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \ + 1) /* sc_cb_ident */ #define decode_setclientid_maxsz \ (op_decode_hdr_maxsz + \ 2 + \ diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 6b213a64b15f..d8e395d0c7c9 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -666,16 +666,17 @@ struct nfs4_rename_res { struct nfs_fattr * new_fattr; }; +#define NFS4_SETCLIENTID_NAMELEN (48) struct nfs4_setclientid { - const nfs4_verifier * sc_verifier; /* request */ + const nfs4_verifier * sc_verifier; unsigned int sc_name_len; - char sc_name[48]; /* request */ - u32 sc_prog; /* request */ + char sc_name[NFS4_SETCLIENTID_NAMELEN]; + u32 sc_prog; unsigned int sc_netid_len; - char sc_netid[4]; /* request */ + char sc_netid[RPCBIND_MAXNETIDLEN]; unsigned int sc_uaddr_len; - char sc_uaddr[24]; /* request */ - u32 sc_cb_ident; /* request */ + char sc_uaddr[RPCBIND_MAXUADDRLEN]; + u32 sc_cb_ident; }; struct nfs4_statfs_arg { -- cgit v1.2.3 From 4392f2592297876967191238a341667a6d4fc456 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 10 Dec 2007 14:57:01 -0500 Subject: NFS: Increase size of cl_ipaddr field to hold IPv6 addresses The nfs_client's cl_ipaddr field needs to be larger to hold strings that represent IPv6 addresses. Signed-off-by: Chuck Lever Cc: Aurelien Charbon Signed-off-by: Trond Myklebust --- include/linux/nfs_fs_sb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 97b325756667..0b3dcba3d97d 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -64,7 +64,7 @@ struct nfs_client { /* Our own IP address, as a null-terminated string. * This is used to generate the clientid, and the callback address. */ - char cl_ipaddr[16]; + char cl_ipaddr[48]; unsigned char cl_id_uniquifier; #endif }; -- cgit v1.2.3 From 6e4cffd7b2cf86022dcf9cceeb63f16ff852caa1 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 10 Dec 2007 14:58:15 -0500 Subject: NFS: Expand server address storage in nfs_client struct Prepare for managing larger addresses in the NFS client by widening the nfs_client struct's cl_addr field. Signed-off-by: Chuck Lever Cc: Aurelien Charbon (Modified to work with the new parameters for nfs_alloc_client) Signed-off-by: Trond Myklebust --- fs/nfs/client.c | 8 ++++++-- include/linux/nfs_fs_sb.h | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 876162cddf1e..44fe7fd7bfbf 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -98,6 +98,7 @@ struct rpc_program nfsacl_program = { struct nfs_client_initdata { const char *hostname; const struct sockaddr_in *addr; + size_t addrlen; const struct nfs_rpc_ops *rpc_ops; }; @@ -125,7 +126,8 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ atomic_set(&clp->cl_count, 1); clp->cl_cons_state = NFS_CS_INITING; - memcpy(&clp->cl_addr, cl_init->addr, sizeof(clp->cl_addr)); + memcpy(&clp->cl_addr, cl_init->addr, cl_init->addrlen); + clp->cl_addrlen = cl_init->addrlen; if (cl_init->hostname) { clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL); @@ -425,7 +427,7 @@ static int nfs_create_rpc_client(struct nfs_client *clp, int proto, struct rpc_create_args args = { .protocol = proto, .address = (struct sockaddr *)&clp->cl_addr, - .addrsize = sizeof(clp->cl_addr), + .addrsize = clp->cl_addrlen, .timeout = &timeparms, .servername = clp->cl_hostname, .program = &nfs_program, @@ -585,6 +587,7 @@ static int nfs_init_server(struct nfs_server *server, struct nfs_client_initdata cl_init = { .hostname = data->nfs_server.hostname, .addr = &data->nfs_server.address, + .addrlen = sizeof(data->nfs_server.address), .rpc_ops = &nfs_v2_clientops, }; struct nfs_client *clp; @@ -938,6 +941,7 @@ static int nfs4_set_client(struct nfs_server *server, struct nfs_client_initdata cl_init = { .hostname = hostname, .addr = addr, + .addrlen = sizeof(*addr), .rpc_ops = &nfs_v4_clientops, }; struct nfs_client *clp; diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 0b3dcba3d97d..912cfe84ea86 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -21,7 +21,8 @@ struct nfs_client { #define NFS_CS_CALLBACK 1 /* - callback started */ #define NFS_CS_IDMAP 2 /* - idmap started */ #define NFS_CS_RENEWD 3 /* - renewd started */ - struct sockaddr_in cl_addr; /* server identifier */ + struct sockaddr_storage cl_addr; /* server identifier */ + size_t cl_addrlen; char * cl_hostname; /* hostname of server */ struct list_head cl_share_link; /* link in global client list */ struct list_head cl_superblocks; /* List of nfs_server structs */ -- cgit v1.2.3 From 69dd716c5ffd89f5ba14ffb871d633ecea74d13a Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 14 Dec 2007 14:56:07 -0500 Subject: NFSv4: Add socket proto argument to setclientid Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 4 +++- include/linux/nfs_xdr.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 5e8c4cf7959e..b3d4e8e5696a 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2891,10 +2891,12 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po for(;;) { setclientid.sc_name_len = scnprintf(setclientid.sc_name, - sizeof(setclientid.sc_name), "%s/%s %s %u", + sizeof(setclientid.sc_name), "%s/%s %s %s %u", clp->cl_ipaddr, rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR), + rpc_peeraddr2str(clp->cl_rpcclient, + RPC_DISPLAY_PROTO), cred->cr_ops->cr_name, clp->cl_id_uniquifier); setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index d8e395d0c7c9..d342ae5c76ab 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -666,7 +666,7 @@ struct nfs4_rename_res { struct nfs_fattr * new_fattr; }; -#define NFS4_SETCLIENTID_NAMELEN (48) +#define NFS4_SETCLIENTID_NAMELEN (56) struct nfs4_setclientid { const nfs4_verifier * sc_verifier; unsigned int sc_name_len; -- cgit v1.2.3 From 2881ae74e68ecfe3b32a90936e5d93a9ba598c3a Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 20 Dec 2007 16:03:54 -0500 Subject: SUNRPC: Clean up the transport timeout initialisation Signed-off-by: Trond Myklebust --- include/linux/sunrpc/xprt.h | 5 ----- net/sunrpc/xprt.c | 17 ----------------- net/sunrpc/xprtrdma/transport.c | 7 ++++++- net/sunrpc/xprtsock.c | 29 +++++++++++++++++++++-------- 4 files changed, 27 insertions(+), 31 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index 2554cd2b016f..a00d4a4ba6ee 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -202,11 +202,6 @@ struct xprt_class { char name[32]; }; -/* - * Transport operations used by ULPs - */ -void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr); - /* * Generic internal transport functions */ diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 7520c6623c46..2bc99569c586 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -977,23 +977,6 @@ void xprt_release(struct rpc_task *task) spin_unlock(&xprt->reserve_lock); } -/** - * xprt_set_timeout - set constant RPC timeout - * @to: RPC timeout parameters to set up - * @retr: number of retries - * @incr: amount of increase after each retry - * - */ -void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr) -{ - to->to_initval = - to->to_increment = incr; - to->to_maxval = to->to_initval + (incr * retr); - to->to_retries = retr; - to->to_exponential = 0; -} -EXPORT_SYMBOL_GPL(xprt_set_timeout); - /** * xprt_create_transport - create an RPC transport * @args: rpc transport creation arguments diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 73033d824eed..39f10016c86b 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -289,6 +289,11 @@ xprt_rdma_destroy(struct rpc_xprt *xprt) module_put(THIS_MODULE); } +static const struct rpc_timeout xprt_rdma_default_timeout = { + .to_initval = 60 * HZ, + .to_maxval = 60 * HZ, +}; + /** * xprt_setup_rdma - Set up transport to use RDMA * @@ -327,7 +332,7 @@ xprt_setup_rdma(struct xprt_create *args) } /* 60 second timeout, no retries */ - xprt_set_timeout(&xprt->timeout, 0, 60UL * HZ); + memcpy(&xprt->timeout, &xprt_rdma_default_timeout, sizeof(xprt->timeout)); xprt->bind_timeout = (60U * HZ); xprt->connect_timeout = (60U * HZ); xprt->reestablish_timeout = (5U * HZ); diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index a4cfdc5b2648..d7b07ac5b710 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1895,6 +1895,13 @@ static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args, return xprt; } +static const struct rpc_timeout xs_udp_default_timeout = { + .to_initval = 5 * HZ, + .to_maxval = 30 * HZ, + .to_increment = 5 * HZ, + .to_retries = 5, +}; + /** * xs_setup_udp - Set up transport to use a UDP socket * @args: rpc transport creation arguments @@ -1905,6 +1912,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) struct sockaddr *addr = args->dstaddr; struct rpc_xprt *xprt; struct sock_xprt *transport; + const struct rpc_timeout *timeo = &xs_udp_default_timeout; xprt = xs_setup_xprt(args, xprt_udp_slot_table_entries); if (IS_ERR(xprt)) @@ -1923,10 +1931,9 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) xprt->ops = &xs_udp_ops; - if (args->timeout) - xprt->timeout = *args->timeout; - else - xprt_set_timeout(&xprt->timeout, 5, 5 * HZ); + if (args->timeout != NULL) + timeo = args->timeout; + memcpy(&xprt->timeout, timeo, sizeof(xprt->timeout)); switch (addr->sa_family) { case AF_INET: @@ -1961,6 +1968,12 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) return ERR_PTR(-EINVAL); } +static const struct rpc_timeout xs_tcp_default_timeout = { + .to_initval = 60 * HZ, + .to_maxval = 60 * HZ, + .to_retries = 2, +}; + /** * xs_setup_tcp - Set up transport to use a TCP socket * @args: rpc transport creation arguments @@ -1971,6 +1984,7 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) struct sockaddr *addr = args->dstaddr; struct rpc_xprt *xprt; struct sock_xprt *transport; + const struct rpc_timeout *timeo = &xs_tcp_default_timeout; xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries); if (IS_ERR(xprt)) @@ -1988,10 +2002,9 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) xprt->ops = &xs_tcp_ops; - if (args->timeout) - xprt->timeout = *args->timeout; - else - xprt_set_timeout(&xprt->timeout, 2, 60 * HZ); + if (args->timeout != NULL) + timeo = args->timeout; + memcpy(&xprt->timeout, timeo, sizeof(xprt->timeout)); switch (addr->sa_family) { case AF_INET: -- cgit v1.2.3 From ba7392bb37cb12781890f45d7ddee1618e33a036 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 20 Dec 2007 16:03:55 -0500 Subject: SUNRPC: Add support for per-client timeout values In order to be able to support setting the timeo and retrans parameters on a per-mountpoint basis, we move the rpc_timeout structure into the rpc_clnt. Signed-off-by: Trond Myklebust --- include/linux/sunrpc/clnt.h | 4 +++- include/linux/sunrpc/xprt.h | 3 +-- net/sunrpc/clnt.c | 12 +++++++++--- net/sunrpc/xprt.c | 11 ++++++----- net/sunrpc/xprtrdma/transport.c | 2 +- net/sunrpc/xprtsock.c | 11 ++--------- 6 files changed, 22 insertions(+), 21 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 4fc268ab6f3e..51a338189a23 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h @@ -46,6 +46,7 @@ struct rpc_clnt { cl_autobind : 1;/* use getport() */ struct rpc_rtt * cl_rtt; /* RTO estimator data */ + const struct rpc_timeout *cl_timeout; /* Timeout strategy */ int cl_nodelen; /* nodename length */ char cl_nodename[UNX_MAXNODENAME]; @@ -54,6 +55,7 @@ struct rpc_clnt { struct dentry * cl_dentry; /* inode */ struct rpc_clnt * cl_parent; /* Points to parent of clones */ struct rpc_rtt cl_rtt_default; + struct rpc_timeout cl_timeout_default; struct rpc_program * cl_program; char cl_inline_name[32]; }; @@ -99,7 +101,7 @@ struct rpc_create_args { struct sockaddr *address; size_t addrsize; struct sockaddr *saddress; - struct rpc_timeout *timeout; + const struct rpc_timeout *timeout; char *servername; struct rpc_program *program; u32 version; diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index a00d4a4ba6ee..c3364d88d83e 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -120,7 +120,7 @@ struct rpc_xprt { struct kref kref; /* Reference count */ struct rpc_xprt_ops * ops; /* transport methods */ - struct rpc_timeout timeout; /* timeout parms */ + const struct rpc_timeout *timeout; /* timeout parms */ struct sockaddr_storage addr; /* server address */ size_t addrlen; /* size of server address */ int prot; /* IP protocol */ @@ -191,7 +191,6 @@ struct xprt_create { struct sockaddr * srcaddr; /* optional local address */ struct sockaddr * dstaddr; /* remote peer address */ size_t addrlen; - struct rpc_timeout * timeout; /* optional timeout parameters */ }; struct xprt_class { diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 6a6b96e8dcb2..a3c00da9ce21 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -188,8 +188,15 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru if (!xprt_bound(clnt->cl_xprt)) clnt->cl_autobind = 1; + clnt->cl_timeout = xprt->timeout; + if (args->timeout != NULL) { + memcpy(&clnt->cl_timeout_default, args->timeout, + sizeof(clnt->cl_timeout_default)); + clnt->cl_timeout = &clnt->cl_timeout_default; + } + clnt->cl_rtt = &clnt->cl_rtt_default; - rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval); + rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval); kref_init(&clnt->cl_kref); @@ -251,7 +258,6 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) .srcaddr = args->saddress, .dstaddr = args->address, .addrlen = args->addrsize, - .timeout = args->timeout }; char servername[48]; @@ -348,7 +354,7 @@ rpc_clone_client(struct rpc_clnt *clnt) new->cl_autobind = 0; INIT_LIST_HEAD(&new->cl_tasks); spin_lock_init(&new->cl_lock); - rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); + rpc_init_rtt(&new->cl_rtt_default, clnt->cl_timeout->to_initval); new->cl_metrics = rpc_alloc_iostats(clnt); if (new->cl_metrics == NULL) goto out_no_stats; diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 2bc99569c586..cfcade906a56 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -501,9 +501,10 @@ EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_def); void xprt_set_retrans_timeout_rtt(struct rpc_task *task) { int timer = task->tk_msg.rpc_proc->p_timer; - struct rpc_rtt *rtt = task->tk_client->cl_rtt; + struct rpc_clnt *clnt = task->tk_client; + struct rpc_rtt *rtt = clnt->cl_rtt; struct rpc_rqst *req = task->tk_rqstp; - unsigned long max_timeout = req->rq_xprt->timeout.to_maxval; + unsigned long max_timeout = clnt->cl_timeout->to_maxval; task->tk_timeout = rpc_calc_rto(rtt, timer); task->tk_timeout <<= rpc_ntimeo(rtt, timer) + req->rq_retries; @@ -514,7 +515,7 @@ EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_rtt); static void xprt_reset_majortimeo(struct rpc_rqst *req) { - struct rpc_timeout *to = &req->rq_xprt->timeout; + const struct rpc_timeout *to = req->rq_task->tk_client->cl_timeout; req->rq_majortimeo = req->rq_timeout; if (to->to_exponential) @@ -534,7 +535,7 @@ static void xprt_reset_majortimeo(struct rpc_rqst *req) int xprt_adjust_timeout(struct rpc_rqst *req) { struct rpc_xprt *xprt = req->rq_xprt; - struct rpc_timeout *to = &xprt->timeout; + const struct rpc_timeout *to = req->rq_task->tk_client->cl_timeout; int status = 0; if (time_before(jiffies, req->rq_majortimeo)) { @@ -928,7 +929,7 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) { struct rpc_rqst *req = task->tk_rqstp; - req->rq_timeout = xprt->timeout.to_initval; + req->rq_timeout = task->tk_client->cl_timeout->to_initval; req->rq_task = task; req->rq_xprt = xprt; req->rq_buffer = NULL; diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 39f10016c86b..d1389afc8342 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -332,7 +332,7 @@ xprt_setup_rdma(struct xprt_create *args) } /* 60 second timeout, no retries */ - memcpy(&xprt->timeout, &xprt_rdma_default_timeout, sizeof(xprt->timeout)); + xprt->timeout = &xprt_rdma_default_timeout; xprt->bind_timeout = (60U * HZ); xprt->connect_timeout = (60U * HZ); xprt->reestablish_timeout = (5U * HZ); diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index d7b07ac5b710..6ba329d339a2 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1912,7 +1912,6 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) struct sockaddr *addr = args->dstaddr; struct rpc_xprt *xprt; struct sock_xprt *transport; - const struct rpc_timeout *timeo = &xs_udp_default_timeout; xprt = xs_setup_xprt(args, xprt_udp_slot_table_entries); if (IS_ERR(xprt)) @@ -1931,9 +1930,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) xprt->ops = &xs_udp_ops; - if (args->timeout != NULL) - timeo = args->timeout; - memcpy(&xprt->timeout, timeo, sizeof(xprt->timeout)); + xprt->timeout = &xs_udp_default_timeout; switch (addr->sa_family) { case AF_INET: @@ -1984,7 +1981,6 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) struct sockaddr *addr = args->dstaddr; struct rpc_xprt *xprt; struct sock_xprt *transport; - const struct rpc_timeout *timeo = &xs_tcp_default_timeout; xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries); if (IS_ERR(xprt)) @@ -2001,10 +1997,7 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) xprt->idle_timeout = XS_IDLE_DISC_TO; xprt->ops = &xs_tcp_ops; - - if (args->timeout != NULL) - timeo = args->timeout; - memcpy(&xprt->timeout, timeo, sizeof(xprt->timeout)); + xprt->timeout = &xs_tcp_default_timeout; switch (addr->sa_family) { case AF_INET: -- cgit v1.2.3 From 331702337f2b2e7cef40366ee207a25604df4671 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 20 Dec 2007 16:03:59 -0500 Subject: NFS: Support per-mountpoint timeout parameters. Signed-off-by: Trond Myklebust --- fs/nfs/client.c | 82 +++++++++++++++++++++++++++-------------------- fs/nfs/super.c | 4 +-- include/linux/nfs_fs_sb.h | 2 -- 3 files changed, 49 insertions(+), 39 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 59a6dccab548..03d9bed7849a 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -415,18 +415,16 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, * Create an RPC client handle */ static int nfs_create_rpc_client(struct nfs_client *clp, int proto, - unsigned int timeo, - unsigned int retrans, - rpc_authflavor_t flavor, - int flags) + const struct rpc_timeout *timeparms, + rpc_authflavor_t flavor, + int flags) { - struct rpc_timeout timeparms; struct rpc_clnt *clnt = NULL; struct rpc_create_args args = { .protocol = proto, .address = (struct sockaddr *)&clp->cl_addr, .addrsize = clp->cl_addrlen, - .timeout = &timeparms, + .timeout = timeparms, .servername = clp->cl_hostname, .program = &nfs_program, .version = clp->rpc_ops->version, @@ -437,10 +435,6 @@ static int nfs_create_rpc_client(struct nfs_client *clp, int proto, if (!IS_ERR(clp->cl_rpcclient)) return 0; - nfs_init_timeout_values(&timeparms, proto, timeo, retrans); - clp->retrans_timeo = timeparms.to_initval; - clp->retrans_count = timeparms.to_retries; - clnt = rpc_create(&args); if (IS_ERR(clnt)) { dprintk("%s: cannot create RPC client. Error = %ld\n", @@ -515,7 +509,9 @@ static inline void nfs_init_server_aclclient(struct nfs_server *server) /* * Create a general RPC client */ -static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t pseudoflavour) +static int nfs_init_server_rpcclient(struct nfs_server *server, + const struct rpc_timeout *timeo, + rpc_authflavor_t pseudoflavour) { struct nfs_client *clp = server->nfs_client; @@ -525,6 +521,11 @@ static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t return PTR_ERR(server->client); } + memcpy(&server->client->cl_timeout_default, + timeo, + sizeof(server->client->cl_timeout_default)); + server->client->cl_timeout = &server->client->cl_timeout_default; + if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) { struct rpc_auth *auth; @@ -549,6 +550,7 @@ static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t * Initialise an NFS2 or NFS3 client */ static int nfs_init_client(struct nfs_client *clp, + const struct rpc_timeout *timeparms, const struct nfs_parsed_mount_data *data) { int error; @@ -564,7 +566,7 @@ static int nfs_init_client(struct nfs_client *clp, * - RFC 2623, sec 2.3.2 */ error = nfs_create_rpc_client(clp, data->nfs_server.protocol, - data->timeo, data->retrans, RPC_AUTH_UNIX, 0); + timeparms, RPC_AUTH_UNIX, 0); if (error < 0) goto error; nfs_mark_client_ready(clp, NFS_CS_READY); @@ -588,6 +590,7 @@ static int nfs_init_server(struct nfs_server *server, .addrlen = data->nfs_server.addrlen, .rpc_ops = &nfs_v2_clientops, }; + struct rpc_timeout timeparms; struct nfs_client *clp; int error; @@ -605,7 +608,9 @@ static int nfs_init_server(struct nfs_server *server, return PTR_ERR(clp); } - error = nfs_init_client(clp, data); + nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, + data->timeo, data->retrans); + error = nfs_init_client(clp, &timeparms, data); if (error < 0) goto error; @@ -629,7 +634,7 @@ static int nfs_init_server(struct nfs_server *server, if (error < 0) goto error; - error = nfs_init_server_rpcclient(server, data->auth_flavors[0]); + error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]); if (error < 0) goto error; @@ -889,7 +894,8 @@ error: * Initialise an NFS4 client record */ static int nfs4_init_client(struct nfs_client *clp, - int proto, int timeo, int retrans, + int proto, + const struct rpc_timeout *timeparms, const char *ip_addr, rpc_authflavor_t authflavour) { @@ -904,7 +910,7 @@ static int nfs4_init_client(struct nfs_client *clp, /* Check NFS protocol revision and initialize RPC op vector */ clp->rpc_ops = &nfs_v4_clientops; - error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour, + error = nfs_create_rpc_client(clp, proto, timeparms, authflavour, RPC_CLNT_CREATE_DISCRTRY); if (error < 0) goto error; @@ -936,7 +942,7 @@ static int nfs4_set_client(struct nfs_server *server, const size_t addrlen, const char *ip_addr, rpc_authflavor_t authflavour, - int proto, int timeo, int retrans) + int proto, const struct rpc_timeout *timeparms) { struct nfs_client_initdata cl_init = { .hostname = hostname, @@ -955,7 +961,7 @@ static int nfs4_set_client(struct nfs_server *server, error = PTR_ERR(clp); goto error; } - error = nfs4_init_client(clp, proto, timeo, retrans, ip_addr, authflavour); + error = nfs4_init_client(clp, proto, timeparms, ip_addr, authflavour); if (error < 0) goto error_put; @@ -976,10 +982,26 @@ error: static int nfs4_init_server(struct nfs_server *server, const struct nfs_parsed_mount_data *data) { + struct rpc_timeout timeparms; int error; dprintk("--> nfs4_init_server()\n"); + nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, + data->timeo, data->retrans); + + /* Get a client record */ + error = nfs4_set_client(server, + data->nfs_server.hostname, + (const struct sockaddr *)&data->nfs_server.address, + data->nfs_server.addrlen, + data->client_address, + data->auth_flavors[0], + data->nfs_server.protocol, + &timeparms); + if (error < 0) + goto error; + /* Initialise the client representation from the mount data */ server->flags = data->flags & NFS_MOUNT_FLAGMASK; server->caps |= NFS_CAP_ATOMIC_OPEN; @@ -994,8 +1016,9 @@ static int nfs4_init_server(struct nfs_server *server, server->acdirmin = data->acdirmin * HZ; server->acdirmax = data->acdirmax * HZ; - error = nfs_init_server_rpcclient(server, data->auth_flavors[0]); + error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]); +error: /* Done */ dprintk("<-- nfs4_init_server() = %d\n", error); return error; @@ -1018,18 +1041,6 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, if (!server) return ERR_PTR(-ENOMEM); - /* Get a client record */ - error = nfs4_set_client(server, - data->nfs_server.hostname, - (struct sockaddr *)&data->nfs_server.address, - data->nfs_server.addrlen, - data->client_address, - data->auth_flavors[0], - data->nfs_server.protocol, - data->timeo, data->retrans); - if (error < 0) - goto error; - /* set up the general RPC client */ error = nfs4_init_server(server, data); if (error < 0) @@ -1103,8 +1114,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, parent_client->cl_ipaddr, data->authflavor, parent_server->client->cl_xprt->prot, - parent_client->retrans_timeo, - parent_client->retrans_count); + parent_server->client->cl_timeout); if (error < 0) goto error; @@ -1112,7 +1122,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, nfs_server_copy_userdata(server, parent_server); server->caps |= NFS_CAP_ATOMIC_OPEN; - error = nfs_init_server_rpcclient(server, data->authflavor); + error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor); if (error < 0) goto error; @@ -1181,7 +1191,9 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, server->fsid = fattr->fsid; - error = nfs_init_server_rpcclient(server, source->client->cl_auth->au_flavor); + error = nfs_init_server_rpcclient(server, + source->client->cl_timeout, + source->client->cl_auth->au_flavor); if (error < 0) goto out_free_server; if (!IS_ERR(source->client_acl)) diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 3cbe32f3e88b..0d1bc61d0b68 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -479,8 +479,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, } seq_printf(m, ",proto=%s", rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO)); - seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ); - seq_printf(m, ",retrans=%u", clp->retrans_count); + seq_printf(m, ",timeo=%lu", 10U * nfss->client->cl_timeout->to_initval / HZ); + seq_printf(m, ",retrans=%u", nfss->client->cl_timeout->to_retries); seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor)); } diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 912cfe84ea86..d15c9487b8f1 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -29,8 +29,6 @@ struct nfs_client { struct rpc_clnt * cl_rpcclient; const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */ - unsigned long retrans_timeo; /* retransmit timeout */ - unsigned int retrans_count; /* number of retransmit tries */ #ifdef CONFIG_NFS_V4 u64 cl_clientid; /* constant */ -- cgit v1.2.3 From 59dca3b28cb915745019d4f4c27d97b6b6ab12c6 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 3 Jan 2008 16:29:06 -0500 Subject: NFS: Fix the 'proto=' mount option Currently, if you have a server mounted using networking protocol, you cannot specify a different value using the 'proto=' option on another mountpoint. Signed-off-by: Trond Myklebust --- fs/nfs/client.c | 20 +++++++++++++------- include/linux/nfs_fs_sb.h | 1 + 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 03d9bed7849a..18fcb05a0707 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -100,6 +100,7 @@ struct nfs_client_initdata { const struct sockaddr *addr; size_t addrlen; const struct nfs_rpc_ops *rpc_ops; + int proto; }; /* @@ -138,6 +139,8 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ INIT_LIST_HEAD(&clp->cl_superblocks); clp->cl_rpcclient = ERR_PTR(-EINVAL); + clp->cl_proto = cl_init->proto; + #ifdef CONFIG_NFS_V4 init_rwsem(&clp->cl_sem); INIT_LIST_HEAD(&clp->cl_delegations); @@ -289,6 +292,9 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat if (clp->rpc_ops != data->rpc_ops) continue; + if (clp->cl_proto != data->proto) + continue; + /* Match the full socket address */ if (memcmp(&clp->cl_addr, data->addr, sizeof(clp->cl_addr)) != 0) continue; @@ -414,14 +420,14 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, /* * Create an RPC client handle */ -static int nfs_create_rpc_client(struct nfs_client *clp, int proto, +static int nfs_create_rpc_client(struct nfs_client *clp, const struct rpc_timeout *timeparms, rpc_authflavor_t flavor, int flags) { struct rpc_clnt *clnt = NULL; struct rpc_create_args args = { - .protocol = proto, + .protocol = clp->cl_proto, .address = (struct sockaddr *)&clp->cl_addr, .addrsize = clp->cl_addrlen, .timeout = timeparms, @@ -565,8 +571,7 @@ static int nfs_init_client(struct nfs_client *clp, * Create a client RPC handle for doing FSSTAT with UNIX auth only * - RFC 2623, sec 2.3.2 */ - error = nfs_create_rpc_client(clp, data->nfs_server.protocol, - timeparms, RPC_AUTH_UNIX, 0); + error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX, 0); if (error < 0) goto error; nfs_mark_client_ready(clp, NFS_CS_READY); @@ -589,6 +594,7 @@ static int nfs_init_server(struct nfs_server *server, .addr = (const struct sockaddr *)&data->nfs_server.address, .addrlen = data->nfs_server.addrlen, .rpc_ops = &nfs_v2_clientops, + .proto = data->nfs_server.protocol, }; struct rpc_timeout timeparms; struct nfs_client *clp; @@ -894,7 +900,6 @@ error: * Initialise an NFS4 client record */ static int nfs4_init_client(struct nfs_client *clp, - int proto, const struct rpc_timeout *timeparms, const char *ip_addr, rpc_authflavor_t authflavour) @@ -910,7 +915,7 @@ static int nfs4_init_client(struct nfs_client *clp, /* Check NFS protocol revision and initialize RPC op vector */ clp->rpc_ops = &nfs_v4_clientops; - error = nfs_create_rpc_client(clp, proto, timeparms, authflavour, + error = nfs_create_rpc_client(clp, timeparms, authflavour, RPC_CLNT_CREATE_DISCRTRY); if (error < 0) goto error; @@ -949,6 +954,7 @@ static int nfs4_set_client(struct nfs_server *server, .addr = addr, .addrlen = addrlen, .rpc_ops = &nfs_v4_clientops, + .proto = proto, }; struct nfs_client *clp; int error; @@ -961,7 +967,7 @@ static int nfs4_set_client(struct nfs_server *server, error = PTR_ERR(clp); goto error; } - error = nfs4_init_client(clp, proto, timeparms, ip_addr, authflavour); + error = nfs4_init_client(clp, timeparms, ip_addr, authflavour); if (error < 0) goto error_put; diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index d15c9487b8f1..b5ba5f79485d 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -29,6 +29,7 @@ struct nfs_client { struct rpc_clnt * cl_rpcclient; const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */ + int cl_proto; /* Network transport protocol */ #ifdef CONFIG_NFS_V4 u64 cl_clientid; /* constant */ -- cgit v1.2.3 From b454ae906085cf7774fb4756746680c9b03b6f84 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 7 Jan 2008 18:34:48 -0500 Subject: SUNRPC: fewer conditionals in the format_ip_address routines Clean up: have the set up routines explicitly pass the strings to be used for the transport name and NETID. This removes a number of conditionals and dependencies on rpc_xprt.prot, which is overloaded. Tighten up type checking on the address_strings array while we're at it. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- include/linux/sunrpc/clnt.h | 2 +- include/linux/sunrpc/xprt.h | 2 +- net/sunrpc/clnt.c | 3 ++- net/sunrpc/rpcb_clnt.c | 2 +- net/sunrpc/xprtsock.c | 56 ++++++++++++++++++--------------------------- 5 files changed, 27 insertions(+), 38 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 51a338189a23..5a13da2573b0 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h @@ -143,7 +143,7 @@ void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int); size_t rpc_max_payload(struct rpc_clnt *); void rpc_force_rebind(struct rpc_clnt *); size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t); -char * rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t); +const char *rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t); #endif /* __KERNEL__ */ #endif /* _LINUX_SUNRPC_CLNT_H */ diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index c3364d88d83e..b3ff9a815e6f 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -183,7 +183,7 @@ struct rpc_xprt { bklog_u; /* backlog queue utilization */ } stat; - char * address_strings[RPC_DISPLAY_MAX]; + const char *address_strings[RPC_DISPLAY_MAX]; }; struct xprt_create { diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index a3c00da9ce21..e775ca793249 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -679,7 +679,8 @@ EXPORT_SYMBOL_GPL(rpc_peeraddr); * @format: address format * */ -char *rpc_peeraddr2str(struct rpc_clnt *clnt, enum rpc_display_format_t format) +const char *rpc_peeraddr2str(struct rpc_clnt *clnt, + enum rpc_display_format_t format) { struct rpc_xprt *xprt = clnt->cl_xprt; diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index f494e58910ec..b60fa92321a5 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -358,7 +358,7 @@ void rpcb_getport_async(struct rpc_task *task) map->r_prot = xprt->prot; map->r_port = 0; map->r_xprt = xprt_get(xprt); - map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); + map->r_netid = (char *)rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); memcpy(map->r_addr, rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR), sizeof(map->r_addr)); diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 6ba329d339a2..b9b94f49c620 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -280,7 +280,9 @@ static inline struct sockaddr_in6 *xs_addr_in6(struct rpc_xprt *xprt) return (struct sockaddr_in6 *) &xprt->addr; } -static void xs_format_ipv4_peer_addresses(struct rpc_xprt *xprt) +static void xs_format_ipv4_peer_addresses(struct rpc_xprt *xprt, + const char *protocol, + const char *netid) { struct sockaddr_in *addr = xs_addr_in(xprt); char *buf; @@ -299,21 +301,14 @@ static void xs_format_ipv4_peer_addresses(struct rpc_xprt *xprt) } xprt->address_strings[RPC_DISPLAY_PORT] = buf; - buf = kzalloc(8, GFP_KERNEL); - if (buf) { - if (xprt->prot == IPPROTO_UDP) - snprintf(buf, 8, "udp"); - else - snprintf(buf, 8, "tcp"); - } - xprt->address_strings[RPC_DISPLAY_PROTO] = buf; + xprt->address_strings[RPC_DISPLAY_PROTO] = protocol; buf = kzalloc(48, GFP_KERNEL); if (buf) { snprintf(buf, 48, "addr="NIPQUAD_FMT" port=%u proto=%s", NIPQUAD(addr->sin_addr.s_addr), ntohs(addr->sin_port), - xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); + protocol); } xprt->address_strings[RPC_DISPLAY_ALL] = buf; @@ -340,12 +335,12 @@ static void xs_format_ipv4_peer_addresses(struct rpc_xprt *xprt) } xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; - xprt->address_strings[RPC_DISPLAY_NETID] = - kstrdup(xprt->prot == IPPROTO_UDP ? - RPCBIND_NETID_UDP : RPCBIND_NETID_TCP, GFP_KERNEL); + xprt->address_strings[RPC_DISPLAY_NETID] = netid; } -static void xs_format_ipv6_peer_addresses(struct rpc_xprt *xprt) +static void xs_format_ipv6_peer_addresses(struct rpc_xprt *xprt, + const char *protocol, + const char *netid) { struct sockaddr_in6 *addr = xs_addr_in6(xprt); char *buf; @@ -364,21 +359,14 @@ static void xs_format_ipv6_peer_addresses(struct rpc_xprt *xprt) } xprt->address_strings[RPC_DISPLAY_PORT] = buf; - buf = kzalloc(8, GFP_KERNEL); - if (buf) { - if (xprt->prot == IPPROTO_UDP) - snprintf(buf, 8, "udp"); - else - snprintf(buf, 8, "tcp"); - } - xprt->address_strings[RPC_DISPLAY_PROTO] = buf; + xprt->address_strings[RPC_DISPLAY_PROTO] = protocol; buf = kzalloc(64, GFP_KERNEL); if (buf) { snprintf(buf, 64, "addr="NIP6_FMT" port=%u proto=%s", NIP6(addr->sin6_addr), ntohs(addr->sin6_port), - xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); + protocol); } xprt->address_strings[RPC_DISPLAY_ALL] = buf; @@ -405,17 +393,17 @@ static void xs_format_ipv6_peer_addresses(struct rpc_xprt *xprt) } xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; - xprt->address_strings[RPC_DISPLAY_NETID] = - kstrdup(xprt->prot == IPPROTO_UDP ? - RPCBIND_NETID_UDP6 : RPCBIND_NETID_TCP6, GFP_KERNEL); + xprt->address_strings[RPC_DISPLAY_NETID] = netid; } static void xs_free_peer_addresses(struct rpc_xprt *xprt) { - int i; - - for (i = 0; i < RPC_DISPLAY_MAX; i++) - kfree(xprt->address_strings[i]); + kfree(xprt->address_strings[RPC_DISPLAY_ADDR]); + kfree(xprt->address_strings[RPC_DISPLAY_PORT]); + kfree(xprt->address_strings[RPC_DISPLAY_ALL]); + kfree(xprt->address_strings[RPC_DISPLAY_HEX_ADDR]); + kfree(xprt->address_strings[RPC_DISPLAY_HEX_PORT]); + kfree(xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR]); } #define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL) @@ -1939,7 +1927,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) INIT_DELAYED_WORK(&transport->connect_worker, xs_udp_connect_worker4); - xs_format_ipv4_peer_addresses(xprt); + xs_format_ipv4_peer_addresses(xprt, "udp", RPCBIND_NETID_UDP); break; case AF_INET6: if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0)) @@ -1947,7 +1935,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) INIT_DELAYED_WORK(&transport->connect_worker, xs_udp_connect_worker6); - xs_format_ipv6_peer_addresses(xprt); + xs_format_ipv6_peer_addresses(xprt, "udp", RPCBIND_NETID_UDP6); break; default: kfree(xprt); @@ -2005,14 +1993,14 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) xprt_set_bound(xprt); INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker4); - xs_format_ipv4_peer_addresses(xprt); + xs_format_ipv4_peer_addresses(xprt, "tcp", RPCBIND_NETID_TCP); break; case AF_INET6: if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0)) xprt_set_bound(xprt); INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker6); - xs_format_ipv6_peer_addresses(xprt); + xs_format_ipv6_peer_addresses(xprt, "tcp", RPCBIND_NETID_TCP6); break; default: kfree(xprt); -- cgit v1.2.3 From 52c4044d00fe703eb3fb18e0d8dfd1c196eb28be Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 11 Jan 2008 17:09:44 -0500 Subject: NLM: Introduce external nlm_host set-up and tear-down functions We would like to remove the per-lock-operation nlm_lookup_host() call from nlmclnt_proc(). The new architecture pins an nlm_host structure to each NFS client superblock that has the "lock" mount option set. The NFS client passes in the pinned nlm_host structure during each call to nlmclnt_proc(). NFS client unmount processing "puts" the nlm_host so it can be garbage- collected later. This patch introduces externally callable NLM functions that handle mount-time nlm_host set up and tear-down. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- fs/lockd/clntlock.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/lockd/bind.h | 7 +++++++ 2 files changed, 55 insertions(+) (limited to 'include/linux') diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index d070b18e539d..9a8f4f45c19e 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -41,6 +41,54 @@ struct nlm_wait { static LIST_HEAD(nlm_blocked); +/** + * nlmclnt_init - Set up per-NFS mount point lockd data structures + * @server_name: server's hostname + * @server_address: server's network address + * @server_addrlen: length of server's address + * @protocol: transport protocol lockd should use + * @nfs_version: NFS protocol version for this mount point + * + * Returns pointer to an appropriate nlm_host struct, + * or an ERR_PTR value. + */ +struct nlm_host *nlmclnt_init(const char *server_name, + const struct sockaddr *server_address, + size_t server_addrlen, + unsigned short protocol, u32 nfs_version) +{ + struct nlm_host *host; + u32 nlm_version = (nfs_version == 2) ? 1 : 4; + int status; + + status = lockd_up(protocol); + if (status < 0) + return ERR_PTR(status); + + host = nlmclnt_lookup_host((struct sockaddr_in *)server_address, + protocol, nlm_version, + server_name, strlen(server_name)); + if (host == NULL) { + lockd_down(); + return ERR_PTR(-ENOLCK); + } + + return host; +} +EXPORT_SYMBOL_GPL(nlmclnt_init); + +/** + * nlmclnt_done - Release resources allocated by nlmclnt_init() + * @host: nlm_host structure reserved by nlmclnt_init() + * + */ +void nlmclnt_done(struct nlm_host *host) +{ + nlm_release_host(host); + lockd_down(); +} +EXPORT_SYMBOL_GPL(nlmclnt_done); + /* * Queue up a lock for blocking so that the GRANTED request can see it */ diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h index 6f1637c61e10..ad5402f5456b 100644 --- a/include/linux/lockd/bind.h +++ b/include/linux/lockd/bind.h @@ -35,6 +35,13 @@ extern struct nlmsvc_binding * nlmsvc_ops; /* * Functions exported by the lockd module */ +extern struct nlm_host *nlmclnt_init(const char *server_name, + const struct sockaddr *server_address, + size_t server_addrlen, + unsigned short protocol, + u32 nfs_version); +extern void nlmclnt_done(struct nlm_host *host); + extern int nlmclnt_proc(struct inode *, int, struct file_lock *); extern int lockd_up(int proto); extern void lockd_down(void); -- cgit v1.2.3 From 9289e7f91add1c09c3ec8571a2080f7507730b8d Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 11 Jan 2008 17:09:52 -0500 Subject: NFS: Invoke nlmclnt_init during NFS mount processing Cache an appropriate nlm_host structure in the NFS client's mount point metadata for later use. Note that there is no need to set NFS_MOUNT_NONLM in the error case -- if nfs_start_lockd() returns a non-zero value, its callers ensure that the mount request fails outright. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- fs/nfs/client.c | 32 +++++++++++++++++++------------- include/linux/nfs_fs_sb.h | 2 ++ 2 files changed, 21 insertions(+), 13 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 18fcb05a0707..0b3ce86f6fc9 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -458,7 +458,7 @@ static int nfs_create_rpc_client(struct nfs_client *clp, static void nfs_destroy_server(struct nfs_server *server) { if (!(server->flags & NFS_MOUNT_NONLM)) - lockd_down(); /* release rpc.lockd */ + nlmclnt_done(server->nlm_host); } /* @@ -466,20 +466,26 @@ static void nfs_destroy_server(struct nfs_server *server) */ static int nfs_start_lockd(struct nfs_server *server) { - int error = 0; + struct nlm_host *host; + struct nfs_client *clp = server->nfs_client; + u32 nfs_version = clp->rpc_ops->version; + unsigned short protocol = server->flags & NFS_MOUNT_TCP ? + IPPROTO_TCP : IPPROTO_UDP; - if (server->nfs_client->rpc_ops->version > 3) - goto out; + if (nfs_version > 3) + return 0; if (server->flags & NFS_MOUNT_NONLM) - goto out; - error = lockd_up((server->flags & NFS_MOUNT_TCP) ? - IPPROTO_TCP : IPPROTO_UDP); - if (error < 0) - server->flags |= NFS_MOUNT_NONLM; - else - server->destroy = nfs_destroy_server; -out: - return error; + return 0; + + host = nlmclnt_init(clp->cl_hostname, + (struct sockaddr *)&clp->cl_addr, + clp->cl_addrlen, protocol, nfs_version); + if (IS_ERR(host)) + return PTR_ERR(host); + + server->nlm_host = host; + server->destroy = nfs_destroy_server; + return 0; } /* diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index b5ba5f79485d..3423c6761bf7 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -8,6 +8,7 @@ #include struct nfs_iostats; +struct nlm_host; /* * The nfs_client identifies our client state to the server. @@ -80,6 +81,7 @@ struct nfs_server { struct list_head master_link; /* link in master servers list */ struct rpc_clnt * client; /* RPC client handle */ struct rpc_clnt * client_acl; /* ACL RPC client handle */ + struct nlm_host *nlm_host; /* NLM client handle */ struct nfs_iostats * io_stats; /* I/O statistics */ struct backing_dev_info backing_dev_info; atomic_long_t writeback; /* number of writeback pages */ -- cgit v1.2.3 From 1093a60ef34bb12010fe7ea4b780bee1c57cfbbe Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 11 Jan 2008 17:09:59 -0500 Subject: NLM/NFS: Use cached nlm_host when calling nlmclnt_proc() Now that each NFS mount point caches its own nlm_host structure, it can be passed to nlmclnt_proc() for each lock request. By pinning an nlm_host for each mount point, we trade the overhead of looking up or creating a fresh nlm_host struct during every NLM procedure call for a little extra memory. We also restrict the nlmclnt_proc symbol to limit the use of this call to in-tree modules. Note that nlm_lookup_host() (just removed from the client's per-request NLM processing) could also trigger an nlm_host garbage collection. Now client-side nlm_host garbage collection occurs only during NFS mount processing. Since the NFS client now holds a reference on these nlm_host structures, they wouldn't have been affected by garbage collection anyway. Given that nlm_lookup_host() reorders the global nlm_host chain after every successful lookup, and that a garbage collection could be triggered during the call, we've removed a significant amount of per-NLM-request CPU processing overhead. Sidebar: there are only a few remaining references to the internals of NFS inodes in the client-side NLM code. The only references I found are related to extracting or comparing the inode's file handle via NFS_FH(). One is in nlmclnt_grant(); the other is in nlmclnt_setlockargs(). Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- fs/lockd/clntproc.c | 33 ++++++++++----------------------- fs/nfs/nfs3proc.c | 4 +++- fs/nfs/proc.c | 4 +++- include/linux/lockd/bind.h | 3 ++- 4 files changed, 18 insertions(+), 26 deletions(-) (limited to 'include/linux') diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index a10343bed160..b1a4dba443bc 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -145,34 +145,21 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req) BUG_ON(req->a_args.lock.fl.fl_ops != NULL); } -/* - * This is the main entry point for the NLM client. +/** + * nlmclnt_proc - Perform a single client-side lock request + * @host: address of a valid nlm_host context representing the NLM server + * @cmd: fcntl-style file lock operation to perform + * @fl: address of arguments for the lock operation + * */ -int -nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) +int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl) { - struct rpc_clnt *client = NFS_CLIENT(inode); - struct sockaddr_in addr; - struct nfs_server *nfssrv = NFS_SERVER(inode); - struct nlm_host *host; struct nlm_rqst *call; sigset_t oldset; unsigned long flags; - int status, vers; - - vers = (NFS_PROTO(inode)->version == 3) ? 4 : 1; - if (NFS_PROTO(inode)->version > 3) { - printk(KERN_NOTICE "NFSv4 file locking not implemented!\n"); - return -ENOLCK; - } - - rpc_peeraddr(client, (struct sockaddr *) &addr, sizeof(addr)); - host = nlmclnt_lookup_host(&addr, client->cl_xprt->prot, vers, - nfssrv->nfs_client->cl_hostname, - strlen(nfssrv->nfs_client->cl_hostname)); - if (host == NULL) - return -ENOLCK; + int status; + nlm_get_host(host); call = nlm_alloc_call(host); if (call == NULL) return -ENOMEM; @@ -219,7 +206,7 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) dprintk("lockd: clnt proc returns %d\n", status); return status; } -EXPORT_SYMBOL(nlmclnt_proc); +EXPORT_SYMBOL_GPL(nlmclnt_proc); /* * Allocate an NLM RPC call struct diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index e68580ebaa47..b353c1a05bfd 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -767,7 +767,9 @@ static void nfs3_proc_commit_setup(struct nfs_write_data *data, struct rpc_messa static int nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl) { - return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl); + struct inode *inode = filp->f_path.dentry->d_inode; + + return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl); } const struct nfs_rpc_ops nfs_v3_clientops = { diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index c9f46a24e75c..5ccf7faee19c 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -593,7 +593,9 @@ nfs_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) static int nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl) { - return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl); + struct inode *inode = filp->f_path.dentry->d_inode; + + return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl); } diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h index ad5402f5456b..73368075af03 100644 --- a/include/linux/lockd/bind.h +++ b/include/linux/lockd/bind.h @@ -42,7 +42,8 @@ extern struct nlm_host *nlmclnt_init(const char *server_name, u32 nfs_version); extern void nlmclnt_done(struct nlm_host *host); -extern int nlmclnt_proc(struct inode *, int, struct file_lock *); +extern int nlmclnt_proc(struct nlm_host *host, int cmd, + struct file_lock *fl); extern int lockd_up(int proto); extern void lockd_down(void); -- cgit v1.2.3 From 883bb163f84e0a54b29846c61621f52db3f27393 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 15 Jan 2008 16:04:20 -0500 Subject: NLM: Introduce an arguments structure for nlmclnt_init() Clean up: pass 5 arguments to nlmclnt_init() in a structure similar to the new nfs_client_initdata structure. Signed-off-by: Chuck Lever --- fs/lockd/clntlock.c | 22 ++++++++-------------- fs/nfs/client.c | 17 ++++++++++------- include/linux/lockd/bind.h | 19 ++++++++++++++----- 3 files changed, 32 insertions(+), 26 deletions(-) (limited to 'include/linux') diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index 9a8f4f45c19e..0b45fd3a4bfd 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -43,31 +43,25 @@ static LIST_HEAD(nlm_blocked); /** * nlmclnt_init - Set up per-NFS mount point lockd data structures - * @server_name: server's hostname - * @server_address: server's network address - * @server_addrlen: length of server's address - * @protocol: transport protocol lockd should use - * @nfs_version: NFS protocol version for this mount point + * @nlm_init: pointer to arguments structure * * Returns pointer to an appropriate nlm_host struct, * or an ERR_PTR value. */ -struct nlm_host *nlmclnt_init(const char *server_name, - const struct sockaddr *server_address, - size_t server_addrlen, - unsigned short protocol, u32 nfs_version) +struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init) { struct nlm_host *host; - u32 nlm_version = (nfs_version == 2) ? 1 : 4; + u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4; int status; - status = lockd_up(protocol); + status = lockd_up(nlm_init->protocol); if (status < 0) return ERR_PTR(status); - host = nlmclnt_lookup_host((struct sockaddr_in *)server_address, - protocol, nlm_version, - server_name, strlen(server_name)); + host = nlmclnt_lookup_host((struct sockaddr_in *)nlm_init->address, + nlm_init->protocol, nlm_version, + nlm_init->hostname, + strlen(nlm_init->hostname)); if (host == NULL) { lockd_down(); return ERR_PTR(-ENOLCK); diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 0b3ce86f6fc9..7a15832369e9 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -468,18 +468,21 @@ static int nfs_start_lockd(struct nfs_server *server) { struct nlm_host *host; struct nfs_client *clp = server->nfs_client; - u32 nfs_version = clp->rpc_ops->version; - unsigned short protocol = server->flags & NFS_MOUNT_TCP ? - IPPROTO_TCP : IPPROTO_UDP; + struct nlmclnt_initdata nlm_init = { + .hostname = clp->cl_hostname, + .address = (struct sockaddr *)&clp->cl_addr, + .addrlen = clp->cl_addrlen, + .protocol = server->flags & NFS_MOUNT_TCP ? + IPPROTO_TCP : IPPROTO_UDP, + .nfs_version = clp->rpc_ops->version, + }; - if (nfs_version > 3) + if (nlm_init.nfs_version > 3) return 0; if (server->flags & NFS_MOUNT_NONLM) return 0; - host = nlmclnt_init(clp->cl_hostname, - (struct sockaddr *)&clp->cl_addr, - clp->cl_addrlen, protocol, nfs_version); + host = nlmclnt_init(&nlm_init); if (IS_ERR(host)) return PTR_ERR(host); diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h index 73368075af03..3d25bcd139d1 100644 --- a/include/linux/lockd/bind.h +++ b/include/linux/lockd/bind.h @@ -32,14 +32,23 @@ struct nlmsvc_binding { extern struct nlmsvc_binding * nlmsvc_ops; +/* + * Similar to nfs_client_initdata, but without the NFS-specific + * rpc_ops field. + */ +struct nlmclnt_initdata { + const char *hostname; + const struct sockaddr *address; + size_t addrlen; + unsigned short protocol; + u32 nfs_version; +}; + /* * Functions exported by the lockd module */ -extern struct nlm_host *nlmclnt_init(const char *server_name, - const struct sockaddr *server_address, - size_t server_addrlen, - unsigned short protocol, - u32 nfs_version); + +extern struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init); extern void nlmclnt_done(struct nlm_host *host); extern int nlmclnt_proc(struct nlm_host *host, int cmd, -- cgit v1.2.3 From c0e07cb68db353c0ffbb0f82401cf6d79c253aed Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 14 Jan 2008 12:32:05 -0500 Subject: NFS: NFS version number is unsigned RPC protocol version numbers are unsigned. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- include/linux/nfs_xdr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index d342ae5c76ab..f301d0b8babc 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -774,7 +774,7 @@ struct nfs_access_entry; * RPC procedure vector for NFSv2/NFSv3 demuxing */ struct nfs_rpc_ops { - int version; /* Protocol version */ + u32 version; /* Protocol version */ struct dentry_operations *dentry_ops; const struct inode_operations *dir_inode_ops; const struct inode_operations *file_inode_ops; -- cgit v1.2.3 From f1ec08cb9492cab579f85f9d937c79788b1dfde3 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 14 Jan 2008 15:11:53 -0500 Subject: SUNRPC: Use appropriate argument types in rpcb client Clean up: Follow recommendations of Chapter 5 of Documentation/CodingStyle and use "u32" instead of "__u32" for types in definitions that are not shared with user space. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- include/linux/sunrpc/clnt.h | 2 +- net/sunrpc/rpcb_clnt.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 5a13da2573b0..3e9addc741c1 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h @@ -125,7 +125,7 @@ void rpc_shutdown_client(struct rpc_clnt *); void rpc_release_client(struct rpc_clnt *); int rpcb_register(u32, u32, int, unsigned short, int *); -int rpcb_getport_sync(struct sockaddr_in *, __u32, __u32, int); +int rpcb_getport_sync(struct sockaddr_in *, u32, u32, int); void rpcb_getport_async(struct rpc_task *); void rpc_call_start(struct rpc_task *); diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 8962ac6b4c11..77af989ecc9c 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -205,8 +205,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) * * XXX: Needs to support IPv6, and rpcbind versions 3 and 4 */ -int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog, - __u32 vers, int prot) +int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot) { struct rpcbind_args map = { .r_prog = prog, -- cgit v1.2.3 From 3a10c30acc4821ca000b52ed0edafd0d3bf26a52 Mon Sep 17 00:00:00 2001 From: Benny Halevy Date: Wed, 23 Jan 2008 08:58:59 +0200 Subject: nfs: obliterate NFS_FLAGS macro use NFS_I(inode)->flags instead Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 8 ++++---- fs/nfs/inode.c | 6 +++--- fs/nfs/read.c | 2 +- include/linux/nfs_fs.h | 5 ++--- 4 files changed, 10 insertions(+), 11 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 72d141a0dbd8..c578d942f000 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -192,7 +192,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) /* We requested READDIRPLUS, but the server doesn't grok it */ if (error == -ENOTSUPP && desc->plus) { NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS; - clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); + clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); desc->plus = 0; goto again; } @@ -577,7 +577,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) break; } if (res == -ETOOSMALL && desc->plus) { - clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); + clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); nfs_zap_caches(inode); desc->plus = 0; desc->entry->eof = 0; @@ -1760,7 +1760,7 @@ static void __nfs_access_zap_cache(struct inode *inode) void nfs_access_zap_cache(struct inode *inode) { /* Remove from global LRU init */ - if (test_and_clear_bit(NFS_INO_ACL_LRU_SET, &NFS_FLAGS(inode))) { + if (test_and_clear_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags)) { spin_lock(&nfs_access_lru_lock); list_del_init(&NFS_I(inode)->access_cache_inode_lru); spin_unlock(&nfs_access_lru_lock); @@ -1874,7 +1874,7 @@ static void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *s smp_mb__after_atomic_inc(); /* Add inode to global LRU list */ - if (!test_and_set_bit(NFS_INO_ACL_LRU_SET, &NFS_FLAGS(inode))) { + if (!test_and_set_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags)) { spin_lock(&nfs_access_lru_lock); list_add_tail(&NFS_I(inode)->access_cache_inode_lru, &nfs_access_lru_list); spin_unlock(&nfs_access_lru_lock); diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 5747d49bdd76..9d7b08c43865 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -192,7 +192,7 @@ void nfs_invalidate_atime(struct inode *inode) */ static void nfs_invalidate_inode(struct inode *inode) { - set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); + set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); nfs_zap_caches_locked(inode); } @@ -291,7 +291,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) inode->i_fop = &nfs_dir_operations; if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS) && fattr->size <= NFS_LIMIT_READDIRPLUS) - set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); + set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); /* Deal with crossing mountpoints */ if (!nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) { if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) @@ -668,7 +668,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) if (status == -ESTALE) { nfs_zap_caches(inode); if (!S_ISDIR(inode->i_mode)) - set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); + set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); } goto out; } diff --git a/fs/nfs/read.c b/fs/nfs/read.c index efc121c494fe..8fd6dfbe1bc3 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -336,7 +336,7 @@ int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data) nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, data->res.count); if (task->tk_status == -ESTALE) { - set_bit(NFS_INO_STALE, &NFS_FLAGS(data->inode)); + set_bit(NFS_INO_STALE, &NFS_I(data->inode)->flags); nfs_mark_for_revalidate(data->inode); } return 0; diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 7095aaa087d8..9e7c24a2aca9 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -214,8 +214,7 @@ static inline struct nfs_inode *NFS_I(struct inode *inode) (S_ISDIR(inode->i_mode)? NFS_SERVER(inode)->acdirmax \ : NFS_SERVER(inode)->acregmax) -#define NFS_FLAGS(inode) (NFS_I(inode)->flags) -#define NFS_STALE(inode) (test_bit(NFS_INO_STALE, &NFS_FLAGS(inode))) +#define NFS_STALE(inode) (test_bit(NFS_INO_STALE, &NFS_I(inode)->flags)) #define NFS_FILEID(inode) (NFS_I(inode)->fileid) @@ -237,7 +236,7 @@ static inline int nfs_server_capable(struct inode *inode, int cap) static inline int NFS_USE_READDIRPLUS(struct inode *inode) { - return test_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); + return test_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); } static inline void nfs_set_verifier(struct dentry * dentry, unsigned long verf) -- cgit v1.2.3 From 99fadcd76465842c014c88b8c9c19b457e9debc0 Mon Sep 17 00:00:00 2001 From: Benny Halevy Date: Wed, 23 Jan 2008 08:59:08 +0200 Subject: nfs: convert NFS_*(inode) helpers to static inline Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- fs/nfs/inode.c | 2 +- include/linux/nfs_fs.h | 76 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 59 insertions(+), 19 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 9d7b08c43865..5d381cfbfe7e 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -229,7 +229,7 @@ nfs_init_locked(struct inode *inode, void *opaque) struct nfs_find_desc *desc = (struct nfs_find_desc *)opaque; struct nfs_fattr *fattr = desc->fattr; - NFS_FILEID(inode) = fattr->fileid; + set_nfs_fileid(inode, fattr->fileid); nfs_copy_fh(NFS_FH(inode), desc->fh); return 0; } diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 9e7c24a2aca9..099ddb4481c0 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -196,27 +196,67 @@ struct nfs_inode { #define NFS_INO_STALE (2) /* possible stale inode */ #define NFS_INO_ACL_LRU_SET (3) /* Inode is on the LRU list */ -static inline struct nfs_inode *NFS_I(struct inode *inode) +static inline struct nfs_inode *NFS_I(const struct inode *inode) { return container_of(inode, struct nfs_inode, vfs_inode); } -#define NFS_SB(s) ((struct nfs_server *)(s->s_fs_info)) - -#define NFS_FH(inode) (&NFS_I(inode)->fh) -#define NFS_SERVER(inode) (NFS_SB(inode->i_sb)) -#define NFS_CLIENT(inode) (NFS_SERVER(inode)->client) -#define NFS_PROTO(inode) (NFS_SERVER(inode)->nfs_client->rpc_ops) -#define NFS_COOKIEVERF(inode) (NFS_I(inode)->cookieverf) -#define NFS_MINATTRTIMEO(inode) \ - (S_ISDIR(inode->i_mode)? NFS_SERVER(inode)->acdirmin \ - : NFS_SERVER(inode)->acregmin) -#define NFS_MAXATTRTIMEO(inode) \ - (S_ISDIR(inode->i_mode)? NFS_SERVER(inode)->acdirmax \ - : NFS_SERVER(inode)->acregmax) - -#define NFS_STALE(inode) (test_bit(NFS_INO_STALE, &NFS_I(inode)->flags)) - -#define NFS_FILEID(inode) (NFS_I(inode)->fileid) + +static inline struct nfs_server *NFS_SB(const struct super_block *s) +{ + return (struct nfs_server *)(s->s_fs_info); +} + +static inline struct nfs_fh *NFS_FH(const struct inode *inode) +{ + return &NFS_I(inode)->fh; +} + +static inline struct nfs_server *NFS_SERVER(const struct inode *inode) +{ + return NFS_SB(inode->i_sb); +} + +static inline struct rpc_clnt *NFS_CLIENT(const struct inode *inode) +{ + return NFS_SERVER(inode)->client; +} + +static inline const struct nfs_rpc_ops *NFS_PROTO(const struct inode *inode) +{ + return NFS_SERVER(inode)->nfs_client->rpc_ops; +} + +static inline __be32 *NFS_COOKIEVERF(const struct inode *inode) +{ + return NFS_I(inode)->cookieverf; +} + +static inline unsigned NFS_MINATTRTIMEO(const struct inode *inode) +{ + struct nfs_server *nfss = NFS_SERVER(inode); + return S_ISDIR(inode->i_mode) ? nfss->acdirmin : nfss->acregmin; +} + +static inline unsigned NFS_MAXATTRTIMEO(const struct inode *inode) +{ + struct nfs_server *nfss = NFS_SERVER(inode); + return S_ISDIR(inode->i_mode) ? nfss->acdirmax : nfss->acregmax; +} + +static inline int NFS_STALE(const struct inode *inode) +{ + return test_bit(NFS_INO_STALE, &NFS_I(inode)->flags); +} + +static inline __u64 NFS_FILEID(const struct inode *inode) +{ + return NFS_I(inode)->fileid; +} + +static inline void set_nfs_fileid(struct inode *inode, __u64 fileid) +{ + NFS_I(inode)->fileid = fileid; +} static inline void nfs_mark_for_revalidate(struct inode *inode) { -- cgit v1.2.3