diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-23 11:53:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-23 11:53:47 -0400 |
commit | f63d395d47f37a4fe771e6d4b1db9d2cdae5ffc5 (patch) | |
tree | 3448a14ae965802adb963762cadeb9989ce4caa2 /fs/nfs/callback_proc.c | |
parent | 643ac9fc5429e85b8b7f534544b80bcc4f34c367 (diff) | |
parent | 5a7c9eec9fde1da0e3adf0a4ddb64ff2a324a492 (diff) |
Merge tag 'nfs-for-3.4-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates for Linux 3.4 from Trond Myklebust:
"New features include:
- Add NFS client support for containers.
This should enable most of the necessary functionality, including
lockd support, and support for rpc.statd, NFSv4 idmapper and
RPCSEC_GSS upcalls into the correct network namespace from which
the mount system call was issued.
- NFSv4 idmapper scalability improvements
Base the idmapper cache on the keyring interface to allow
concurrent access to idmapper entries. Start the process of
migrating users from the single-threaded daemon-based approach to
the multi-threaded request-key based approach.
- NFSv4.1 implementation id.
Allows the NFSv4.1 client and server to mutually identify each
other for logging and debugging purposes.
- Support the 'vers=4.1' mount option for mounting NFSv4.1 instead of
having to use the more counterintuitive 'vers=4,minorversion=1'.
- SUNRPC tracepoints.
Start the process of adding tracepoints in order to improve
debugging of the RPC layer.
- pNFS object layout support for autologin.
Important bugfixes include:
- Fix a bug in rpc_wake_up/rpc_wake_up_status that caused them to
fail to wake up all tasks when applied to priority waitqueues.
- Ensure that we handle read delegations correctly, when we try to
truncate a file.
- A number of fixes for NFSv4 state manager loops (mostly to do with
delegation recovery)."
* tag 'nfs-for-3.4-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (224 commits)
NFS: fix sb->s_id in nfs debug prints
xprtrdma: Remove assumption that each segment is <= PAGE_SIZE
xprtrdma: The transport should not bug-check when a dup reply is received
pnfs-obj: autologin: Add support for protocol autologin
NFS: Remove nfs4_setup_sequence from generic rename code
NFS: Remove nfs4_setup_sequence from generic unlink code
NFS: Remove nfs4_setup_sequence from generic read code
NFS: Remove nfs4_setup_sequence from generic write code
NFS: Fix more NFS debug related build warnings
SUNRPC/LOCKD: Fix build warnings when CONFIG_SUNRPC_DEBUG is undefined
nfs: non void functions must return a value
SUNRPC: Kill compiler warning when RPC_DEBUG is unset
SUNRPC/NFS: Add Kbuild dependencies for NFS_DEBUG/RPC_DEBUG
NFS: Use cond_resched_lock() to reduce latencies in the commit scans
NFSv4: It is not safe to dereference lsp->ls_state in release_lockowner
NFS: ncommit count is being double decremented
SUNRPC: We must not use list_for_each_entry_safe() in rpc_wake_up()
Try using machine credentials for RENEW calls
NFSv4.1: Fix a few issues in filelayout_commit_pagelist
NFSv4.1: Clean ups and bugfixes for the pNFS read/writeback/commit code
...
Diffstat (limited to 'fs/nfs/callback_proc.c')
-rw-r--r-- | fs/nfs/callback_proc.c | 99 |
1 files changed, 46 insertions, 53 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 54cea8ad5a7..1b5d809a105 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/nfs4.h> | 8 | #include <linux/nfs4.h> |
9 | #include <linux/nfs_fs.h> | 9 | #include <linux/nfs_fs.h> |
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
11 | #include <linux/rcupdate.h> | ||
11 | #include "nfs4_fs.h" | 12 | #include "nfs4_fs.h" |
12 | #include "callback.h" | 13 | #include "callback.h" |
13 | #include "delegation.h" | 14 | #include "delegation.h" |
@@ -33,7 +34,7 @@ __be32 nfs4_callback_getattr(struct cb_getattrargs *args, | |||
33 | res->bitmap[0] = res->bitmap[1] = 0; | 34 | res->bitmap[0] = res->bitmap[1] = 0; |
34 | res->status = htonl(NFS4ERR_BADHANDLE); | 35 | res->status = htonl(NFS4ERR_BADHANDLE); |
35 | 36 | ||
36 | dprintk("NFS: GETATTR callback request from %s\n", | 37 | dprintk_rcu("NFS: GETATTR callback request from %s\n", |
37 | rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR)); | 38 | rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR)); |
38 | 39 | ||
39 | inode = nfs_delegation_find_inode(cps->clp, &args->fh); | 40 | inode = nfs_delegation_find_inode(cps->clp, &args->fh); |
@@ -73,7 +74,7 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy, | |||
73 | if (!cps->clp) /* Always set for v4.0. Set in cb_sequence for v4.1 */ | 74 | if (!cps->clp) /* Always set for v4.0. Set in cb_sequence for v4.1 */ |
74 | goto out; | 75 | goto out; |
75 | 76 | ||
76 | dprintk("NFS: RECALL callback request from %s\n", | 77 | dprintk_rcu("NFS: RECALL callback request from %s\n", |
77 | rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR)); | 78 | rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR)); |
78 | 79 | ||
79 | res = htonl(NFS4ERR_BADHANDLE); | 80 | res = htonl(NFS4ERR_BADHANDLE); |
@@ -86,8 +87,7 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy, | |||
86 | res = 0; | 87 | res = 0; |
87 | break; | 88 | break; |
88 | case -ENOENT: | 89 | case -ENOENT: |
89 | if (res != 0) | 90 | res = htonl(NFS4ERR_BAD_STATEID); |
90 | res = htonl(NFS4ERR_BAD_STATEID); | ||
91 | break; | 91 | break; |
92 | default: | 92 | default: |
93 | res = htonl(NFS4ERR_RESOURCE); | 93 | res = htonl(NFS4ERR_RESOURCE); |
@@ -98,52 +98,64 @@ out: | |||
98 | return res; | 98 | return res; |
99 | } | 99 | } |
100 | 100 | ||
101 | int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid) | ||
102 | { | ||
103 | if (delegation == NULL || memcmp(delegation->stateid.data, stateid->data, | ||
104 | sizeof(delegation->stateid.data)) != 0) | ||
105 | return 0; | ||
106 | return 1; | ||
107 | } | ||
108 | |||
109 | #if defined(CONFIG_NFS_V4_1) | 101 | #if defined(CONFIG_NFS_V4_1) |
110 | 102 | ||
111 | static u32 initiate_file_draining(struct nfs_client *clp, | 103 | /* |
112 | struct cb_layoutrecallargs *args) | 104 | * Lookup a layout by filehandle. |
105 | * | ||
106 | * Note: gets a refcount on the layout hdr and on its respective inode. | ||
107 | * Caller must put the layout hdr and the inode. | ||
108 | * | ||
109 | * TODO: keep track of all layouts (and delegations) in a hash table | ||
110 | * hashed by filehandle. | ||
111 | */ | ||
112 | static struct pnfs_layout_hdr * get_layout_by_fh_locked(struct nfs_client *clp, struct nfs_fh *fh) | ||
113 | { | 113 | { |
114 | struct nfs_server *server; | 114 | struct nfs_server *server; |
115 | struct pnfs_layout_hdr *lo; | ||
116 | struct inode *ino; | 115 | struct inode *ino; |
117 | bool found = false; | 116 | struct pnfs_layout_hdr *lo; |
118 | u32 rv = NFS4ERR_NOMATCHING_LAYOUT; | ||
119 | LIST_HEAD(free_me_list); | ||
120 | 117 | ||
121 | spin_lock(&clp->cl_lock); | ||
122 | rcu_read_lock(); | ||
123 | list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { | 118 | list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { |
124 | list_for_each_entry(lo, &server->layouts, plh_layouts) { | 119 | list_for_each_entry(lo, &server->layouts, plh_layouts) { |
125 | if (nfs_compare_fh(&args->cbl_fh, | 120 | if (nfs_compare_fh(fh, &NFS_I(lo->plh_inode)->fh)) |
126 | &NFS_I(lo->plh_inode)->fh)) | ||
127 | continue; | 121 | continue; |
128 | ino = igrab(lo->plh_inode); | 122 | ino = igrab(lo->plh_inode); |
129 | if (!ino) | 123 | if (!ino) |
130 | continue; | 124 | continue; |
131 | found = true; | ||
132 | /* Without this, layout can be freed as soon | ||
133 | * as we release cl_lock. | ||
134 | */ | ||
135 | get_layout_hdr(lo); | 125 | get_layout_hdr(lo); |
136 | break; | 126 | return lo; |
137 | } | 127 | } |
138 | if (found) | ||
139 | break; | ||
140 | } | 128 | } |
129 | |||
130 | return NULL; | ||
131 | } | ||
132 | |||
133 | static struct pnfs_layout_hdr * get_layout_by_fh(struct nfs_client *clp, struct nfs_fh *fh) | ||
134 | { | ||
135 | struct pnfs_layout_hdr *lo; | ||
136 | |||
137 | spin_lock(&clp->cl_lock); | ||
138 | rcu_read_lock(); | ||
139 | lo = get_layout_by_fh_locked(clp, fh); | ||
141 | rcu_read_unlock(); | 140 | rcu_read_unlock(); |
142 | spin_unlock(&clp->cl_lock); | 141 | spin_unlock(&clp->cl_lock); |
143 | 142 | ||
144 | if (!found) | 143 | return lo; |
144 | } | ||
145 | |||
146 | static u32 initiate_file_draining(struct nfs_client *clp, | ||
147 | struct cb_layoutrecallargs *args) | ||
148 | { | ||
149 | struct inode *ino; | ||
150 | struct pnfs_layout_hdr *lo; | ||
151 | u32 rv = NFS4ERR_NOMATCHING_LAYOUT; | ||
152 | LIST_HEAD(free_me_list); | ||
153 | |||
154 | lo = get_layout_by_fh(clp, &args->cbl_fh); | ||
155 | if (!lo) | ||
145 | return NFS4ERR_NOMATCHING_LAYOUT; | 156 | return NFS4ERR_NOMATCHING_LAYOUT; |
146 | 157 | ||
158 | ino = lo->plh_inode; | ||
147 | spin_lock(&ino->i_lock); | 159 | spin_lock(&ino->i_lock); |
148 | if (test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags) || | 160 | if (test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags) || |
149 | mark_matching_lsegs_invalid(lo, &free_me_list, | 161 | mark_matching_lsegs_invalid(lo, &free_me_list, |
@@ -213,17 +225,13 @@ static u32 initiate_bulk_draining(struct nfs_client *clp, | |||
213 | static u32 do_callback_layoutrecall(struct nfs_client *clp, | 225 | static u32 do_callback_layoutrecall(struct nfs_client *clp, |
214 | struct cb_layoutrecallargs *args) | 226 | struct cb_layoutrecallargs *args) |
215 | { | 227 | { |
216 | u32 res = NFS4ERR_DELAY; | 228 | u32 res; |
217 | 229 | ||
218 | dprintk("%s enter, type=%i\n", __func__, args->cbl_recall_type); | 230 | dprintk("%s enter, type=%i\n", __func__, args->cbl_recall_type); |
219 | if (test_and_set_bit(NFS4CLNT_LAYOUTRECALL, &clp->cl_state)) | ||
220 | goto out; | ||
221 | if (args->cbl_recall_type == RETURN_FILE) | 231 | if (args->cbl_recall_type == RETURN_FILE) |
222 | res = initiate_file_draining(clp, args); | 232 | res = initiate_file_draining(clp, args); |
223 | else | 233 | else |
224 | res = initiate_bulk_draining(clp, args); | 234 | res = initiate_bulk_draining(clp, args); |
225 | clear_bit(NFS4CLNT_LAYOUTRECALL, &clp->cl_state); | ||
226 | out: | ||
227 | dprintk("%s returning %i\n", __func__, res); | 235 | dprintk("%s returning %i\n", __func__, res); |
228 | return res; | 236 | return res; |
229 | 237 | ||
@@ -303,21 +311,6 @@ out: | |||
303 | return res; | 311 | return res; |
304 | } | 312 | } |
305 | 313 | ||
306 | int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid) | ||
307 | { | ||
308 | if (delegation == NULL) | ||
309 | return 0; | ||
310 | |||
311 | if (stateid->stateid.seqid != 0) | ||
312 | return 0; | ||
313 | if (memcmp(&delegation->stateid.stateid.other, | ||
314 | &stateid->stateid.other, | ||
315 | NFS4_STATEID_OTHER_SIZE)) | ||
316 | return 0; | ||
317 | |||
318 | return 1; | ||
319 | } | ||
320 | |||
321 | /* | 314 | /* |
322 | * Validate the sequenceID sent by the server. | 315 | * Validate the sequenceID sent by the server. |
323 | * Return success if the sequenceID is one more than what we last saw on | 316 | * Return success if the sequenceID is one more than what we last saw on |
@@ -441,7 +434,7 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args, | |||
441 | int i; | 434 | int i; |
442 | __be32 status = htonl(NFS4ERR_BADSESSION); | 435 | __be32 status = htonl(NFS4ERR_BADSESSION); |
443 | 436 | ||
444 | clp = nfs4_find_client_sessionid(args->csa_addr, &args->csa_sessionid); | 437 | clp = nfs4_find_client_sessionid(cps->net, args->csa_addr, &args->csa_sessionid); |
445 | if (clp == NULL) | 438 | if (clp == NULL) |
446 | goto out; | 439 | goto out; |
447 | 440 | ||
@@ -517,7 +510,7 @@ __be32 nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy, | |||
517 | if (!cps->clp) /* set in cb_sequence */ | 510 | if (!cps->clp) /* set in cb_sequence */ |
518 | goto out; | 511 | goto out; |
519 | 512 | ||
520 | dprintk("NFS: RECALL_ANY callback request from %s\n", | 513 | dprintk_rcu("NFS: RECALL_ANY callback request from %s\n", |
521 | rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR)); | 514 | rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR)); |
522 | 515 | ||
523 | status = cpu_to_be32(NFS4ERR_INVAL); | 516 | status = cpu_to_be32(NFS4ERR_INVAL); |
@@ -552,7 +545,7 @@ __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy, | |||
552 | if (!cps->clp) /* set in cb_sequence */ | 545 | if (!cps->clp) /* set in cb_sequence */ |
553 | goto out; | 546 | goto out; |
554 | 547 | ||
555 | dprintk("NFS: CB_RECALL_SLOT request from %s target max slots %d\n", | 548 | dprintk_rcu("NFS: CB_RECALL_SLOT request from %s target max slots %d\n", |
556 | rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR), | 549 | rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR), |
557 | args->crsa_target_max_slots); | 550 | args->crsa_target_max_slots); |
558 | 551 | ||