diff options
52 files changed, 1335 insertions, 1174 deletions
diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c index 13ad1539fbf..00ec0b9c94d 100644 --- a/fs/lockd/clnt4xdr.c +++ b/fs/lockd/clnt4xdr.c | |||
@@ -64,10 +64,6 @@ static void nlm4_compute_offsets(const struct nlm_lock *lock, | |||
64 | { | 64 | { |
65 | const struct file_lock *fl = &lock->fl; | 65 | const struct file_lock *fl = &lock->fl; |
66 | 66 | ||
67 | BUG_ON(fl->fl_start > NLM4_OFFSET_MAX); | ||
68 | BUG_ON(fl->fl_end > NLM4_OFFSET_MAX && | ||
69 | fl->fl_end != OFFSET_MAX); | ||
70 | |||
71 | *l_offset = loff_t_to_s64(fl->fl_start); | 67 | *l_offset = loff_t_to_s64(fl->fl_start); |
72 | if (fl->fl_end == OFFSET_MAX) | 68 | if (fl->fl_end == OFFSET_MAX) |
73 | *l_len = 0; | 69 | *l_len = 0; |
@@ -122,7 +118,6 @@ static void encode_netobj(struct xdr_stream *xdr, | |||
122 | { | 118 | { |
123 | __be32 *p; | 119 | __be32 *p; |
124 | 120 | ||
125 | BUG_ON(length > XDR_MAX_NETOBJ); | ||
126 | p = xdr_reserve_space(xdr, 4 + length); | 121 | p = xdr_reserve_space(xdr, 4 + length); |
127 | xdr_encode_opaque(p, data, length); | 122 | xdr_encode_opaque(p, data, length); |
128 | } | 123 | } |
@@ -156,7 +151,6 @@ out_overflow: | |||
156 | static void encode_cookie(struct xdr_stream *xdr, | 151 | static void encode_cookie(struct xdr_stream *xdr, |
157 | const struct nlm_cookie *cookie) | 152 | const struct nlm_cookie *cookie) |
158 | { | 153 | { |
159 | BUG_ON(cookie->len > NLM_MAXCOOKIELEN); | ||
160 | encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); | 154 | encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); |
161 | } | 155 | } |
162 | 156 | ||
@@ -198,7 +192,6 @@ out_overflow: | |||
198 | */ | 192 | */ |
199 | static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) | 193 | static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) |
200 | { | 194 | { |
201 | BUG_ON(fh->size > NFS3_FHSIZE); | ||
202 | encode_netobj(xdr, (u8 *)&fh->data, fh->size); | 195 | encode_netobj(xdr, (u8 *)&fh->data, fh->size); |
203 | } | 196 | } |
204 | 197 | ||
@@ -336,7 +329,6 @@ static void encode_caller_name(struct xdr_stream *xdr, const char *name) | |||
336 | u32 length = strlen(name); | 329 | u32 length = strlen(name); |
337 | __be32 *p; | 330 | __be32 *p; |
338 | 331 | ||
339 | BUG_ON(length > NLM_MAXSTRLEN); | ||
340 | p = xdr_reserve_space(xdr, 4 + length); | 332 | p = xdr_reserve_space(xdr, 4 + length); |
341 | xdr_encode_opaque(p, name, length); | 333 | xdr_encode_opaque(p, name, length); |
342 | } | 334 | } |
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 05d29124c6a..54f9e6ce043 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
@@ -141,7 +141,7 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl) | |||
141 | 141 | ||
142 | static void nlmclnt_release_lockargs(struct nlm_rqst *req) | 142 | static void nlmclnt_release_lockargs(struct nlm_rqst *req) |
143 | { | 143 | { |
144 | BUG_ON(req->a_args.lock.fl.fl_ops != NULL); | 144 | WARN_ON_ONCE(req->a_args.lock.fl.fl_ops != NULL); |
145 | } | 145 | } |
146 | 146 | ||
147 | /** | 147 | /** |
@@ -465,7 +465,6 @@ static const struct file_lock_operations nlmclnt_lock_ops = { | |||
465 | 465 | ||
466 | static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host) | 466 | static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host) |
467 | { | 467 | { |
468 | BUG_ON(fl->fl_ops != NULL); | ||
469 | fl->fl_u.nfs_fl.state = 0; | 468 | fl->fl_u.nfs_fl.state = 0; |
470 | fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner); | 469 | fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner); |
471 | INIT_LIST_HEAD(&fl->fl_u.nfs_fl.list); | 470 | INIT_LIST_HEAD(&fl->fl_u.nfs_fl.list); |
diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c index 982d2676e1f..9a55797a1cd 100644 --- a/fs/lockd/clntxdr.c +++ b/fs/lockd/clntxdr.c | |||
@@ -60,10 +60,6 @@ static void nlm_compute_offsets(const struct nlm_lock *lock, | |||
60 | { | 60 | { |
61 | const struct file_lock *fl = &lock->fl; | 61 | const struct file_lock *fl = &lock->fl; |
62 | 62 | ||
63 | BUG_ON(fl->fl_start > NLM_OFFSET_MAX); | ||
64 | BUG_ON(fl->fl_end > NLM_OFFSET_MAX && | ||
65 | fl->fl_end != OFFSET_MAX); | ||
66 | |||
67 | *l_offset = loff_t_to_s32(fl->fl_start); | 63 | *l_offset = loff_t_to_s32(fl->fl_start); |
68 | if (fl->fl_end == OFFSET_MAX) | 64 | if (fl->fl_end == OFFSET_MAX) |
69 | *l_len = 0; | 65 | *l_len = 0; |
@@ -119,7 +115,6 @@ static void encode_netobj(struct xdr_stream *xdr, | |||
119 | { | 115 | { |
120 | __be32 *p; | 116 | __be32 *p; |
121 | 117 | ||
122 | BUG_ON(length > XDR_MAX_NETOBJ); | ||
123 | p = xdr_reserve_space(xdr, 4 + length); | 118 | p = xdr_reserve_space(xdr, 4 + length); |
124 | xdr_encode_opaque(p, data, length); | 119 | xdr_encode_opaque(p, data, length); |
125 | } | 120 | } |
@@ -153,7 +148,6 @@ out_overflow: | |||
153 | static void encode_cookie(struct xdr_stream *xdr, | 148 | static void encode_cookie(struct xdr_stream *xdr, |
154 | const struct nlm_cookie *cookie) | 149 | const struct nlm_cookie *cookie) |
155 | { | 150 | { |
156 | BUG_ON(cookie->len > NLM_MAXCOOKIELEN); | ||
157 | encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); | 151 | encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); |
158 | } | 152 | } |
159 | 153 | ||
@@ -195,7 +189,6 @@ out_overflow: | |||
195 | */ | 189 | */ |
196 | static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) | 190 | static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) |
197 | { | 191 | { |
198 | BUG_ON(fh->size != NFS2_FHSIZE); | ||
199 | encode_netobj(xdr, (u8 *)&fh->data, NFS2_FHSIZE); | 192 | encode_netobj(xdr, (u8 *)&fh->data, NFS2_FHSIZE); |
200 | } | 193 | } |
201 | 194 | ||
@@ -330,7 +323,6 @@ static void encode_caller_name(struct xdr_stream *xdr, const char *name) | |||
330 | u32 length = strlen(name); | 323 | u32 length = strlen(name); |
331 | __be32 *p; | 324 | __be32 *p; |
332 | 325 | ||
333 | BUG_ON(length > NLM_MAXSTRLEN); | ||
334 | p = xdr_reserve_space(xdr, 4 + length); | 326 | p = xdr_reserve_space(xdr, 4 + length); |
335 | xdr_encode_opaque(p, name, length); | 327 | xdr_encode_opaque(p, name, length); |
336 | } | 328 | } |
diff --git a/fs/lockd/host.c b/fs/lockd/host.c index f9b22e58f78..0e17090c310 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c | |||
@@ -177,9 +177,6 @@ static void nlm_destroy_host_locked(struct nlm_host *host) | |||
177 | 177 | ||
178 | dprintk("lockd: destroy host %s\n", host->h_name); | 178 | dprintk("lockd: destroy host %s\n", host->h_name); |
179 | 179 | ||
180 | BUG_ON(!list_empty(&host->h_lockowners)); | ||
181 | BUG_ON(atomic_read(&host->h_count)); | ||
182 | |||
183 | hlist_del_init(&host->h_hash); | 180 | hlist_del_init(&host->h_hash); |
184 | 181 | ||
185 | nsm_unmonitor(host); | 182 | nsm_unmonitor(host); |
@@ -289,13 +286,12 @@ void nlmclnt_release_host(struct nlm_host *host) | |||
289 | 286 | ||
290 | dprintk("lockd: release client host %s\n", host->h_name); | 287 | dprintk("lockd: release client host %s\n", host->h_name); |
291 | 288 | ||
292 | BUG_ON(atomic_read(&host->h_count) < 0); | 289 | WARN_ON_ONCE(host->h_server); |
293 | BUG_ON(host->h_server); | ||
294 | 290 | ||
295 | if (atomic_dec_and_test(&host->h_count)) { | 291 | if (atomic_dec_and_test(&host->h_count)) { |
296 | BUG_ON(!list_empty(&host->h_lockowners)); | 292 | WARN_ON_ONCE(!list_empty(&host->h_lockowners)); |
297 | BUG_ON(!list_empty(&host->h_granted)); | 293 | WARN_ON_ONCE(!list_empty(&host->h_granted)); |
298 | BUG_ON(!list_empty(&host->h_reclaim)); | 294 | WARN_ON_ONCE(!list_empty(&host->h_reclaim)); |
299 | 295 | ||
300 | mutex_lock(&nlm_host_mutex); | 296 | mutex_lock(&nlm_host_mutex); |
301 | nlm_destroy_host_locked(host); | 297 | nlm_destroy_host_locked(host); |
@@ -412,8 +408,7 @@ void nlmsvc_release_host(struct nlm_host *host) | |||
412 | 408 | ||
413 | dprintk("lockd: release server host %s\n", host->h_name); | 409 | dprintk("lockd: release server host %s\n", host->h_name); |
414 | 410 | ||
415 | BUG_ON(atomic_read(&host->h_count) < 0); | 411 | WARN_ON_ONCE(!host->h_server); |
416 | BUG_ON(!host->h_server); | ||
417 | atomic_dec(&host->h_count); | 412 | atomic_dec(&host->h_count); |
418 | } | 413 | } |
419 | 414 | ||
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 3d7e09bcc0e..3c2cfc68363 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c | |||
@@ -154,8 +154,6 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, | |||
154 | .rpc_resp = res, | 154 | .rpc_resp = res, |
155 | }; | 155 | }; |
156 | 156 | ||
157 | BUG_ON(clnt == NULL); | ||
158 | |||
159 | memset(res, 0, sizeof(*res)); | 157 | memset(res, 0, sizeof(*res)); |
160 | 158 | ||
161 | msg.rpc_proc = &clnt->cl_procinfo[proc]; | 159 | msg.rpc_proc = &clnt->cl_procinfo[proc]; |
@@ -466,7 +464,6 @@ static void encode_nsm_string(struct xdr_stream *xdr, const char *string) | |||
466 | const u32 len = strlen(string); | 464 | const u32 len = strlen(string); |
467 | __be32 *p; | 465 | __be32 *p; |
468 | 466 | ||
469 | BUG_ON(len > SM_MAXSTRLEN); | ||
470 | p = xdr_reserve_space(xdr, 4 + len); | 467 | p = xdr_reserve_space(xdr, 4 + len); |
471 | xdr_encode_opaque(p, string, len); | 468 | xdr_encode_opaque(p, string, len); |
472 | } | 469 | } |
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index b7db60897f9..cce2c057bd2 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile | |||
@@ -24,7 +24,7 @@ nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o | |||
24 | delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ | 24 | delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ |
25 | nfs4namespace.o nfs4getroot.o nfs4client.o | 25 | nfs4namespace.o nfs4getroot.o nfs4client.o |
26 | nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o | 26 | nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o |
27 | nfsv4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o | 27 | nfsv4-$(CONFIG_NFS_V4_1) += nfs4session.o pnfs.o pnfs_dev.o |
28 | 28 | ||
29 | obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o | 29 | obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o |
30 | nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o | 30 | nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o |
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index f1027b06a1a..4fa788c93f4 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/pagevec.h> | 40 | #include <linux/pagevec.h> |
41 | 41 | ||
42 | #include "../pnfs.h" | 42 | #include "../pnfs.h" |
43 | #include "../nfs4session.h" | ||
43 | #include "../internal.h" | 44 | #include "../internal.h" |
44 | #include "blocklayout.h" | 45 | #include "blocklayout.h" |
45 | 46 | ||
diff --git a/fs/nfs/cache_lib.c b/fs/nfs/cache_lib.c index dded2636811..862a2f16db6 100644 --- a/fs/nfs/cache_lib.c +++ b/fs/nfs/cache_lib.c | |||
@@ -118,7 +118,6 @@ int nfs_cache_register_sb(struct super_block *sb, struct cache_detail *cd) | |||
118 | struct dentry *dir; | 118 | struct dentry *dir; |
119 | 119 | ||
120 | dir = rpc_d_lookup_sb(sb, "cache"); | 120 | dir = rpc_d_lookup_sb(sb, "cache"); |
121 | BUG_ON(dir == NULL); | ||
122 | ret = sunrpc_cache_register_pipefs(dir, cd->name, 0600, cd); | 121 | ret = sunrpc_cache_register_pipefs(dir, cd->name, 0600, cd); |
123 | dput(dir); | 122 | dput(dir); |
124 | return ret; | 123 | return ret; |
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index 4251c2ae06a..efd54f0a4c4 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h | |||
@@ -142,7 +142,7 @@ extern __be32 nfs4_callback_recallany(struct cb_recallanyargs *args, | |||
142 | 142 | ||
143 | struct cb_recallslotargs { | 143 | struct cb_recallslotargs { |
144 | struct sockaddr *crsa_addr; | 144 | struct sockaddr *crsa_addr; |
145 | uint32_t crsa_target_max_slots; | 145 | uint32_t crsa_target_highest_slotid; |
146 | }; | 146 | }; |
147 | extern __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, | 147 | extern __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, |
148 | void *dummy, | 148 | void *dummy, |
@@ -167,8 +167,6 @@ extern __be32 nfs4_callback_layoutrecall( | |||
167 | struct cb_layoutrecallargs *args, | 167 | struct cb_layoutrecallargs *args, |
168 | void *dummy, struct cb_process_state *cps); | 168 | void *dummy, struct cb_process_state *cps); |
169 | 169 | ||
170 | extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses); | ||
171 | |||
172 | struct cb_devicenotifyitem { | 170 | struct cb_devicenotifyitem { |
173 | uint32_t cbd_notify_type; | 171 | uint32_t cbd_notify_type; |
174 | uint32_t cbd_layout_type; | 172 | uint32_t cbd_layout_type; |
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 76b4a7a3e55..c89b26bc975 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include "delegation.h" | 14 | #include "delegation.h" |
15 | #include "internal.h" | 15 | #include "internal.h" |
16 | #include "pnfs.h" | 16 | #include "pnfs.h" |
17 | #include "nfs4session.h" | ||
17 | 18 | ||
18 | #ifdef NFS_DEBUG | 19 | #ifdef NFS_DEBUG |
19 | #define NFSDBG_FACILITY NFSDBG_CALLBACK | 20 | #define NFSDBG_FACILITY NFSDBG_CALLBACK |
@@ -216,7 +217,6 @@ static u32 initiate_bulk_draining(struct nfs_client *clp, | |||
216 | } | 217 | } |
217 | pnfs_get_layout_hdr(lo); | 218 | pnfs_get_layout_hdr(lo); |
218 | spin_unlock(&ino->i_lock); | 219 | spin_unlock(&ino->i_lock); |
219 | BUG_ON(!list_empty(&lo->plh_bulk_recall)); | ||
220 | list_add(&lo->plh_bulk_recall, &recall_list); | 220 | list_add(&lo->plh_bulk_recall, &recall_list); |
221 | } | 221 | } |
222 | } | 222 | } |
@@ -562,23 +562,16 @@ __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy, | |||
562 | if (!cps->clp) /* set in cb_sequence */ | 562 | if (!cps->clp) /* set in cb_sequence */ |
563 | goto out; | 563 | goto out; |
564 | 564 | ||
565 | dprintk_rcu("NFS: CB_RECALL_SLOT request from %s target max slots %d\n", | 565 | dprintk_rcu("NFS: CB_RECALL_SLOT request from %s target highest slotid %d\n", |
566 | rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR), | 566 | rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR), |
567 | args->crsa_target_max_slots); | 567 | args->crsa_target_highest_slotid); |
568 | 568 | ||
569 | fc_tbl = &cps->clp->cl_session->fc_slot_table; | 569 | fc_tbl = &cps->clp->cl_session->fc_slot_table; |
570 | 570 | ||
571 | status = htonl(NFS4ERR_BAD_HIGH_SLOT); | ||
572 | if (args->crsa_target_max_slots > fc_tbl->max_slots || | ||
573 | args->crsa_target_max_slots < 1) | ||
574 | goto out; | ||
575 | |||
576 | status = htonl(NFS4_OK); | 571 | status = htonl(NFS4_OK); |
577 | if (args->crsa_target_max_slots == fc_tbl->max_slots) | ||
578 | goto out; | ||
579 | 572 | ||
580 | fc_tbl->target_max_slots = args->crsa_target_max_slots; | 573 | nfs41_set_target_slotid(fc_tbl, args->crsa_target_highest_slotid); |
581 | nfs41_handle_recall_slot(cps->clp); | 574 | nfs41_server_notify_target_slotid_update(cps->clp); |
582 | out: | 575 | out: |
583 | dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); | 576 | dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); |
584 | return status; | 577 | return status; |
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index 742ff4ffced..59461c957d9 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "nfs4_fs.h" | 16 | #include "nfs4_fs.h" |
17 | #include "callback.h" | 17 | #include "callback.h" |
18 | #include "internal.h" | 18 | #include "internal.h" |
19 | #include "nfs4session.h" | ||
19 | 20 | ||
20 | #define CB_OP_TAGLEN_MAXSZ (512) | 21 | #define CB_OP_TAGLEN_MAXSZ (512) |
21 | #define CB_OP_HDR_RES_MAXSZ (2 + CB_OP_TAGLEN_MAXSZ) | 22 | #define CB_OP_HDR_RES_MAXSZ (2 + CB_OP_TAGLEN_MAXSZ) |
@@ -520,7 +521,7 @@ static __be32 decode_recallslot_args(struct svc_rqst *rqstp, | |||
520 | p = read_buf(xdr, 4); | 521 | p = read_buf(xdr, 4); |
521 | if (unlikely(p == NULL)) | 522 | if (unlikely(p == NULL)) |
522 | return htonl(NFS4ERR_BADXDR); | 523 | return htonl(NFS4ERR_BADXDR); |
523 | args->crsa_target_max_slots = ntohl(*p++); | 524 | args->crsa_target_highest_slotid = ntohl(*p++); |
524 | return 0; | 525 | return 0; |
525 | } | 526 | } |
526 | 527 | ||
@@ -762,7 +763,7 @@ static void nfs4_callback_free_slot(struct nfs4_session *session) | |||
762 | * A single slot, so highest used slotid is either 0 or -1 | 763 | * A single slot, so highest used slotid is either 0 or -1 |
763 | */ | 764 | */ |
764 | tbl->highest_used_slotid = NFS4_NO_SLOT; | 765 | tbl->highest_used_slotid = NFS4_NO_SLOT; |
765 | nfs4_check_drain_bc_complete(session); | 766 | nfs4_session_drain_complete(session, tbl); |
766 | spin_unlock(&tbl->slot_tbl_lock); | 767 | spin_unlock(&tbl->slot_tbl_lock); |
767 | } | 768 | } |
768 | 769 | ||
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 8b39a42ac35..9f3c66438d0 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -277,7 +277,7 @@ void nfs_put_client(struct nfs_client *clp) | |||
277 | nfs_cb_idr_remove_locked(clp); | 277 | nfs_cb_idr_remove_locked(clp); |
278 | spin_unlock(&nn->nfs_client_lock); | 278 | spin_unlock(&nn->nfs_client_lock); |
279 | 279 | ||
280 | BUG_ON(!list_empty(&clp->cl_superblocks)); | 280 | WARN_ON_ONCE(!list_empty(&clp->cl_superblocks)); |
281 | 281 | ||
282 | clp->rpc_ops->free_client(clp); | 282 | clp->rpc_ops->free_client(clp); |
283 | } | 283 | } |
@@ -615,8 +615,7 @@ EXPORT_SYMBOL_GPL(nfs_create_rpc_client); | |||
615 | */ | 615 | */ |
616 | static void nfs_destroy_server(struct nfs_server *server) | 616 | static void nfs_destroy_server(struct nfs_server *server) |
617 | { | 617 | { |
618 | if (!(server->flags & NFS_MOUNT_LOCAL_FLOCK) || | 618 | if (server->nlm_host) |
619 | !(server->flags & NFS_MOUNT_LOCAL_FCNTL)) | ||
620 | nlmclnt_done(server->nlm_host); | 619 | nlmclnt_done(server->nlm_host); |
621 | } | 620 | } |
622 | 621 | ||
@@ -1061,10 +1060,6 @@ struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info, | |||
1061 | if (error < 0) | 1060 | if (error < 0) |
1062 | goto error; | 1061 | goto error; |
1063 | 1062 | ||
1064 | BUG_ON(!server->nfs_client); | ||
1065 | BUG_ON(!server->nfs_client->rpc_ops); | ||
1066 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | ||
1067 | |||
1068 | /* Probe the root fh to retrieve its FSID */ | 1063 | /* Probe the root fh to retrieve its FSID */ |
1069 | error = nfs_probe_fsinfo(server, mount_info->mntfh, fattr); | 1064 | error = nfs_probe_fsinfo(server, mount_info->mntfh, fattr); |
1070 | if (error < 0) | 1065 | if (error < 0) |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 1cc71f60b49..32e6c53520e 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -979,10 +979,11 @@ static int nfs_is_exclusive_create(struct inode *dir, unsigned int flags) | |||
979 | * particular file and the "nocto" mount flag is not set. | 979 | * particular file and the "nocto" mount flag is not set. |
980 | * | 980 | * |
981 | */ | 981 | */ |
982 | static inline | 982 | static |
983 | int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags) | 983 | int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags) |
984 | { | 984 | { |
985 | struct nfs_server *server = NFS_SERVER(inode); | 985 | struct nfs_server *server = NFS_SERVER(inode); |
986 | int ret; | ||
986 | 987 | ||
987 | if (IS_AUTOMOUNT(inode)) | 988 | if (IS_AUTOMOUNT(inode)) |
988 | return 0; | 989 | return 0; |
@@ -993,9 +994,13 @@ int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags) | |||
993 | if ((flags & LOOKUP_OPEN) && !(server->flags & NFS_MOUNT_NOCTO) && | 994 | if ((flags & LOOKUP_OPEN) && !(server->flags & NFS_MOUNT_NOCTO) && |
994 | (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) | 995 | (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) |
995 | goto out_force; | 996 | goto out_force; |
996 | return 0; | 997 | out: |
998 | return (inode->i_nlink == 0) ? -ENOENT : 0; | ||
997 | out_force: | 999 | out_force: |
998 | return __nfs_revalidate_inode(server, inode); | 1000 | ret = __nfs_revalidate_inode(server, inode); |
1001 | if (ret != 0) | ||
1002 | return ret; | ||
1003 | goto out; | ||
999 | } | 1004 | } |
1000 | 1005 | ||
1001 | /* | 1006 | /* |
@@ -1156,11 +1161,14 @@ static int nfs_dentry_delete(const struct dentry *dentry) | |||
1156 | 1161 | ||
1157 | } | 1162 | } |
1158 | 1163 | ||
1164 | /* Ensure that we revalidate inode->i_nlink */ | ||
1159 | static void nfs_drop_nlink(struct inode *inode) | 1165 | static void nfs_drop_nlink(struct inode *inode) |
1160 | { | 1166 | { |
1161 | spin_lock(&inode->i_lock); | 1167 | spin_lock(&inode->i_lock); |
1162 | if (inode->i_nlink > 0) | 1168 | /* drop the inode if we're reasonably sure this is the last link */ |
1163 | drop_nlink(inode); | 1169 | if (inode->i_nlink == 1) |
1170 | clear_nlink(inode); | ||
1171 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR; | ||
1164 | spin_unlock(&inode->i_lock); | 1172 | spin_unlock(&inode->i_lock); |
1165 | } | 1173 | } |
1166 | 1174 | ||
@@ -1175,8 +1183,8 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) | |||
1175 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA; | 1183 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA; |
1176 | 1184 | ||
1177 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { | 1185 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { |
1178 | drop_nlink(inode); | ||
1179 | nfs_complete_unlink(dentry, inode); | 1186 | nfs_complete_unlink(dentry, inode); |
1187 | nfs_drop_nlink(inode); | ||
1180 | } | 1188 | } |
1181 | iput(inode); | 1189 | iput(inode); |
1182 | } | 1190 | } |
@@ -1647,10 +1655,8 @@ static int nfs_safe_remove(struct dentry *dentry) | |||
1647 | if (inode != NULL) { | 1655 | if (inode != NULL) { |
1648 | NFS_PROTO(inode)->return_delegation(inode); | 1656 | NFS_PROTO(inode)->return_delegation(inode); |
1649 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1657 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
1650 | /* The VFS may want to delete this inode */ | ||
1651 | if (error == 0) | 1658 | if (error == 0) |
1652 | nfs_drop_nlink(inode); | 1659 | nfs_drop_nlink(inode); |
1653 | nfs_mark_for_revalidate(inode); | ||
1654 | } else | 1660 | } else |
1655 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1661 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
1656 | if (error == -ENOENT) | 1662 | if (error == -ENOENT) |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index cae26cbd59e..0bd7a55a5f0 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -266,21 +266,8 @@ static void nfs_direct_read_completion(struct nfs_pgio_header *hdr) | |||
266 | struct nfs_page *req = nfs_list_entry(hdr->pages.next); | 266 | struct nfs_page *req = nfs_list_entry(hdr->pages.next); |
267 | struct page *page = req->wb_page; | 267 | struct page *page = req->wb_page; |
268 | 268 | ||
269 | if (test_bit(NFS_IOHDR_EOF, &hdr->flags)) { | 269 | if (!PageCompound(page) && bytes < hdr->good_bytes) |
270 | if (bytes > hdr->good_bytes) | 270 | set_page_dirty(page); |
271 | zero_user(page, 0, PAGE_SIZE); | ||
272 | else if (hdr->good_bytes - bytes < PAGE_SIZE) | ||
273 | zero_user_segment(page, | ||
274 | hdr->good_bytes & ~PAGE_MASK, | ||
275 | PAGE_SIZE); | ||
276 | } | ||
277 | if (!PageCompound(page)) { | ||
278 | if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) { | ||
279 | if (bytes < hdr->good_bytes) | ||
280 | set_page_dirty(page); | ||
281 | } else | ||
282 | set_page_dirty(page); | ||
283 | } | ||
284 | bytes += req->wb_bytes; | 271 | bytes += req->wb_bytes; |
285 | nfs_list_remove_request(req); | 272 | nfs_list_remove_request(req); |
286 | nfs_direct_readpage_release(req); | 273 | nfs_direct_readpage_release(req); |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6fa01aea248..2faae14d89f 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -107,13 +107,19 @@ u64 nfs_compat_user_ino64(u64 fileid) | |||
107 | return ino; | 107 | return ino; |
108 | } | 108 | } |
109 | 109 | ||
110 | int nfs_drop_inode(struct inode *inode) | ||
111 | { | ||
112 | return NFS_STALE(inode) || generic_drop_inode(inode); | ||
113 | } | ||
114 | EXPORT_SYMBOL_GPL(nfs_drop_inode); | ||
115 | |||
110 | void nfs_clear_inode(struct inode *inode) | 116 | void nfs_clear_inode(struct inode *inode) |
111 | { | 117 | { |
112 | /* | 118 | /* |
113 | * The following should never happen... | 119 | * The following should never happen... |
114 | */ | 120 | */ |
115 | BUG_ON(nfs_have_writebacks(inode)); | 121 | WARN_ON_ONCE(nfs_have_writebacks(inode)); |
116 | BUG_ON(!list_empty(&NFS_I(inode)->open_files)); | 122 | WARN_ON_ONCE(!list_empty(&NFS_I(inode)->open_files)); |
117 | nfs_zap_acl_cache(inode); | 123 | nfs_zap_acl_cache(inode); |
118 | nfs_access_zap_cache(inode); | 124 | nfs_access_zap_cache(inode); |
119 | nfs_fscache_release_inode_cookie(inode); | 125 | nfs_fscache_release_inode_cookie(inode); |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 05521cadac2..f0e6c7df1a0 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -18,27 +18,6 @@ struct nfs_string; | |||
18 | */ | 18 | */ |
19 | #define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) | 19 | #define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) |
20 | 20 | ||
21 | /* | ||
22 | * Determine if sessions are in use. | ||
23 | */ | ||
24 | static inline int nfs4_has_session(const struct nfs_client *clp) | ||
25 | { | ||
26 | #ifdef CONFIG_NFS_V4_1 | ||
27 | if (clp->cl_session) | ||
28 | return 1; | ||
29 | #endif /* CONFIG_NFS_V4_1 */ | ||
30 | return 0; | ||
31 | } | ||
32 | |||
33 | static inline int nfs4_has_persistent_session(const struct nfs_client *clp) | ||
34 | { | ||
35 | #ifdef CONFIG_NFS_V4_1 | ||
36 | if (nfs4_has_session(clp)) | ||
37 | return (clp->cl_session->flags & SESSION4_PERSIST); | ||
38 | #endif /* CONFIG_NFS_V4_1 */ | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static inline void nfs_attr_check_mountpoint(struct super_block *parent, struct nfs_fattr *fattr) | 21 | static inline void nfs_attr_check_mountpoint(struct super_block *parent, struct nfs_fattr *fattr) |
43 | { | 22 | { |
44 | if (!nfs_fsid_equal(&NFS_SB(parent)->fsid, &fattr->fsid)) | 23 | if (!nfs_fsid_equal(&NFS_SB(parent)->fsid, &fattr->fsid)) |
@@ -276,8 +255,6 @@ extern const u32 nfs41_maxwrite_overhead; | |||
276 | extern struct rpc_procinfo nfs4_procedures[]; | 255 | extern struct rpc_procinfo nfs4_procedures[]; |
277 | #endif | 256 | #endif |
278 | 257 | ||
279 | extern int nfs4_init_ds_session(struct nfs_client *, unsigned long); | ||
280 | |||
281 | /* proc.c */ | 258 | /* proc.c */ |
282 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); | 259 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); |
283 | extern struct nfs_client *nfs_init_client(struct nfs_client *clp, | 260 | extern struct nfs_client *nfs_init_client(struct nfs_client *clp, |
@@ -319,6 +296,7 @@ extern struct workqueue_struct *nfsiod_workqueue; | |||
319 | extern struct inode *nfs_alloc_inode(struct super_block *sb); | 296 | extern struct inode *nfs_alloc_inode(struct super_block *sb); |
320 | extern void nfs_destroy_inode(struct inode *); | 297 | extern void nfs_destroy_inode(struct inode *); |
321 | extern int nfs_write_inode(struct inode *, struct writeback_control *); | 298 | extern int nfs_write_inode(struct inode *, struct writeback_control *); |
299 | extern int nfs_drop_inode(struct inode *); | ||
322 | extern void nfs_clear_inode(struct inode *); | 300 | extern void nfs_clear_inode(struct inode *); |
323 | extern void nfs_evict_inode(struct inode *); | 301 | extern void nfs_evict_inode(struct inode *); |
324 | void nfs_zap_acl_cache(struct inode *inode); | 302 | void nfs_zap_acl_cache(struct inode *inode); |
@@ -386,9 +364,6 @@ extern int nfs_initiate_read(struct rpc_clnt *clnt, | |||
386 | extern void nfs_read_prepare(struct rpc_task *task, void *calldata); | 364 | extern void nfs_read_prepare(struct rpc_task *task, void *calldata); |
387 | extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, | 365 | extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, |
388 | struct nfs_pgio_header *hdr); | 366 | struct nfs_pgio_header *hdr); |
389 | extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, | ||
390 | struct inode *inode, | ||
391 | const struct nfs_pgio_completion_ops *compl_ops); | ||
392 | extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); | 367 | extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); |
393 | extern void nfs_readdata_release(struct nfs_read_data *rdata); | 368 | extern void nfs_readdata_release(struct nfs_read_data *rdata); |
394 | 369 | ||
@@ -411,9 +386,6 @@ extern struct nfs_write_header *nfs_writehdr_alloc(void); | |||
411 | extern void nfs_writehdr_free(struct nfs_pgio_header *hdr); | 386 | extern void nfs_writehdr_free(struct nfs_pgio_header *hdr); |
412 | extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, | 387 | extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, |
413 | struct nfs_pgio_header *hdr); | 388 | struct nfs_pgio_header *hdr); |
414 | extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, | ||
415 | struct inode *inode, int ioflags, | ||
416 | const struct nfs_pgio_completion_ops *compl_ops); | ||
417 | extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); | 389 | extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); |
418 | extern void nfs_writedata_release(struct nfs_write_data *wdata); | 390 | extern void nfs_writedata_release(struct nfs_write_data *wdata); |
419 | extern void nfs_commit_free(struct nfs_commit_data *p); | 391 | extern void nfs_commit_free(struct nfs_commit_data *p); |
@@ -474,18 +446,6 @@ extern struct nfs_client *nfs4_init_client(struct nfs_client *clp, | |||
474 | const struct rpc_timeout *timeparms, | 446 | const struct rpc_timeout *timeparms, |
475 | const char *ip_addr, | 447 | const char *ip_addr, |
476 | rpc_authflavor_t authflavour); | 448 | rpc_authflavor_t authflavour); |
477 | extern int _nfs4_call_sync(struct rpc_clnt *clnt, | ||
478 | struct nfs_server *server, | ||
479 | struct rpc_message *msg, | ||
480 | struct nfs4_sequence_args *args, | ||
481 | struct nfs4_sequence_res *res, | ||
482 | int cache_reply); | ||
483 | extern int _nfs4_call_sync_session(struct rpc_clnt *clnt, | ||
484 | struct nfs_server *server, | ||
485 | struct rpc_message *msg, | ||
486 | struct nfs4_sequence_args *args, | ||
487 | struct nfs4_sequence_res *res, | ||
488 | int cache_reply); | ||
489 | extern int nfs40_walk_client_list(struct nfs_client *clp, | 449 | extern int nfs40_walk_client_list(struct nfs_client *clp, |
490 | struct nfs_client **result, | 450 | struct nfs_client **result, |
491 | struct rpc_cred *cred); | 451 | struct rpc_cred *cred); |
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 015f71f8f62..91a6faf811a 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c | |||
@@ -169,6 +169,9 @@ int nfs_mount(struct nfs_mount_request *info) | |||
169 | (info->hostname ? info->hostname : "server"), | 169 | (info->hostname ? info->hostname : "server"), |
170 | info->dirpath); | 170 | info->dirpath); |
171 | 171 | ||
172 | if (strlen(info->dirpath) > MNTPATHLEN) | ||
173 | return -ENAMETOOLONG; | ||
174 | |||
172 | if (info->noresvport) | 175 | if (info->noresvport) |
173 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; | 176 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; |
174 | 177 | ||
@@ -242,6 +245,9 @@ void nfs_umount(const struct nfs_mount_request *info) | |||
242 | struct rpc_clnt *clnt; | 245 | struct rpc_clnt *clnt; |
243 | int status; | 246 | int status; |
244 | 247 | ||
248 | if (strlen(info->dirpath) > MNTPATHLEN) | ||
249 | return; | ||
250 | |||
245 | if (info->noresvport) | 251 | if (info->noresvport) |
246 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; | 252 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; |
247 | 253 | ||
@@ -283,7 +289,6 @@ static void encode_mntdirpath(struct xdr_stream *xdr, const char *pathname) | |||
283 | const u32 pathname_len = strlen(pathname); | 289 | const u32 pathname_len = strlen(pathname); |
284 | __be32 *p; | 290 | __be32 *p; |
285 | 291 | ||
286 | BUG_ON(pathname_len > MNTPATHLEN); | ||
287 | p = xdr_reserve_space(xdr, 4 + pathname_len); | 292 | p = xdr_reserve_space(xdr, 4 + pathname_len); |
288 | xdr_encode_opaque(p, pathname, pathname_len); | 293 | xdr_encode_opaque(p, pathname, pathname_len); |
289 | } | 294 | } |
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index d04f0df7be5..06b9df49f7f 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c | |||
@@ -195,7 +195,6 @@ static void encode_fhandle(struct xdr_stream *xdr, const struct nfs_fh *fh) | |||
195 | { | 195 | { |
196 | __be32 *p; | 196 | __be32 *p; |
197 | 197 | ||
198 | BUG_ON(fh->size != NFS2_FHSIZE); | ||
199 | p = xdr_reserve_space(xdr, NFS2_FHSIZE); | 198 | p = xdr_reserve_space(xdr, NFS2_FHSIZE); |
200 | memcpy(p, fh->data, NFS2_FHSIZE); | 199 | memcpy(p, fh->data, NFS2_FHSIZE); |
201 | } | 200 | } |
@@ -388,7 +387,7 @@ static void encode_filename(struct xdr_stream *xdr, | |||
388 | { | 387 | { |
389 | __be32 *p; | 388 | __be32 *p; |
390 | 389 | ||
391 | BUG_ON(length > NFS2_MAXNAMLEN); | 390 | WARN_ON_ONCE(length > NFS2_MAXNAMLEN); |
392 | p = xdr_reserve_space(xdr, 4 + length); | 391 | p = xdr_reserve_space(xdr, 4 + length); |
393 | xdr_encode_opaque(p, name, length); | 392 | xdr_encode_opaque(p, name, length); |
394 | } | 393 | } |
@@ -428,7 +427,6 @@ static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length) | |||
428 | { | 427 | { |
429 | __be32 *p; | 428 | __be32 *p; |
430 | 429 | ||
431 | BUG_ON(length > NFS2_MAXPATHLEN); | ||
432 | p = xdr_reserve_space(xdr, 4); | 430 | p = xdr_reserve_space(xdr, 4); |
433 | *p = cpu_to_be32(length); | 431 | *p = cpu_to_be32(length); |
434 | xdr_write_pages(xdr, pages, 0, length); | 432 | xdr_write_pages(xdr, pages, 0, length); |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 69322096c32..70efb63b1e4 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -24,14 +24,14 @@ | |||
24 | 24 | ||
25 | #define NFSDBG_FACILITY NFSDBG_PROC | 25 | #define NFSDBG_FACILITY NFSDBG_PROC |
26 | 26 | ||
27 | /* A wrapper to handle the EJUKEBOX and EKEYEXPIRED error messages */ | 27 | /* A wrapper to handle the EJUKEBOX error messages */ |
28 | static int | 28 | static int |
29 | nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) | 29 | nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) |
30 | { | 30 | { |
31 | int res; | 31 | int res; |
32 | do { | 32 | do { |
33 | res = rpc_call_sync(clnt, msg, flags); | 33 | res = rpc_call_sync(clnt, msg, flags); |
34 | if (res != -EJUKEBOX && res != -EKEYEXPIRED) | 34 | if (res != -EJUKEBOX) |
35 | break; | 35 | break; |
36 | freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); | 36 | freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); |
37 | res = -ERESTARTSYS; | 37 | res = -ERESTARTSYS; |
@@ -44,7 +44,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) | |||
44 | static int | 44 | static int |
45 | nfs3_async_handle_jukebox(struct rpc_task *task, struct inode *inode) | 45 | nfs3_async_handle_jukebox(struct rpc_task *task, struct inode *inode) |
46 | { | 46 | { |
47 | if (task->tk_status != -EJUKEBOX && task->tk_status != -EKEYEXPIRED) | 47 | if (task->tk_status != -EJUKEBOX) |
48 | return 0; | 48 | return 0; |
49 | if (task->tk_status == -EJUKEBOX) | 49 | if (task->tk_status == -EJUKEBOX) |
50 | nfs_inc_stats(inode, NFSIOS_DELAY); | 50 | nfs_inc_stats(inode, NFSIOS_DELAY); |
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 6cbe89400df..bffc32406fb 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
@@ -198,7 +198,7 @@ static void encode_filename3(struct xdr_stream *xdr, | |||
198 | { | 198 | { |
199 | __be32 *p; | 199 | __be32 *p; |
200 | 200 | ||
201 | BUG_ON(length > NFS3_MAXNAMLEN); | 201 | WARN_ON_ONCE(length > NFS3_MAXNAMLEN); |
202 | p = xdr_reserve_space(xdr, 4 + length); | 202 | p = xdr_reserve_space(xdr, 4 + length); |
203 | xdr_encode_opaque(p, name, length); | 203 | xdr_encode_opaque(p, name, length); |
204 | } | 204 | } |
@@ -238,7 +238,6 @@ out_overflow: | |||
238 | static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages, | 238 | static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages, |
239 | const u32 length) | 239 | const u32 length) |
240 | { | 240 | { |
241 | BUG_ON(length > NFS3_MAXPATHLEN); | ||
242 | encode_uint32(xdr, length); | 241 | encode_uint32(xdr, length); |
243 | xdr_write_pages(xdr, pages, 0, length); | 242 | xdr_write_pages(xdr, pages, 0, length); |
244 | } | 243 | } |
@@ -388,7 +387,6 @@ out_overflow: | |||
388 | */ | 387 | */ |
389 | static void encode_ftype3(struct xdr_stream *xdr, const u32 type) | 388 | static void encode_ftype3(struct xdr_stream *xdr, const u32 type) |
390 | { | 389 | { |
391 | BUG_ON(type > NF3FIFO); | ||
392 | encode_uint32(xdr, type); | 390 | encode_uint32(xdr, type); |
393 | } | 391 | } |
394 | 392 | ||
@@ -443,7 +441,7 @@ static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh) | |||
443 | { | 441 | { |
444 | __be32 *p; | 442 | __be32 *p; |
445 | 443 | ||
446 | BUG_ON(fh->size > NFS3_FHSIZE); | 444 | WARN_ON_ONCE(fh->size > NFS3_FHSIZE); |
447 | p = xdr_reserve_space(xdr, 4 + fh->size); | 445 | p = xdr_reserve_space(xdr, 4 + fh->size); |
448 | xdr_encode_opaque(p, fh->data, fh->size); | 446 | xdr_encode_opaque(p, fh->data, fh->size); |
449 | } | 447 | } |
@@ -1339,6 +1337,7 @@ static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req, | |||
1339 | error = nfsacl_encode(xdr->buf, base, args->inode, | 1337 | error = nfsacl_encode(xdr->buf, base, args->inode, |
1340 | (args->mask & NFS_ACL) ? | 1338 | (args->mask & NFS_ACL) ? |
1341 | args->acl_access : NULL, 1, 0); | 1339 | args->acl_access : NULL, 1, 0); |
1340 | /* FIXME: this is just broken */ | ||
1342 | BUG_ON(error < 0); | 1341 | BUG_ON(error < 0); |
1343 | error = nfsacl_encode(xdr->buf, base + error, args->inode, | 1342 | error = nfsacl_encode(xdr->buf, base + error, args->inode, |
1344 | (args->mask & NFS_DFACL) ? | 1343 | (args->mask & NFS_DFACL) ? |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index a525fdefccd..a3f488b074a 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -11,6 +11,8 @@ | |||
11 | 11 | ||
12 | #if IS_ENABLED(CONFIG_NFS_V4) | 12 | #if IS_ENABLED(CONFIG_NFS_V4) |
13 | 13 | ||
14 | #define NFS4_MAX_LOOP_ON_RECOVER (10) | ||
15 | |||
14 | struct idmap; | 16 | struct idmap; |
15 | 17 | ||
16 | enum nfs4_client_state { | 18 | enum nfs4_client_state { |
@@ -21,18 +23,12 @@ enum nfs4_client_state { | |||
21 | NFS4CLNT_RECLAIM_NOGRACE, | 23 | NFS4CLNT_RECLAIM_NOGRACE, |
22 | NFS4CLNT_DELEGRETURN, | 24 | NFS4CLNT_DELEGRETURN, |
23 | NFS4CLNT_SESSION_RESET, | 25 | NFS4CLNT_SESSION_RESET, |
24 | NFS4CLNT_RECALL_SLOT, | ||
25 | NFS4CLNT_LEASE_CONFIRM, | 26 | NFS4CLNT_LEASE_CONFIRM, |
26 | NFS4CLNT_SERVER_SCOPE_MISMATCH, | 27 | NFS4CLNT_SERVER_SCOPE_MISMATCH, |
27 | NFS4CLNT_PURGE_STATE, | 28 | NFS4CLNT_PURGE_STATE, |
28 | NFS4CLNT_BIND_CONN_TO_SESSION, | 29 | NFS4CLNT_BIND_CONN_TO_SESSION, |
29 | }; | 30 | }; |
30 | 31 | ||
31 | enum nfs4_session_state { | ||
32 | NFS4_SESSION_INITING, | ||
33 | NFS4_SESSION_DRAINING, | ||
34 | }; | ||
35 | |||
36 | #define NFS4_RENEW_TIMEOUT 0x01 | 32 | #define NFS4_RENEW_TIMEOUT 0x01 |
37 | #define NFS4_RENEW_DELEGATION_CB 0x02 | 33 | #define NFS4_RENEW_DELEGATION_CB 0x02 |
38 | 34 | ||
@@ -43,8 +39,7 @@ struct nfs4_minor_version_ops { | |||
43 | struct nfs_server *server, | 39 | struct nfs_server *server, |
44 | struct rpc_message *msg, | 40 | struct rpc_message *msg, |
45 | struct nfs4_sequence_args *args, | 41 | struct nfs4_sequence_args *args, |
46 | struct nfs4_sequence_res *res, | 42 | struct nfs4_sequence_res *res); |
47 | int cache_reply); | ||
48 | bool (*match_stateid)(const nfs4_stateid *, | 43 | bool (*match_stateid)(const nfs4_stateid *, |
49 | const nfs4_stateid *); | 44 | const nfs4_stateid *); |
50 | int (*find_root_sec)(struct nfs_server *, struct nfs_fh *, | 45 | int (*find_root_sec)(struct nfs_server *, struct nfs_fh *, |
@@ -241,18 +236,14 @@ static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *ser | |||
241 | return server->nfs_client->cl_session; | 236 | return server->nfs_client->cl_session; |
242 | } | 237 | } |
243 | 238 | ||
244 | extern bool nfs4_set_task_privileged(struct rpc_task *task, void *dummy); | ||
245 | extern int nfs4_setup_sequence(const struct nfs_server *server, | 239 | extern int nfs4_setup_sequence(const struct nfs_server *server, |
246 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, | 240 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, |
247 | struct rpc_task *task); | 241 | struct rpc_task *task); |
248 | extern int nfs41_setup_sequence(struct nfs4_session *session, | 242 | extern int nfs41_setup_sequence(struct nfs4_session *session, |
249 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, | 243 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, |
250 | struct rpc_task *task); | 244 | struct rpc_task *task); |
251 | extern void nfs4_destroy_session(struct nfs4_session *session); | ||
252 | extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); | ||
253 | extern int nfs4_proc_create_session(struct nfs_client *, struct rpc_cred *); | 245 | extern int nfs4_proc_create_session(struct nfs_client *, struct rpc_cred *); |
254 | extern int nfs4_proc_destroy_session(struct nfs4_session *, struct rpc_cred *); | 246 | extern int nfs4_proc_destroy_session(struct nfs4_session *, struct rpc_cred *); |
255 | extern int nfs4_init_session(struct nfs_server *server); | ||
256 | extern int nfs4_proc_get_lease_time(struct nfs_client *clp, | 247 | extern int nfs4_proc_get_lease_time(struct nfs_client *clp, |
257 | struct nfs_fsinfo *fsinfo); | 248 | struct nfs_fsinfo *fsinfo); |
258 | extern int nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, | 249 | extern int nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, |
@@ -280,11 +271,7 @@ static inline int nfs4_setup_sequence(const struct nfs_server *server, | |||
280 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, | 271 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, |
281 | struct rpc_task *task) | 272 | struct rpc_task *task) |
282 | { | 273 | { |
283 | return 0; | 274 | rpc_call_start(task); |
284 | } | ||
285 | |||
286 | static inline int nfs4_init_session(struct nfs_server *server) | ||
287 | { | ||
288 | return 0; | 275 | return 0; |
289 | } | 276 | } |
290 | 277 | ||
@@ -321,17 +308,20 @@ extern void nfs4_renew_state(struct work_struct *); | |||
321 | 308 | ||
322 | /* nfs4state.c */ | 309 | /* nfs4state.c */ |
323 | struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp); | 310 | struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp); |
311 | struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp); | ||
324 | struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp); | 312 | struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp); |
325 | int nfs4_discover_server_trunking(struct nfs_client *clp, | 313 | int nfs4_discover_server_trunking(struct nfs_client *clp, |
326 | struct nfs_client **); | 314 | struct nfs_client **); |
327 | int nfs40_discover_server_trunking(struct nfs_client *clp, | 315 | int nfs40_discover_server_trunking(struct nfs_client *clp, |
328 | struct nfs_client **, struct rpc_cred *); | 316 | struct nfs_client **, struct rpc_cred *); |
329 | #if defined(CONFIG_NFS_V4_1) | 317 | #if defined(CONFIG_NFS_V4_1) |
330 | struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp); | ||
331 | struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp); | 318 | struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp); |
332 | int nfs41_discover_server_trunking(struct nfs_client *clp, | 319 | int nfs41_discover_server_trunking(struct nfs_client *clp, |
333 | struct nfs_client **, struct rpc_cred *); | 320 | struct nfs_client **, struct rpc_cred *); |
334 | extern void nfs4_schedule_session_recovery(struct nfs4_session *, int); | 321 | extern void nfs4_schedule_session_recovery(struct nfs4_session *, int); |
322 | extern void nfs41_server_notify_target_slotid_update(struct nfs_client *clp); | ||
323 | extern void nfs41_server_notify_highest_slotid_update(struct nfs_client *clp); | ||
324 | |||
335 | #else | 325 | #else |
336 | static inline void nfs4_schedule_session_recovery(struct nfs4_session *session, int err) | 326 | static inline void nfs4_schedule_session_recovery(struct nfs4_session *session, int err) |
337 | { | 327 | { |
@@ -349,11 +339,12 @@ extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t); | |||
349 | extern void nfs_inode_find_state_and_recover(struct inode *inode, | 339 | extern void nfs_inode_find_state_and_recover(struct inode *inode, |
350 | const nfs4_stateid *stateid); | 340 | const nfs4_stateid *stateid); |
351 | extern void nfs4_schedule_lease_recovery(struct nfs_client *); | 341 | extern void nfs4_schedule_lease_recovery(struct nfs_client *); |
342 | extern int nfs4_wait_clnt_recover(struct nfs_client *clp); | ||
343 | extern int nfs4_client_recover_expired_lease(struct nfs_client *clp); | ||
352 | extern void nfs4_schedule_state_manager(struct nfs_client *); | 344 | extern void nfs4_schedule_state_manager(struct nfs_client *); |
353 | extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp); | 345 | extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp); |
354 | extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); | 346 | extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); |
355 | extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); | 347 | extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); |
356 | extern void nfs41_handle_recall_slot(struct nfs_client *clp); | ||
357 | extern void nfs41_handle_server_scope(struct nfs_client *, | 348 | extern void nfs41_handle_server_scope(struct nfs_client *, |
358 | struct nfs41_server_scope **); | 349 | struct nfs41_server_scope **); |
359 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); | 350 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 6bacfde1319..acc34726812 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include "internal.h" | 12 | #include "internal.h" |
13 | #include "callback.h" | 13 | #include "callback.h" |
14 | #include "delegation.h" | 14 | #include "delegation.h" |
15 | #include "nfs4session.h" | ||
15 | #include "pnfs.h" | 16 | #include "pnfs.h" |
16 | #include "netns.h" | 17 | #include "netns.h" |
17 | 18 | ||
@@ -713,10 +714,6 @@ static int nfs4_server_common_setup(struct nfs_server *server, | |||
713 | struct nfs_fattr *fattr; | 714 | struct nfs_fattr *fattr; |
714 | int error; | 715 | int error; |
715 | 716 | ||
716 | BUG_ON(!server->nfs_client); | ||
717 | BUG_ON(!server->nfs_client->rpc_ops); | ||
718 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | ||
719 | |||
720 | /* data servers support only a subset of NFSv4.1 */ | 717 | /* data servers support only a subset of NFSv4.1 */ |
721 | if (is_ds_only_client(server->nfs_client)) | 718 | if (is_ds_only_client(server->nfs_client)) |
722 | return -EPROTONOSUPPORT; | 719 | return -EPROTONOSUPPORT; |
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index afddd6639af..e7699308364 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c | |||
@@ -20,7 +20,6 @@ nfs4_file_open(struct inode *inode, struct file *filp) | |||
20 | struct iattr attr; | 20 | struct iattr attr; |
21 | int err; | 21 | int err; |
22 | 22 | ||
23 | BUG_ON(inode != dentry->d_inode); | ||
24 | /* | 23 | /* |
25 | * If no cached dentry exists or if it's negative, NFSv4 handled the | 24 | * If no cached dentry exists or if it's negative, NFSv4 handled the |
26 | * opens in ->lookup() or ->create(). | 25 | * opens in ->lookup() or ->create(). |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 2e45fd9c02a..194c4841033 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | #include <linux/sunrpc/metrics.h> | 36 | #include <linux/sunrpc/metrics.h> |
37 | 37 | ||
38 | #include "nfs4session.h" | ||
38 | #include "internal.h" | 39 | #include "internal.h" |
39 | #include "delegation.h" | 40 | #include "delegation.h" |
40 | #include "nfs4filelayout.h" | 41 | #include "nfs4filelayout.h" |
@@ -178,7 +179,6 @@ static int filelayout_async_handle_error(struct rpc_task *task, | |||
178 | break; | 179 | break; |
179 | case -NFS4ERR_DELAY: | 180 | case -NFS4ERR_DELAY: |
180 | case -NFS4ERR_GRACE: | 181 | case -NFS4ERR_GRACE: |
181 | case -EKEYEXPIRED: | ||
182 | rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX); | 182 | rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX); |
183 | break; | 183 | break; |
184 | case -NFS4ERR_RETRY_UNCACHED_REP: | 184 | case -NFS4ERR_RETRY_UNCACHED_REP: |
@@ -306,12 +306,10 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data) | |||
306 | } | 306 | } |
307 | rdata->read_done_cb = filelayout_read_done_cb; | 307 | rdata->read_done_cb = filelayout_read_done_cb; |
308 | 308 | ||
309 | if (nfs41_setup_sequence(rdata->ds_clp->cl_session, | 309 | nfs41_setup_sequence(rdata->ds_clp->cl_session, |
310 | &rdata->args.seq_args, &rdata->res.seq_res, | 310 | &rdata->args.seq_args, |
311 | task)) | 311 | &rdata->res.seq_res, |
312 | return; | 312 | task); |
313 | |||
314 | rpc_call_start(task); | ||
315 | } | 313 | } |
316 | 314 | ||
317 | static void filelayout_read_call_done(struct rpc_task *task, void *data) | 315 | static void filelayout_read_call_done(struct rpc_task *task, void *data) |
@@ -408,12 +406,10 @@ static void filelayout_write_prepare(struct rpc_task *task, void *data) | |||
408 | rpc_exit(task, 0); | 406 | rpc_exit(task, 0); |
409 | return; | 407 | return; |
410 | } | 408 | } |
411 | if (nfs41_setup_sequence(wdata->ds_clp->cl_session, | 409 | nfs41_setup_sequence(wdata->ds_clp->cl_session, |
412 | &wdata->args.seq_args, &wdata->res.seq_res, | 410 | &wdata->args.seq_args, |
413 | task)) | 411 | &wdata->res.seq_res, |
414 | return; | 412 | task); |
415 | |||
416 | rpc_call_start(task); | ||
417 | } | 413 | } |
418 | 414 | ||
419 | static void filelayout_write_call_done(struct rpc_task *task, void *data) | 415 | static void filelayout_write_call_done(struct rpc_task *task, void *data) |
@@ -449,12 +445,10 @@ static void filelayout_commit_prepare(struct rpc_task *task, void *data) | |||
449 | { | 445 | { |
450 | struct nfs_commit_data *wdata = data; | 446 | struct nfs_commit_data *wdata = data; |
451 | 447 | ||
452 | if (nfs41_setup_sequence(wdata->ds_clp->cl_session, | 448 | nfs41_setup_sequence(wdata->ds_clp->cl_session, |
453 | &wdata->args.seq_args, &wdata->res.seq_res, | 449 | &wdata->args.seq_args, |
454 | task)) | 450 | &wdata->res.seq_res, |
455 | return; | 451 | task); |
456 | |||
457 | rpc_call_start(task); | ||
458 | } | 452 | } |
459 | 453 | ||
460 | static void filelayout_write_commit_done(struct rpc_task *task, void *data) | 454 | static void filelayout_write_commit_done(struct rpc_task *task, void *data) |
@@ -512,7 +506,6 @@ filelayout_read_pagelist(struct nfs_read_data *data) | |||
512 | loff_t offset = data->args.offset; | 506 | loff_t offset = data->args.offset; |
513 | u32 j, idx; | 507 | u32 j, idx; |
514 | struct nfs_fh *fh; | 508 | struct nfs_fh *fh; |
515 | int status; | ||
516 | 509 | ||
517 | dprintk("--> %s ino %lu pgbase %u req %Zu@%llu\n", | 510 | dprintk("--> %s ino %lu pgbase %u req %Zu@%llu\n", |
518 | __func__, hdr->inode->i_ino, | 511 | __func__, hdr->inode->i_ino, |
@@ -538,9 +531,8 @@ filelayout_read_pagelist(struct nfs_read_data *data) | |||
538 | data->mds_offset = offset; | 531 | data->mds_offset = offset; |
539 | 532 | ||
540 | /* Perform an asynchronous read to ds */ | 533 | /* Perform an asynchronous read to ds */ |
541 | status = nfs_initiate_read(ds->ds_clp->cl_rpcclient, data, | 534 | nfs_initiate_read(ds->ds_clp->cl_rpcclient, data, |
542 | &filelayout_read_call_ops, RPC_TASK_SOFTCONN); | 535 | &filelayout_read_call_ops, RPC_TASK_SOFTCONN); |
543 | BUG_ON(status != 0); | ||
544 | return PNFS_ATTEMPTED; | 536 | return PNFS_ATTEMPTED; |
545 | } | 537 | } |
546 | 538 | ||
@@ -554,7 +546,6 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync) | |||
554 | loff_t offset = data->args.offset; | 546 | loff_t offset = data->args.offset; |
555 | u32 j, idx; | 547 | u32 j, idx; |
556 | struct nfs_fh *fh; | 548 | struct nfs_fh *fh; |
557 | int status; | ||
558 | 549 | ||
559 | /* Retrieve the correct rpc_client for the byte range */ | 550 | /* Retrieve the correct rpc_client for the byte range */ |
560 | j = nfs4_fl_calc_j_index(lseg, offset); | 551 | j = nfs4_fl_calc_j_index(lseg, offset); |
@@ -579,10 +570,9 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync) | |||
579 | data->args.offset = filelayout_get_dserver_offset(lseg, offset); | 570 | data->args.offset = filelayout_get_dserver_offset(lseg, offset); |
580 | 571 | ||
581 | /* Perform an asynchronous write */ | 572 | /* Perform an asynchronous write */ |
582 | status = nfs_initiate_write(ds->ds_clp->cl_rpcclient, data, | 573 | nfs_initiate_write(ds->ds_clp->cl_rpcclient, data, |
583 | &filelayout_write_call_ops, sync, | 574 | &filelayout_write_call_ops, sync, |
584 | RPC_TASK_SOFTCONN); | 575 | RPC_TASK_SOFTCONN); |
585 | BUG_ON(status != 0); | ||
586 | return PNFS_ATTEMPTED; | 576 | return PNFS_ATTEMPTED; |
587 | } | 577 | } |
588 | 578 | ||
@@ -909,7 +899,7 @@ static void | |||
909 | filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio, | 899 | filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio, |
910 | struct nfs_page *req) | 900 | struct nfs_page *req) |
911 | { | 901 | { |
912 | BUG_ON(pgio->pg_lseg != NULL); | 902 | WARN_ON_ONCE(pgio->pg_lseg != NULL); |
913 | 903 | ||
914 | if (req->wb_offset != req->wb_pgbase) { | 904 | if (req->wb_offset != req->wb_pgbase) { |
915 | /* | 905 | /* |
@@ -939,7 +929,7 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio, | |||
939 | struct nfs_commit_info cinfo; | 929 | struct nfs_commit_info cinfo; |
940 | int status; | 930 | int status; |
941 | 931 | ||
942 | BUG_ON(pgio->pg_lseg != NULL); | 932 | WARN_ON_ONCE(pgio->pg_lseg != NULL); |
943 | 933 | ||
944 | if (req->wb_offset != req->wb_pgbase) | 934 | if (req->wb_offset != req->wb_pgbase) |
945 | goto out_mds; | 935 | goto out_mds; |
@@ -1187,7 +1177,6 @@ static void filelayout_recover_commit_reqs(struct list_head *dst, | |||
1187 | */ | 1177 | */ |
1188 | for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) { | 1178 | for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) { |
1189 | if (transfer_commit_list(&b->written, dst, cinfo, 0)) { | 1179 | if (transfer_commit_list(&b->written, dst, cinfo, 0)) { |
1190 | BUG_ON(!list_empty(&b->written)); | ||
1191 | pnfs_put_lseg(b->wlseg); | 1180 | pnfs_put_lseg(b->wlseg); |
1192 | b->wlseg = NULL; | 1181 | b->wlseg = NULL; |
1193 | } | 1182 | } |
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index a8eaa9b7bb0..b720064bcd7 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | 34 | ||
35 | #include "internal.h" | 35 | #include "internal.h" |
36 | #include "nfs4session.h" | ||
36 | #include "nfs4filelayout.h" | 37 | #include "nfs4filelayout.h" |
37 | 38 | ||
38 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD | 39 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD |
@@ -162,8 +163,6 @@ nfs4_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds) | |||
162 | dprintk("--> %s DS %s au_flavor %d\n", __func__, ds->ds_remotestr, | 163 | dprintk("--> %s DS %s au_flavor %d\n", __func__, ds->ds_remotestr, |
163 | mds_srv->nfs_client->cl_rpcclient->cl_auth->au_flavor); | 164 | mds_srv->nfs_client->cl_rpcclient->cl_auth->au_flavor); |
164 | 165 | ||
165 | BUG_ON(list_empty(&ds->ds_addrs)); | ||
166 | |||
167 | list_for_each_entry(da, &ds->ds_addrs, da_node) { | 166 | list_for_each_entry(da, &ds->ds_addrs, da_node) { |
168 | dprintk("%s: DS %s: trying address %s\n", | 167 | dprintk("%s: DS %s: trying address %s\n", |
169 | __func__, ds->ds_remotestr, da->da_remotestr); | 168 | __func__, ds->ds_remotestr, da->da_remotestr); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 5eec4429970..493f0f41c55 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -52,7 +52,6 @@ | |||
52 | #include <linux/mount.h> | 52 | #include <linux/mount.h> |
53 | #include <linux/module.h> | 53 | #include <linux/module.h> |
54 | #include <linux/nfs_idmap.h> | 54 | #include <linux/nfs_idmap.h> |
55 | #include <linux/sunrpc/bc_xprt.h> | ||
56 | #include <linux/xattr.h> | 55 | #include <linux/xattr.h> |
57 | #include <linux/utsname.h> | 56 | #include <linux/utsname.h> |
58 | #include <linux/freezer.h> | 57 | #include <linux/freezer.h> |
@@ -64,14 +63,14 @@ | |||
64 | #include "callback.h" | 63 | #include "callback.h" |
65 | #include "pnfs.h" | 64 | #include "pnfs.h" |
66 | #include "netns.h" | 65 | #include "netns.h" |
66 | #include "nfs4session.h" | ||
67 | |||
67 | 68 | ||
68 | #define NFSDBG_FACILITY NFSDBG_PROC | 69 | #define NFSDBG_FACILITY NFSDBG_PROC |
69 | 70 | ||
70 | #define NFS4_POLL_RETRY_MIN (HZ/10) | 71 | #define NFS4_POLL_RETRY_MIN (HZ/10) |
71 | #define NFS4_POLL_RETRY_MAX (15*HZ) | 72 | #define NFS4_POLL_RETRY_MAX (15*HZ) |
72 | 73 | ||
73 | #define NFS4_MAX_LOOP_ON_RECOVER (10) | ||
74 | |||
75 | struct nfs4_opendata; | 74 | struct nfs4_opendata; |
76 | static int _nfs4_proc_open(struct nfs4_opendata *data); | 75 | static int _nfs4_proc_open(struct nfs4_opendata *data); |
77 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); | 76 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); |
@@ -206,7 +205,6 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent | |||
206 | { | 205 | { |
207 | __be32 *start, *p; | 206 | __be32 *start, *p; |
208 | 207 | ||
209 | BUG_ON(readdir->count < 80); | ||
210 | if (cookie > 2) { | 208 | if (cookie > 2) { |
211 | readdir->cookie = cookie; | 209 | readdir->cookie = cookie; |
212 | memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier)); | 210 | memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier)); |
@@ -256,22 +254,6 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent | |||
256 | kunmap_atomic(start); | 254 | kunmap_atomic(start); |
257 | } | 255 | } |
258 | 256 | ||
259 | static int nfs4_wait_clnt_recover(struct nfs_client *clp) | ||
260 | { | ||
261 | int res; | ||
262 | |||
263 | might_sleep(); | ||
264 | |||
265 | res = wait_on_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING, | ||
266 | nfs_wait_bit_killable, TASK_KILLABLE); | ||
267 | if (res) | ||
268 | return res; | ||
269 | |||
270 | if (clp->cl_cons_state < 0) | ||
271 | return clp->cl_cons_state; | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) | 257 | static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) |
276 | { | 258 | { |
277 | int res = 0; | 259 | int res = 0; |
@@ -351,7 +333,6 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc | |||
351 | } | 333 | } |
352 | case -NFS4ERR_GRACE: | 334 | case -NFS4ERR_GRACE: |
353 | case -NFS4ERR_DELAY: | 335 | case -NFS4ERR_DELAY: |
354 | case -EKEYEXPIRED: | ||
355 | ret = nfs4_delay(server->client, &exception->timeout); | 336 | ret = nfs4_delay(server->client, &exception->timeout); |
356 | if (ret != 0) | 337 | if (ret != 0) |
357 | break; | 338 | break; |
@@ -397,144 +378,136 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp | |||
397 | 378 | ||
398 | #if defined(CONFIG_NFS_V4_1) | 379 | #if defined(CONFIG_NFS_V4_1) |
399 | 380 | ||
400 | /* | ||
401 | * nfs4_free_slot - free a slot and efficiently update slot table. | ||
402 | * | ||
403 | * freeing a slot is trivially done by clearing its respective bit | ||
404 | * in the bitmap. | ||
405 | * If the freed slotid equals highest_used_slotid we want to update it | ||
406 | * so that the server would be able to size down the slot table if needed, | ||
407 | * otherwise we know that the highest_used_slotid is still in use. | ||
408 | * When updating highest_used_slotid there may be "holes" in the bitmap | ||
409 | * so we need to scan down from highest_used_slotid to 0 looking for the now | ||
410 | * highest slotid in use. | ||
411 | * If none found, highest_used_slotid is set to NFS4_NO_SLOT. | ||
412 | * | ||
413 | * Must be called while holding tbl->slot_tbl_lock | ||
414 | */ | ||
415 | static void | ||
416 | nfs4_free_slot(struct nfs4_slot_table *tbl, u32 slotid) | ||
417 | { | ||
418 | BUG_ON(slotid >= NFS4_MAX_SLOT_TABLE); | ||
419 | /* clear used bit in bitmap */ | ||
420 | __clear_bit(slotid, tbl->used_slots); | ||
421 | |||
422 | /* update highest_used_slotid when it is freed */ | ||
423 | if (slotid == tbl->highest_used_slotid) { | ||
424 | slotid = find_last_bit(tbl->used_slots, tbl->max_slots); | ||
425 | if (slotid < tbl->max_slots) | ||
426 | tbl->highest_used_slotid = slotid; | ||
427 | else | ||
428 | tbl->highest_used_slotid = NFS4_NO_SLOT; | ||
429 | } | ||
430 | dprintk("%s: slotid %u highest_used_slotid %d\n", __func__, | ||
431 | slotid, tbl->highest_used_slotid); | ||
432 | } | ||
433 | |||
434 | bool nfs4_set_task_privileged(struct rpc_task *task, void *dummy) | ||
435 | { | ||
436 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
437 | return true; | ||
438 | } | ||
439 | |||
440 | /* | ||
441 | * Signal state manager thread if session fore channel is drained | ||
442 | */ | ||
443 | static void nfs4_check_drain_fc_complete(struct nfs4_session *ses) | ||
444 | { | ||
445 | if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state)) { | ||
446 | rpc_wake_up_first(&ses->fc_slot_table.slot_tbl_waitq, | ||
447 | nfs4_set_task_privileged, NULL); | ||
448 | return; | ||
449 | } | ||
450 | |||
451 | if (ses->fc_slot_table.highest_used_slotid != NFS4_NO_SLOT) | ||
452 | return; | ||
453 | |||
454 | dprintk("%s COMPLETE: Session Fore Channel Drained\n", __func__); | ||
455 | complete(&ses->fc_slot_table.complete); | ||
456 | } | ||
457 | |||
458 | /* | ||
459 | * Signal state manager thread if session back channel is drained | ||
460 | */ | ||
461 | void nfs4_check_drain_bc_complete(struct nfs4_session *ses) | ||
462 | { | ||
463 | if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state) || | ||
464 | ses->bc_slot_table.highest_used_slotid != NFS4_NO_SLOT) | ||
465 | return; | ||
466 | dprintk("%s COMPLETE: Session Back Channel Drained\n", __func__); | ||
467 | complete(&ses->bc_slot_table.complete); | ||
468 | } | ||
469 | |||
470 | static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) | 381 | static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) |
471 | { | 382 | { |
383 | struct nfs4_session *session; | ||
472 | struct nfs4_slot_table *tbl; | 384 | struct nfs4_slot_table *tbl; |
385 | bool send_new_highest_used_slotid = false; | ||
473 | 386 | ||
474 | tbl = &res->sr_session->fc_slot_table; | ||
475 | if (!res->sr_slot) { | 387 | if (!res->sr_slot) { |
476 | /* just wake up the next guy waiting since | 388 | /* just wake up the next guy waiting since |
477 | * we may have not consumed a slot after all */ | 389 | * we may have not consumed a slot after all */ |
478 | dprintk("%s: No slot\n", __func__); | 390 | dprintk("%s: No slot\n", __func__); |
479 | return; | 391 | return; |
480 | } | 392 | } |
393 | tbl = res->sr_slot->table; | ||
394 | session = tbl->session; | ||
481 | 395 | ||
482 | spin_lock(&tbl->slot_tbl_lock); | 396 | spin_lock(&tbl->slot_tbl_lock); |
483 | nfs4_free_slot(tbl, res->sr_slot - tbl->slots); | 397 | /* Be nice to the server: try to ensure that the last transmitted |
484 | nfs4_check_drain_fc_complete(res->sr_session); | 398 | * value for highest_user_slotid <= target_highest_slotid |
399 | */ | ||
400 | if (tbl->highest_used_slotid > tbl->target_highest_slotid) | ||
401 | send_new_highest_used_slotid = true; | ||
402 | |||
403 | if (nfs41_wake_and_assign_slot(tbl, res->sr_slot)) { | ||
404 | send_new_highest_used_slotid = false; | ||
405 | goto out_unlock; | ||
406 | } | ||
407 | nfs4_free_slot(tbl, res->sr_slot); | ||
408 | |||
409 | if (tbl->highest_used_slotid != NFS4_NO_SLOT) | ||
410 | send_new_highest_used_slotid = false; | ||
411 | out_unlock: | ||
485 | spin_unlock(&tbl->slot_tbl_lock); | 412 | spin_unlock(&tbl->slot_tbl_lock); |
486 | res->sr_slot = NULL; | 413 | res->sr_slot = NULL; |
414 | if (send_new_highest_used_slotid) | ||
415 | nfs41_server_notify_highest_slotid_update(session->clp); | ||
487 | } | 416 | } |
488 | 417 | ||
489 | static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) | 418 | static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) |
490 | { | 419 | { |
491 | unsigned long timestamp; | 420 | struct nfs4_session *session; |
421 | struct nfs4_slot *slot; | ||
492 | struct nfs_client *clp; | 422 | struct nfs_client *clp; |
493 | 423 | bool interrupted = false; | |
494 | /* | 424 | int ret = 1; |
495 | * sr_status remains 1 if an RPC level error occurred. The server | ||
496 | * may or may not have processed the sequence operation.. | ||
497 | * Proceed as if the server received and processed the sequence | ||
498 | * operation. | ||
499 | */ | ||
500 | if (res->sr_status == 1) | ||
501 | res->sr_status = NFS_OK; | ||
502 | 425 | ||
503 | /* don't increment the sequence number if the task wasn't sent */ | 426 | /* don't increment the sequence number if the task wasn't sent */ |
504 | if (!RPC_WAS_SENT(task)) | 427 | if (!RPC_WAS_SENT(task)) |
505 | goto out; | 428 | goto out; |
506 | 429 | ||
430 | slot = res->sr_slot; | ||
431 | session = slot->table->session; | ||
432 | |||
433 | if (slot->interrupted) { | ||
434 | slot->interrupted = 0; | ||
435 | interrupted = true; | ||
436 | } | ||
437 | |||
507 | /* Check the SEQUENCE operation status */ | 438 | /* Check the SEQUENCE operation status */ |
508 | switch (res->sr_status) { | 439 | switch (res->sr_status) { |
509 | case 0: | 440 | case 0: |
510 | /* Update the slot's sequence and clientid lease timer */ | 441 | /* Update the slot's sequence and clientid lease timer */ |
511 | ++res->sr_slot->seq_nr; | 442 | ++slot->seq_nr; |
512 | timestamp = res->sr_renewal_time; | 443 | clp = session->clp; |
513 | clp = res->sr_session->clp; | 444 | do_renew_lease(clp, res->sr_timestamp); |
514 | do_renew_lease(clp, timestamp); | ||
515 | /* Check sequence flags */ | 445 | /* Check sequence flags */ |
516 | if (res->sr_status_flags != 0) | 446 | if (res->sr_status_flags != 0) |
517 | nfs4_schedule_lease_recovery(clp); | 447 | nfs4_schedule_lease_recovery(clp); |
448 | nfs41_update_target_slotid(slot->table, slot, res); | ||
518 | break; | 449 | break; |
450 | case 1: | ||
451 | /* | ||
452 | * sr_status remains 1 if an RPC level error occurred. | ||
453 | * The server may or may not have processed the sequence | ||
454 | * operation.. | ||
455 | * Mark the slot as having hosted an interrupted RPC call. | ||
456 | */ | ||
457 | slot->interrupted = 1; | ||
458 | goto out; | ||
519 | case -NFS4ERR_DELAY: | 459 | case -NFS4ERR_DELAY: |
520 | /* The server detected a resend of the RPC call and | 460 | /* The server detected a resend of the RPC call and |
521 | * returned NFS4ERR_DELAY as per Section 2.10.6.2 | 461 | * returned NFS4ERR_DELAY as per Section 2.10.6.2 |
522 | * of RFC5661. | 462 | * of RFC5661. |
523 | */ | 463 | */ |
524 | dprintk("%s: slot=%td seq=%d: Operation in progress\n", | 464 | dprintk("%s: slot=%u seq=%u: Operation in progress\n", |
525 | __func__, | 465 | __func__, |
526 | res->sr_slot - res->sr_session->fc_slot_table.slots, | 466 | slot->slot_nr, |
527 | res->sr_slot->seq_nr); | 467 | slot->seq_nr); |
528 | goto out_retry; | 468 | goto out_retry; |
469 | case -NFS4ERR_BADSLOT: | ||
470 | /* | ||
471 | * The slot id we used was probably retired. Try again | ||
472 | * using a different slot id. | ||
473 | */ | ||
474 | goto retry_nowait; | ||
475 | case -NFS4ERR_SEQ_MISORDERED: | ||
476 | /* | ||
477 | * Was the last operation on this sequence interrupted? | ||
478 | * If so, retry after bumping the sequence number. | ||
479 | */ | ||
480 | if (interrupted) { | ||
481 | ++slot->seq_nr; | ||
482 | goto retry_nowait; | ||
483 | } | ||
484 | /* | ||
485 | * Could this slot have been previously retired? | ||
486 | * If so, then the server may be expecting seq_nr = 1! | ||
487 | */ | ||
488 | if (slot->seq_nr != 1) { | ||
489 | slot->seq_nr = 1; | ||
490 | goto retry_nowait; | ||
491 | } | ||
492 | break; | ||
493 | case -NFS4ERR_SEQ_FALSE_RETRY: | ||
494 | ++slot->seq_nr; | ||
495 | goto retry_nowait; | ||
529 | default: | 496 | default: |
530 | /* Just update the slot sequence no. */ | 497 | /* Just update the slot sequence no. */ |
531 | ++res->sr_slot->seq_nr; | 498 | ++slot->seq_nr; |
532 | } | 499 | } |
533 | out: | 500 | out: |
534 | /* The session may be reset by one of the error handlers. */ | 501 | /* The session may be reset by one of the error handlers. */ |
535 | dprintk("%s: Error %d free the slot \n", __func__, res->sr_status); | 502 | dprintk("%s: Error %d free the slot \n", __func__, res->sr_status); |
536 | nfs41_sequence_free_slot(res); | 503 | nfs41_sequence_free_slot(res); |
537 | return 1; | 504 | return ret; |
505 | retry_nowait: | ||
506 | if (rpc_restart_call_prepare(task)) { | ||
507 | task->tk_status = 0; | ||
508 | ret = 0; | ||
509 | } | ||
510 | goto out; | ||
538 | out_retry: | 511 | out_retry: |
539 | if (!rpc_restart_call(task)) | 512 | if (!rpc_restart_call(task)) |
540 | goto out; | 513 | goto out; |
@@ -545,55 +518,27 @@ out_retry: | |||
545 | static int nfs4_sequence_done(struct rpc_task *task, | 518 | static int nfs4_sequence_done(struct rpc_task *task, |
546 | struct nfs4_sequence_res *res) | 519 | struct nfs4_sequence_res *res) |
547 | { | 520 | { |
548 | if (res->sr_session == NULL) | 521 | if (res->sr_slot == NULL) |
549 | return 1; | 522 | return 1; |
550 | return nfs41_sequence_done(task, res); | 523 | return nfs41_sequence_done(task, res); |
551 | } | 524 | } |
552 | 525 | ||
553 | /* | ||
554 | * nfs4_find_slot - efficiently look for a free slot | ||
555 | * | ||
556 | * nfs4_find_slot looks for an unset bit in the used_slots bitmap. | ||
557 | * If found, we mark the slot as used, update the highest_used_slotid, | ||
558 | * and respectively set up the sequence operation args. | ||
559 | * The slot number is returned if found, or NFS4_NO_SLOT otherwise. | ||
560 | * | ||
561 | * Note: must be called with under the slot_tbl_lock. | ||
562 | */ | ||
563 | static u32 | ||
564 | nfs4_find_slot(struct nfs4_slot_table *tbl) | ||
565 | { | ||
566 | u32 slotid; | ||
567 | u32 ret_id = NFS4_NO_SLOT; | ||
568 | |||
569 | dprintk("--> %s used_slots=%04lx highest_used=%u max_slots=%u\n", | ||
570 | __func__, tbl->used_slots[0], tbl->highest_used_slotid, | ||
571 | tbl->max_slots); | ||
572 | slotid = find_first_zero_bit(tbl->used_slots, tbl->max_slots); | ||
573 | if (slotid >= tbl->max_slots) | ||
574 | goto out; | ||
575 | __set_bit(slotid, tbl->used_slots); | ||
576 | if (slotid > tbl->highest_used_slotid || | ||
577 | tbl->highest_used_slotid == NFS4_NO_SLOT) | ||
578 | tbl->highest_used_slotid = slotid; | ||
579 | ret_id = slotid; | ||
580 | out: | ||
581 | dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n", | ||
582 | __func__, tbl->used_slots[0], tbl->highest_used_slotid, ret_id); | ||
583 | return ret_id; | ||
584 | } | ||
585 | |||
586 | static void nfs41_init_sequence(struct nfs4_sequence_args *args, | 526 | static void nfs41_init_sequence(struct nfs4_sequence_args *args, |
587 | struct nfs4_sequence_res *res, int cache_reply) | 527 | struct nfs4_sequence_res *res, int cache_reply) |
588 | { | 528 | { |
589 | args->sa_session = NULL; | 529 | args->sa_slot = NULL; |
590 | args->sa_cache_this = 0; | 530 | args->sa_cache_this = 0; |
531 | args->sa_privileged = 0; | ||
591 | if (cache_reply) | 532 | if (cache_reply) |
592 | args->sa_cache_this = 1; | 533 | args->sa_cache_this = 1; |
593 | res->sr_session = NULL; | ||
594 | res->sr_slot = NULL; | 534 | res->sr_slot = NULL; |
595 | } | 535 | } |
596 | 536 | ||
537 | static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args) | ||
538 | { | ||
539 | args->sa_privileged = 1; | ||
540 | } | ||
541 | |||
597 | int nfs41_setup_sequence(struct nfs4_session *session, | 542 | int nfs41_setup_sequence(struct nfs4_session *session, |
598 | struct nfs4_sequence_args *args, | 543 | struct nfs4_sequence_args *args, |
599 | struct nfs4_sequence_res *res, | 544 | struct nfs4_sequence_res *res, |
@@ -601,59 +546,59 @@ int nfs41_setup_sequence(struct nfs4_session *session, | |||
601 | { | 546 | { |
602 | struct nfs4_slot *slot; | 547 | struct nfs4_slot *slot; |
603 | struct nfs4_slot_table *tbl; | 548 | struct nfs4_slot_table *tbl; |
604 | u32 slotid; | ||
605 | 549 | ||
606 | dprintk("--> %s\n", __func__); | 550 | dprintk("--> %s\n", __func__); |
607 | /* slot already allocated? */ | 551 | /* slot already allocated? */ |
608 | if (res->sr_slot != NULL) | 552 | if (res->sr_slot != NULL) |
609 | return 0; | 553 | goto out_success; |
610 | 554 | ||
611 | tbl = &session->fc_slot_table; | 555 | tbl = &session->fc_slot_table; |
612 | 556 | ||
557 | task->tk_timeout = 0; | ||
558 | |||
613 | spin_lock(&tbl->slot_tbl_lock); | 559 | spin_lock(&tbl->slot_tbl_lock); |
614 | if (test_bit(NFS4_SESSION_DRAINING, &session->session_state) && | 560 | if (test_bit(NFS4_SESSION_DRAINING, &session->session_state) && |
615 | !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) { | 561 | !args->sa_privileged) { |
616 | /* The state manager will wait until the slot table is empty */ | 562 | /* The state manager will wait until the slot table is empty */ |
617 | rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); | ||
618 | spin_unlock(&tbl->slot_tbl_lock); | ||
619 | dprintk("%s session is draining\n", __func__); | 563 | dprintk("%s session is draining\n", __func__); |
620 | return -EAGAIN; | 564 | goto out_sleep; |
621 | } | 565 | } |
622 | 566 | ||
623 | if (!rpc_queue_empty(&tbl->slot_tbl_waitq) && | 567 | slot = nfs4_alloc_slot(tbl); |
624 | !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) { | 568 | if (IS_ERR(slot)) { |
625 | rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); | 569 | /* If out of memory, try again in 1/4 second */ |
626 | spin_unlock(&tbl->slot_tbl_lock); | 570 | if (slot == ERR_PTR(-ENOMEM)) |
627 | dprintk("%s enforce FIFO order\n", __func__); | 571 | task->tk_timeout = HZ >> 2; |
628 | return -EAGAIN; | ||
629 | } | ||
630 | |||
631 | slotid = nfs4_find_slot(tbl); | ||
632 | if (slotid == NFS4_NO_SLOT) { | ||
633 | rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); | ||
634 | spin_unlock(&tbl->slot_tbl_lock); | ||
635 | dprintk("<-- %s: no free slots\n", __func__); | 572 | dprintk("<-- %s: no free slots\n", __func__); |
636 | return -EAGAIN; | 573 | goto out_sleep; |
637 | } | 574 | } |
638 | spin_unlock(&tbl->slot_tbl_lock); | 575 | spin_unlock(&tbl->slot_tbl_lock); |
639 | 576 | ||
640 | rpc_task_set_priority(task, RPC_PRIORITY_NORMAL); | 577 | args->sa_slot = slot; |
641 | slot = tbl->slots + slotid; | ||
642 | args->sa_session = session; | ||
643 | args->sa_slotid = slotid; | ||
644 | 578 | ||
645 | dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr); | 579 | dprintk("<-- %s slotid=%d seqid=%d\n", __func__, |
580 | slot->slot_nr, slot->seq_nr); | ||
646 | 581 | ||
647 | res->sr_session = session; | ||
648 | res->sr_slot = slot; | 582 | res->sr_slot = slot; |
649 | res->sr_renewal_time = jiffies; | 583 | res->sr_timestamp = jiffies; |
650 | res->sr_status_flags = 0; | 584 | res->sr_status_flags = 0; |
651 | /* | 585 | /* |
652 | * sr_status is only set in decode_sequence, and so will remain | 586 | * sr_status is only set in decode_sequence, and so will remain |
653 | * set to 1 if an rpc level failure occurs. | 587 | * set to 1 if an rpc level failure occurs. |
654 | */ | 588 | */ |
655 | res->sr_status = 1; | 589 | res->sr_status = 1; |
590 | out_success: | ||
591 | rpc_call_start(task); | ||
656 | return 0; | 592 | return 0; |
593 | out_sleep: | ||
594 | /* Privileged tasks are queued with top priority */ | ||
595 | if (args->sa_privileged) | ||
596 | rpc_sleep_on_priority(&tbl->slot_tbl_waitq, task, | ||
597 | NULL, RPC_PRIORITY_PRIVILEGED); | ||
598 | else | ||
599 | rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); | ||
600 | spin_unlock(&tbl->slot_tbl_lock); | ||
601 | return -EAGAIN; | ||
657 | } | 602 | } |
658 | EXPORT_SYMBOL_GPL(nfs41_setup_sequence); | 603 | EXPORT_SYMBOL_GPL(nfs41_setup_sequence); |
659 | 604 | ||
@@ -665,12 +610,14 @@ int nfs4_setup_sequence(const struct nfs_server *server, | |||
665 | struct nfs4_session *session = nfs4_get_session(server); | 610 | struct nfs4_session *session = nfs4_get_session(server); |
666 | int ret = 0; | 611 | int ret = 0; |
667 | 612 | ||
668 | if (session == NULL) | 613 | if (session == NULL) { |
614 | rpc_call_start(task); | ||
669 | goto out; | 615 | goto out; |
616 | } | ||
670 | 617 | ||
671 | dprintk("--> %s clp %p session %p sr_slot %td\n", | 618 | dprintk("--> %s clp %p session %p sr_slot %d\n", |
672 | __func__, session->clp, session, res->sr_slot ? | 619 | __func__, session->clp, session, res->sr_slot ? |
673 | res->sr_slot - session->fc_slot_table.slots : -1); | 620 | res->sr_slot->slot_nr : -1); |
674 | 621 | ||
675 | ret = nfs41_setup_sequence(session, args, res, task); | 622 | ret = nfs41_setup_sequence(session, args, res, task); |
676 | out: | 623 | out: |
@@ -687,19 +634,11 @@ struct nfs41_call_sync_data { | |||
687 | static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) | 634 | static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) |
688 | { | 635 | { |
689 | struct nfs41_call_sync_data *data = calldata; | 636 | struct nfs41_call_sync_data *data = calldata; |
637 | struct nfs4_session *session = nfs4_get_session(data->seq_server); | ||
690 | 638 | ||
691 | dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server); | 639 | dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server); |
692 | 640 | ||
693 | if (nfs4_setup_sequence(data->seq_server, data->seq_args, | 641 | nfs41_setup_sequence(session, data->seq_args, data->seq_res, task); |
694 | data->seq_res, task)) | ||
695 | return; | ||
696 | rpc_call_start(task); | ||
697 | } | ||
698 | |||
699 | static void nfs41_call_priv_sync_prepare(struct rpc_task *task, void *calldata) | ||
700 | { | ||
701 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
702 | nfs41_call_sync_prepare(task, calldata); | ||
703 | } | 642 | } |
704 | 643 | ||
705 | static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) | 644 | static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) |
@@ -714,17 +653,11 @@ static const struct rpc_call_ops nfs41_call_sync_ops = { | |||
714 | .rpc_call_done = nfs41_call_sync_done, | 653 | .rpc_call_done = nfs41_call_sync_done, |
715 | }; | 654 | }; |
716 | 655 | ||
717 | static const struct rpc_call_ops nfs41_call_priv_sync_ops = { | ||
718 | .rpc_call_prepare = nfs41_call_priv_sync_prepare, | ||
719 | .rpc_call_done = nfs41_call_sync_done, | ||
720 | }; | ||
721 | |||
722 | static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | 656 | static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, |
723 | struct nfs_server *server, | 657 | struct nfs_server *server, |
724 | struct rpc_message *msg, | 658 | struct rpc_message *msg, |
725 | struct nfs4_sequence_args *args, | 659 | struct nfs4_sequence_args *args, |
726 | struct nfs4_sequence_res *res, | 660 | struct nfs4_sequence_res *res) |
727 | int privileged) | ||
728 | { | 661 | { |
729 | int ret; | 662 | int ret; |
730 | struct rpc_task *task; | 663 | struct rpc_task *task; |
@@ -740,8 +673,6 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | |||
740 | .callback_data = &data | 673 | .callback_data = &data |
741 | }; | 674 | }; |
742 | 675 | ||
743 | if (privileged) | ||
744 | task_setup.callback_ops = &nfs41_call_priv_sync_ops; | ||
745 | task = rpc_run_task(&task_setup); | 676 | task = rpc_run_task(&task_setup); |
746 | if (IS_ERR(task)) | 677 | if (IS_ERR(task)) |
747 | ret = PTR_ERR(task); | 678 | ret = PTR_ERR(task); |
@@ -752,24 +683,18 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, | |||
752 | return ret; | 683 | return ret; |
753 | } | 684 | } |
754 | 685 | ||
755 | int _nfs4_call_sync_session(struct rpc_clnt *clnt, | ||
756 | struct nfs_server *server, | ||
757 | struct rpc_message *msg, | ||
758 | struct nfs4_sequence_args *args, | ||
759 | struct nfs4_sequence_res *res, | ||
760 | int cache_reply) | ||
761 | { | ||
762 | nfs41_init_sequence(args, res, cache_reply); | ||
763 | return nfs4_call_sync_sequence(clnt, server, msg, args, res, 0); | ||
764 | } | ||
765 | |||
766 | #else | 686 | #else |
767 | static inline | 687 | static |
768 | void nfs41_init_sequence(struct nfs4_sequence_args *args, | 688 | void nfs41_init_sequence(struct nfs4_sequence_args *args, |
769 | struct nfs4_sequence_res *res, int cache_reply) | 689 | struct nfs4_sequence_res *res, int cache_reply) |
770 | { | 690 | { |
771 | } | 691 | } |
772 | 692 | ||
693 | static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args) | ||
694 | { | ||
695 | } | ||
696 | |||
697 | |||
773 | static int nfs4_sequence_done(struct rpc_task *task, | 698 | static int nfs4_sequence_done(struct rpc_task *task, |
774 | struct nfs4_sequence_res *res) | 699 | struct nfs4_sequence_res *res) |
775 | { | 700 | { |
@@ -777,18 +702,17 @@ static int nfs4_sequence_done(struct rpc_task *task, | |||
777 | } | 702 | } |
778 | #endif /* CONFIG_NFS_V4_1 */ | 703 | #endif /* CONFIG_NFS_V4_1 */ |
779 | 704 | ||
705 | static | ||
780 | int _nfs4_call_sync(struct rpc_clnt *clnt, | 706 | int _nfs4_call_sync(struct rpc_clnt *clnt, |
781 | struct nfs_server *server, | 707 | struct nfs_server *server, |
782 | struct rpc_message *msg, | 708 | struct rpc_message *msg, |
783 | struct nfs4_sequence_args *args, | 709 | struct nfs4_sequence_args *args, |
784 | struct nfs4_sequence_res *res, | 710 | struct nfs4_sequence_res *res) |
785 | int cache_reply) | ||
786 | { | 711 | { |
787 | nfs41_init_sequence(args, res, cache_reply); | ||
788 | return rpc_call_sync(clnt, msg, 0); | 712 | return rpc_call_sync(clnt, msg, 0); |
789 | } | 713 | } |
790 | 714 | ||
791 | static inline | 715 | static |
792 | int nfs4_call_sync(struct rpc_clnt *clnt, | 716 | int nfs4_call_sync(struct rpc_clnt *clnt, |
793 | struct nfs_server *server, | 717 | struct nfs_server *server, |
794 | struct rpc_message *msg, | 718 | struct rpc_message *msg, |
@@ -796,8 +720,9 @@ int nfs4_call_sync(struct rpc_clnt *clnt, | |||
796 | struct nfs4_sequence_res *res, | 720 | struct nfs4_sequence_res *res, |
797 | int cache_reply) | 721 | int cache_reply) |
798 | { | 722 | { |
723 | nfs41_init_sequence(args, res, cache_reply); | ||
799 | return server->nfs_client->cl_mvops->call_sync(clnt, server, msg, | 724 | return server->nfs_client->cl_mvops->call_sync(clnt, server, msg, |
800 | args, res, cache_reply); | 725 | args, res); |
801 | } | 726 | } |
802 | 727 | ||
803 | static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) | 728 | static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) |
@@ -1445,13 +1370,6 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state | |||
1445 | nfs_inode_find_state_and_recover(state->inode, | 1370 | nfs_inode_find_state_and_recover(state->inode, |
1446 | stateid); | 1371 | stateid); |
1447 | nfs4_schedule_stateid_recovery(server, state); | 1372 | nfs4_schedule_stateid_recovery(server, state); |
1448 | case -EKEYEXPIRED: | ||
1449 | /* | ||
1450 | * User RPCSEC_GSS context has expired. | ||
1451 | * We cannot recover this stateid now, so | ||
1452 | * skip it and allow recovery thread to | ||
1453 | * proceed. | ||
1454 | */ | ||
1455 | case -ENOMEM: | 1373 | case -ENOMEM: |
1456 | err = 0; | 1374 | err = 0; |
1457 | goto out; | 1375 | goto out; |
@@ -1574,20 +1492,12 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
1574 | &data->o_res.seq_res, | 1492 | &data->o_res.seq_res, |
1575 | task) != 0) | 1493 | task) != 0) |
1576 | nfs_release_seqid(data->o_arg.seqid); | 1494 | nfs_release_seqid(data->o_arg.seqid); |
1577 | else | ||
1578 | rpc_call_start(task); | ||
1579 | return; | 1495 | return; |
1580 | unlock_no_action: | 1496 | unlock_no_action: |
1581 | rcu_read_unlock(); | 1497 | rcu_read_unlock(); |
1582 | out_no_action: | 1498 | out_no_action: |
1583 | task->tk_action = NULL; | 1499 | task->tk_action = NULL; |
1584 | 1500 | nfs4_sequence_done(task, &data->o_res.seq_res); | |
1585 | } | ||
1586 | |||
1587 | static void nfs4_recover_open_prepare(struct rpc_task *task, void *calldata) | ||
1588 | { | ||
1589 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
1590 | nfs4_open_prepare(task, calldata); | ||
1591 | } | 1501 | } |
1592 | 1502 | ||
1593 | static void nfs4_open_done(struct rpc_task *task, void *calldata) | 1503 | static void nfs4_open_done(struct rpc_task *task, void *calldata) |
@@ -1648,12 +1558,6 @@ static const struct rpc_call_ops nfs4_open_ops = { | |||
1648 | .rpc_release = nfs4_open_release, | 1558 | .rpc_release = nfs4_open_release, |
1649 | }; | 1559 | }; |
1650 | 1560 | ||
1651 | static const struct rpc_call_ops nfs4_recover_open_ops = { | ||
1652 | .rpc_call_prepare = nfs4_recover_open_prepare, | ||
1653 | .rpc_call_done = nfs4_open_done, | ||
1654 | .rpc_release = nfs4_open_release, | ||
1655 | }; | ||
1656 | |||
1657 | static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover) | 1561 | static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover) |
1658 | { | 1562 | { |
1659 | struct inode *dir = data->dir->d_inode; | 1563 | struct inode *dir = data->dir->d_inode; |
@@ -1683,7 +1587,7 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover) | |||
1683 | data->rpc_status = 0; | 1587 | data->rpc_status = 0; |
1684 | data->cancelled = 0; | 1588 | data->cancelled = 0; |
1685 | if (isrecover) | 1589 | if (isrecover) |
1686 | task_setup_data.callback_ops = &nfs4_recover_open_ops; | 1590 | nfs4_set_sequence_privileged(&o_arg->seq_args); |
1687 | task = rpc_run_task(&task_setup_data); | 1591 | task = rpc_run_task(&task_setup_data); |
1688 | if (IS_ERR(task)) | 1592 | if (IS_ERR(task)) |
1689 | return PTR_ERR(task); | 1593 | return PTR_ERR(task); |
@@ -1789,24 +1693,6 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
1789 | return 0; | 1693 | return 0; |
1790 | } | 1694 | } |
1791 | 1695 | ||
1792 | static int nfs4_client_recover_expired_lease(struct nfs_client *clp) | ||
1793 | { | ||
1794 | unsigned int loop; | ||
1795 | int ret; | ||
1796 | |||
1797 | for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) { | ||
1798 | ret = nfs4_wait_clnt_recover(clp); | ||
1799 | if (ret != 0) | ||
1800 | break; | ||
1801 | if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) && | ||
1802 | !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state)) | ||
1803 | break; | ||
1804 | nfs4_schedule_state_manager(clp); | ||
1805 | ret = -EIO; | ||
1806 | } | ||
1807 | return ret; | ||
1808 | } | ||
1809 | |||
1810 | static int nfs4_recover_expired_lease(struct nfs_server *server) | 1696 | static int nfs4_recover_expired_lease(struct nfs_server *server) |
1811 | { | 1697 | { |
1812 | return nfs4_client_recover_expired_lease(server->nfs_client); | 1698 | return nfs4_client_recover_expired_lease(server->nfs_client); |
@@ -2282,6 +2168,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2282 | if (!call_close) { | 2168 | if (!call_close) { |
2283 | /* Note: exit _without_ calling nfs4_close_done */ | 2169 | /* Note: exit _without_ calling nfs4_close_done */ |
2284 | task->tk_action = NULL; | 2170 | task->tk_action = NULL; |
2171 | nfs4_sequence_done(task, &calldata->res.seq_res); | ||
2285 | goto out; | 2172 | goto out; |
2286 | } | 2173 | } |
2287 | 2174 | ||
@@ -2299,8 +2186,6 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2299 | &calldata->res.seq_res, | 2186 | &calldata->res.seq_res, |
2300 | task) != 0) | 2187 | task) != 0) |
2301 | nfs_release_seqid(calldata->arg.seqid); | 2188 | nfs_release_seqid(calldata->arg.seqid); |
2302 | else | ||
2303 | rpc_call_start(task); | ||
2304 | out: | 2189 | out: |
2305 | dprintk("%s: done!\n", __func__); | 2190 | dprintk("%s: done!\n", __func__); |
2306 | } | 2191 | } |
@@ -2533,7 +2418,8 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2533 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS]; | 2418 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS]; |
2534 | 2419 | ||
2535 | len = rpcauth_list_flavors(flav_array, ARRAY_SIZE(flav_array)); | 2420 | len = rpcauth_list_flavors(flav_array, ARRAY_SIZE(flav_array)); |
2536 | BUG_ON(len < 0); | 2421 | if (len < 0) |
2422 | return len; | ||
2537 | 2423 | ||
2538 | for (i = 0; i < len; i++) { | 2424 | for (i = 0; i < len; i++) { |
2539 | /* AUTH_UNIX is the default flavor if none was specified, | 2425 | /* AUTH_UNIX is the default flavor if none was specified, |
@@ -3038,12 +2924,10 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) | |||
3038 | 2924 | ||
3039 | static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) | 2925 | static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) |
3040 | { | 2926 | { |
3041 | if (nfs4_setup_sequence(NFS_SERVER(data->dir), | 2927 | nfs4_setup_sequence(NFS_SERVER(data->dir), |
3042 | &data->args.seq_args, | 2928 | &data->args.seq_args, |
3043 | &data->res.seq_res, | 2929 | &data->res.seq_res, |
3044 | task)) | 2930 | task); |
3045 | return; | ||
3046 | rpc_call_start(task); | ||
3047 | } | 2931 | } |
3048 | 2932 | ||
3049 | static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) | 2933 | static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) |
@@ -3071,12 +2955,10 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir) | |||
3071 | 2955 | ||
3072 | static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data) | 2956 | static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data) |
3073 | { | 2957 | { |
3074 | if (nfs4_setup_sequence(NFS_SERVER(data->old_dir), | 2958 | nfs4_setup_sequence(NFS_SERVER(data->old_dir), |
3075 | &data->args.seq_args, | 2959 | &data->args.seq_args, |
3076 | &data->res.seq_res, | 2960 | &data->res.seq_res, |
3077 | task)) | 2961 | task); |
3078 | return; | ||
3079 | rpc_call_start(task); | ||
3080 | } | 2962 | } |
3081 | 2963 | ||
3082 | static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, | 2964 | static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, |
@@ -3362,9 +3244,6 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
3362 | int mode = sattr->ia_mode; | 3244 | int mode = sattr->ia_mode; |
3363 | int status = -ENOMEM; | 3245 | int status = -ENOMEM; |
3364 | 3246 | ||
3365 | BUG_ON(!(sattr->ia_valid & ATTR_MODE)); | ||
3366 | BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode)); | ||
3367 | |||
3368 | data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4SOCK); | 3247 | data = nfs4_alloc_createdata(dir, &dentry->d_name, sattr, NF4SOCK); |
3369 | if (data == NULL) | 3248 | if (data == NULL) |
3370 | goto out; | 3249 | goto out; |
@@ -3380,10 +3259,13 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
3380 | data->arg.ftype = NF4CHR; | 3259 | data->arg.ftype = NF4CHR; |
3381 | data->arg.u.device.specdata1 = MAJOR(rdev); | 3260 | data->arg.u.device.specdata1 = MAJOR(rdev); |
3382 | data->arg.u.device.specdata2 = MINOR(rdev); | 3261 | data->arg.u.device.specdata2 = MINOR(rdev); |
3262 | } else if (!S_ISSOCK(mode)) { | ||
3263 | status = -EINVAL; | ||
3264 | goto out_free; | ||
3383 | } | 3265 | } |
3384 | 3266 | ||
3385 | status = nfs4_do_create(dir, dentry, data); | 3267 | status = nfs4_do_create(dir, dentry, data); |
3386 | 3268 | out_free: | |
3387 | nfs4_free_createdata(data); | 3269 | nfs4_free_createdata(data); |
3388 | out: | 3270 | out: |
3389 | return status; | 3271 | return status; |
@@ -3565,12 +3447,10 @@ static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message | |||
3565 | 3447 | ||
3566 | static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) | 3448 | static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) |
3567 | { | 3449 | { |
3568 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), | 3450 | nfs4_setup_sequence(NFS_SERVER(data->header->inode), |
3569 | &data->args.seq_args, | 3451 | &data->args.seq_args, |
3570 | &data->res.seq_res, | 3452 | &data->res.seq_res, |
3571 | task)) | 3453 | task); |
3572 | return; | ||
3573 | rpc_call_start(task); | ||
3574 | } | 3454 | } |
3575 | 3455 | ||
3576 | static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data) | 3456 | static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data) |
@@ -3631,22 +3511,18 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag | |||
3631 | 3511 | ||
3632 | static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) | 3512 | static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) |
3633 | { | 3513 | { |
3634 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), | 3514 | nfs4_setup_sequence(NFS_SERVER(data->header->inode), |
3635 | &data->args.seq_args, | 3515 | &data->args.seq_args, |
3636 | &data->res.seq_res, | 3516 | &data->res.seq_res, |
3637 | task)) | 3517 | task); |
3638 | return; | ||
3639 | rpc_call_start(task); | ||
3640 | } | 3518 | } |
3641 | 3519 | ||
3642 | static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) | 3520 | static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) |
3643 | { | 3521 | { |
3644 | if (nfs4_setup_sequence(NFS_SERVER(data->inode), | 3522 | nfs4_setup_sequence(NFS_SERVER(data->inode), |
3645 | &data->args.seq_args, | 3523 | &data->args.seq_args, |
3646 | &data->res.seq_res, | 3524 | &data->res.seq_res, |
3647 | task)) | 3525 | task); |
3648 | return; | ||
3649 | rpc_call_start(task); | ||
3650 | } | 3526 | } |
3651 | 3527 | ||
3652 | static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *data) | 3528 | static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *data) |
@@ -3937,8 +3813,13 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
3937 | goto out_free; | 3813 | goto out_free; |
3938 | } | 3814 | } |
3939 | nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len); | 3815 | nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len); |
3940 | if (buf) | 3816 | if (buf) { |
3817 | if (res.acl_len > buflen) { | ||
3818 | ret = -ERANGE; | ||
3819 | goto out_free; | ||
3820 | } | ||
3941 | _copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len); | 3821 | _copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len); |
3822 | } | ||
3942 | out_ok: | 3823 | out_ok: |
3943 | ret = res.acl_len; | 3824 | ret = res.acl_len; |
3944 | out_free: | 3825 | out_free: |
@@ -4085,7 +3966,6 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
4085 | case -NFS4ERR_DELAY: | 3966 | case -NFS4ERR_DELAY: |
4086 | nfs_inc_server_stats(server, NFSIOS_DELAY); | 3967 | nfs_inc_server_stats(server, NFSIOS_DELAY); |
4087 | case -NFS4ERR_GRACE: | 3968 | case -NFS4ERR_GRACE: |
4088 | case -EKEYEXPIRED: | ||
4089 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 3969 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
4090 | task->tk_status = 0; | 3970 | task->tk_status = 0; |
4091 | return -EAGAIN; | 3971 | return -EAGAIN; |
@@ -4293,11 +4173,10 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data) | |||
4293 | 4173 | ||
4294 | d_data = (struct nfs4_delegreturndata *)data; | 4174 | d_data = (struct nfs4_delegreturndata *)data; |
4295 | 4175 | ||
4296 | if (nfs4_setup_sequence(d_data->res.server, | 4176 | nfs4_setup_sequence(d_data->res.server, |
4297 | &d_data->args.seq_args, | 4177 | &d_data->args.seq_args, |
4298 | &d_data->res.seq_res, task)) | 4178 | &d_data->res.seq_res, |
4299 | return; | 4179 | task); |
4300 | rpc_call_start(task); | ||
4301 | } | 4180 | } |
4302 | #endif /* CONFIG_NFS_V4_1 */ | 4181 | #endif /* CONFIG_NFS_V4_1 */ |
4303 | 4182 | ||
@@ -4543,6 +4422,7 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) | |||
4543 | if (test_bit(NFS_LOCK_INITIALIZED, &calldata->lsp->ls_flags) == 0) { | 4422 | if (test_bit(NFS_LOCK_INITIALIZED, &calldata->lsp->ls_flags) == 0) { |
4544 | /* Note: exit _without_ running nfs4_locku_done */ | 4423 | /* Note: exit _without_ running nfs4_locku_done */ |
4545 | task->tk_action = NULL; | 4424 | task->tk_action = NULL; |
4425 | nfs4_sequence_done(task, &calldata->res.seq_res); | ||
4546 | return; | 4426 | return; |
4547 | } | 4427 | } |
4548 | calldata->timestamp = jiffies; | 4428 | calldata->timestamp = jiffies; |
@@ -4551,8 +4431,6 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) | |||
4551 | &calldata->res.seq_res, | 4431 | &calldata->res.seq_res, |
4552 | task) != 0) | 4432 | task) != 0) |
4553 | nfs_release_seqid(calldata->arg.seqid); | 4433 | nfs_release_seqid(calldata->arg.seqid); |
4554 | else | ||
4555 | rpc_call_start(task); | ||
4556 | } | 4434 | } |
4557 | 4435 | ||
4558 | static const struct rpc_call_ops nfs4_locku_ops = { | 4436 | static const struct rpc_call_ops nfs4_locku_ops = { |
@@ -4696,8 +4574,9 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) | |||
4696 | return; | 4574 | return; |
4697 | /* Do we need to do an open_to_lock_owner? */ | 4575 | /* Do we need to do an open_to_lock_owner? */ |
4698 | if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { | 4576 | if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { |
4699 | if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) | 4577 | if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) { |
4700 | goto out_release_lock_seqid; | 4578 | goto out_release_lock_seqid; |
4579 | } | ||
4701 | data->arg.open_stateid = &state->stateid; | 4580 | data->arg.open_stateid = &state->stateid; |
4702 | data->arg.new_lock_owner = 1; | 4581 | data->arg.new_lock_owner = 1; |
4703 | data->res.open_seqid = data->arg.open_seqid; | 4582 | data->res.open_seqid = data->arg.open_seqid; |
@@ -4707,20 +4586,12 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) | |||
4707 | if (nfs4_setup_sequence(data->server, | 4586 | if (nfs4_setup_sequence(data->server, |
4708 | &data->arg.seq_args, | 4587 | &data->arg.seq_args, |
4709 | &data->res.seq_res, | 4588 | &data->res.seq_res, |
4710 | task) == 0) { | 4589 | task) == 0) |
4711 | rpc_call_start(task); | ||
4712 | return; | 4590 | return; |
4713 | } | ||
4714 | nfs_release_seqid(data->arg.open_seqid); | 4591 | nfs_release_seqid(data->arg.open_seqid); |
4715 | out_release_lock_seqid: | 4592 | out_release_lock_seqid: |
4716 | nfs_release_seqid(data->arg.lock_seqid); | 4593 | nfs_release_seqid(data->arg.lock_seqid); |
4717 | dprintk("%s: done!, ret = %d\n", __func__, task->tk_status); | 4594 | dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); |
4718 | } | ||
4719 | |||
4720 | static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata) | ||
4721 | { | ||
4722 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
4723 | nfs4_lock_prepare(task, calldata); | ||
4724 | } | 4595 | } |
4725 | 4596 | ||
4726 | static void nfs4_lock_done(struct rpc_task *task, void *calldata) | 4597 | static void nfs4_lock_done(struct rpc_task *task, void *calldata) |
@@ -4775,12 +4646,6 @@ static const struct rpc_call_ops nfs4_lock_ops = { | |||
4775 | .rpc_release = nfs4_lock_release, | 4646 | .rpc_release = nfs4_lock_release, |
4776 | }; | 4647 | }; |
4777 | 4648 | ||
4778 | static const struct rpc_call_ops nfs4_recover_lock_ops = { | ||
4779 | .rpc_call_prepare = nfs4_recover_lock_prepare, | ||
4780 | .rpc_call_done = nfs4_lock_done, | ||
4781 | .rpc_release = nfs4_lock_release, | ||
4782 | }; | ||
4783 | |||
4784 | static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error) | 4649 | static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error) |
4785 | { | 4650 | { |
4786 | switch (error) { | 4651 | switch (error) { |
@@ -4823,15 +4688,15 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
4823 | return -ENOMEM; | 4688 | return -ENOMEM; |
4824 | if (IS_SETLKW(cmd)) | 4689 | if (IS_SETLKW(cmd)) |
4825 | data->arg.block = 1; | 4690 | data->arg.block = 1; |
4826 | if (recovery_type > NFS_LOCK_NEW) { | ||
4827 | if (recovery_type == NFS_LOCK_RECLAIM) | ||
4828 | data->arg.reclaim = NFS_LOCK_RECLAIM; | ||
4829 | task_setup_data.callback_ops = &nfs4_recover_lock_ops; | ||
4830 | } | ||
4831 | nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); | 4691 | nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); |
4832 | msg.rpc_argp = &data->arg; | 4692 | msg.rpc_argp = &data->arg; |
4833 | msg.rpc_resp = &data->res; | 4693 | msg.rpc_resp = &data->res; |
4834 | task_setup_data.callback_data = data; | 4694 | task_setup_data.callback_data = data; |
4695 | if (recovery_type > NFS_LOCK_NEW) { | ||
4696 | if (recovery_type == NFS_LOCK_RECLAIM) | ||
4697 | data->arg.reclaim = NFS_LOCK_RECLAIM; | ||
4698 | nfs4_set_sequence_privileged(&data->arg.seq_args); | ||
4699 | } | ||
4835 | task = rpc_run_task(&task_setup_data); | 4700 | task = rpc_run_task(&task_setup_data); |
4836 | if (IS_ERR(task)) | 4701 | if (IS_ERR(task)) |
4837 | return PTR_ERR(task); | 4702 | return PTR_ERR(task); |
@@ -5100,15 +4965,6 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) | |||
5100 | nfs4_schedule_stateid_recovery(server, state); | 4965 | nfs4_schedule_stateid_recovery(server, state); |
5101 | err = 0; | 4966 | err = 0; |
5102 | goto out; | 4967 | goto out; |
5103 | case -EKEYEXPIRED: | ||
5104 | /* | ||
5105 | * User RPCSEC_GSS context has expired. | ||
5106 | * We cannot recover this stateid now, so | ||
5107 | * skip it and allow recovery thread to | ||
5108 | * proceed. | ||
5109 | */ | ||
5110 | err = 0; | ||
5111 | goto out; | ||
5112 | case -ENOMEM: | 4968 | case -ENOMEM: |
5113 | case -NFS4ERR_DENIED: | 4969 | case -NFS4ERR_DENIED: |
5114 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ | 4970 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ |
@@ -5357,7 +5213,6 @@ int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred | |||
5357 | }; | 5213 | }; |
5358 | 5214 | ||
5359 | dprintk("--> %s\n", __func__); | 5215 | dprintk("--> %s\n", __func__); |
5360 | BUG_ON(clp == NULL); | ||
5361 | 5216 | ||
5362 | res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); | 5217 | res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); |
5363 | if (unlikely(res.session == NULL)) { | 5218 | if (unlikely(res.session == NULL)) { |
@@ -5569,20 +5424,16 @@ struct nfs4_get_lease_time_data { | |||
5569 | static void nfs4_get_lease_time_prepare(struct rpc_task *task, | 5424 | static void nfs4_get_lease_time_prepare(struct rpc_task *task, |
5570 | void *calldata) | 5425 | void *calldata) |
5571 | { | 5426 | { |
5572 | int ret; | ||
5573 | struct nfs4_get_lease_time_data *data = | 5427 | struct nfs4_get_lease_time_data *data = |
5574 | (struct nfs4_get_lease_time_data *)calldata; | 5428 | (struct nfs4_get_lease_time_data *)calldata; |
5575 | 5429 | ||
5576 | dprintk("--> %s\n", __func__); | 5430 | dprintk("--> %s\n", __func__); |
5577 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
5578 | /* just setup sequence, do not trigger session recovery | 5431 | /* just setup sequence, do not trigger session recovery |
5579 | since we're invoked within one */ | 5432 | since we're invoked within one */ |
5580 | ret = nfs41_setup_sequence(data->clp->cl_session, | 5433 | nfs41_setup_sequence(data->clp->cl_session, |
5581 | &data->args->la_seq_args, | 5434 | &data->args->la_seq_args, |
5582 | &data->res->lr_seq_res, task); | 5435 | &data->res->lr_seq_res, |
5583 | 5436 | task); | |
5584 | BUG_ON(ret == -EAGAIN); | ||
5585 | rpc_call_start(task); | ||
5586 | dprintk("<-- %s\n", __func__); | 5437 | dprintk("<-- %s\n", __func__); |
5587 | } | 5438 | } |
5588 | 5439 | ||
@@ -5644,6 +5495,7 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
5644 | int status; | 5495 | int status; |
5645 | 5496 | ||
5646 | nfs41_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0); | 5497 | nfs41_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0); |
5498 | nfs4_set_sequence_privileged(&args.la_seq_args); | ||
5647 | dprintk("--> %s\n", __func__); | 5499 | dprintk("--> %s\n", __func__); |
5648 | task = rpc_run_task(&task_setup); | 5500 | task = rpc_run_task(&task_setup); |
5649 | 5501 | ||
@@ -5658,145 +5510,6 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
5658 | return status; | 5510 | return status; |
5659 | } | 5511 | } |
5660 | 5512 | ||
5661 | static struct nfs4_slot *nfs4_alloc_slots(u32 max_slots, gfp_t gfp_flags) | ||
5662 | { | ||
5663 | return kcalloc(max_slots, sizeof(struct nfs4_slot), gfp_flags); | ||
5664 | } | ||
5665 | |||
5666 | static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl, | ||
5667 | struct nfs4_slot *new, | ||
5668 | u32 max_slots, | ||
5669 | u32 ivalue) | ||
5670 | { | ||
5671 | struct nfs4_slot *old = NULL; | ||
5672 | u32 i; | ||
5673 | |||
5674 | spin_lock(&tbl->slot_tbl_lock); | ||
5675 | if (new) { | ||
5676 | old = tbl->slots; | ||
5677 | tbl->slots = new; | ||
5678 | tbl->max_slots = max_slots; | ||
5679 | } | ||
5680 | tbl->highest_used_slotid = NFS4_NO_SLOT; | ||
5681 | for (i = 0; i < tbl->max_slots; i++) | ||
5682 | tbl->slots[i].seq_nr = ivalue; | ||
5683 | spin_unlock(&tbl->slot_tbl_lock); | ||
5684 | kfree(old); | ||
5685 | } | ||
5686 | |||
5687 | /* | ||
5688 | * (re)Initialise a slot table | ||
5689 | */ | ||
5690 | static int nfs4_realloc_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs, | ||
5691 | u32 ivalue) | ||
5692 | { | ||
5693 | struct nfs4_slot *new = NULL; | ||
5694 | int ret = -ENOMEM; | ||
5695 | |||
5696 | dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__, | ||
5697 | max_reqs, tbl->max_slots); | ||
5698 | |||
5699 | /* Does the newly negotiated max_reqs match the existing slot table? */ | ||
5700 | if (max_reqs != tbl->max_slots) { | ||
5701 | new = nfs4_alloc_slots(max_reqs, GFP_NOFS); | ||
5702 | if (!new) | ||
5703 | goto out; | ||
5704 | } | ||
5705 | ret = 0; | ||
5706 | |||
5707 | nfs4_add_and_init_slots(tbl, new, max_reqs, ivalue); | ||
5708 | dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, | ||
5709 | tbl, tbl->slots, tbl->max_slots); | ||
5710 | out: | ||
5711 | dprintk("<-- %s: return %d\n", __func__, ret); | ||
5712 | return ret; | ||
5713 | } | ||
5714 | |||
5715 | /* Destroy the slot table */ | ||
5716 | static void nfs4_destroy_slot_tables(struct nfs4_session *session) | ||
5717 | { | ||
5718 | if (session->fc_slot_table.slots != NULL) { | ||
5719 | kfree(session->fc_slot_table.slots); | ||
5720 | session->fc_slot_table.slots = NULL; | ||
5721 | } | ||
5722 | if (session->bc_slot_table.slots != NULL) { | ||
5723 | kfree(session->bc_slot_table.slots); | ||
5724 | session->bc_slot_table.slots = NULL; | ||
5725 | } | ||
5726 | return; | ||
5727 | } | ||
5728 | |||
5729 | /* | ||
5730 | * Initialize or reset the forechannel and backchannel tables | ||
5731 | */ | ||
5732 | static int nfs4_setup_session_slot_tables(struct nfs4_session *ses) | ||
5733 | { | ||
5734 | struct nfs4_slot_table *tbl; | ||
5735 | int status; | ||
5736 | |||
5737 | dprintk("--> %s\n", __func__); | ||
5738 | /* Fore channel */ | ||
5739 | tbl = &ses->fc_slot_table; | ||
5740 | status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1); | ||
5741 | if (status) /* -ENOMEM */ | ||
5742 | return status; | ||
5743 | /* Back channel */ | ||
5744 | tbl = &ses->bc_slot_table; | ||
5745 | status = nfs4_realloc_slot_table(tbl, ses->bc_attrs.max_reqs, 0); | ||
5746 | if (status && tbl->slots == NULL) | ||
5747 | /* Fore and back channel share a connection so get | ||
5748 | * both slot tables or neither */ | ||
5749 | nfs4_destroy_slot_tables(ses); | ||
5750 | return status; | ||
5751 | } | ||
5752 | |||
5753 | struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | ||
5754 | { | ||
5755 | struct nfs4_session *session; | ||
5756 | struct nfs4_slot_table *tbl; | ||
5757 | |||
5758 | session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); | ||
5759 | if (!session) | ||
5760 | return NULL; | ||
5761 | |||
5762 | tbl = &session->fc_slot_table; | ||
5763 | tbl->highest_used_slotid = NFS4_NO_SLOT; | ||
5764 | spin_lock_init(&tbl->slot_tbl_lock); | ||
5765 | rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table"); | ||
5766 | init_completion(&tbl->complete); | ||
5767 | |||
5768 | tbl = &session->bc_slot_table; | ||
5769 | tbl->highest_used_slotid = NFS4_NO_SLOT; | ||
5770 | spin_lock_init(&tbl->slot_tbl_lock); | ||
5771 | rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table"); | ||
5772 | init_completion(&tbl->complete); | ||
5773 | |||
5774 | session->session_state = 1<<NFS4_SESSION_INITING; | ||
5775 | |||
5776 | session->clp = clp; | ||
5777 | return session; | ||
5778 | } | ||
5779 | |||
5780 | void nfs4_destroy_session(struct nfs4_session *session) | ||
5781 | { | ||
5782 | struct rpc_xprt *xprt; | ||
5783 | struct rpc_cred *cred; | ||
5784 | |||
5785 | cred = nfs4_get_exchange_id_cred(session->clp); | ||
5786 | nfs4_proc_destroy_session(session, cred); | ||
5787 | if (cred) | ||
5788 | put_rpccred(cred); | ||
5789 | |||
5790 | rcu_read_lock(); | ||
5791 | xprt = rcu_dereference(session->clp->cl_rpcclient->cl_xprt); | ||
5792 | rcu_read_unlock(); | ||
5793 | dprintk("%s Destroy backchannel for xprt %p\n", | ||
5794 | __func__, xprt); | ||
5795 | xprt_destroy_backchannel(xprt, NFS41_BC_MIN_CALLBACKS); | ||
5796 | nfs4_destroy_slot_tables(session); | ||
5797 | kfree(session); | ||
5798 | } | ||
5799 | |||
5800 | /* | 5513 | /* |
5801 | * Initialize the values to be used by the client in CREATE_SESSION | 5514 | * Initialize the values to be used by the client in CREATE_SESSION |
5802 | * If nfs4_init_session set the fore channel request and response sizes, | 5515 | * If nfs4_init_session set the fore channel request and response sizes, |
@@ -5809,8 +5522,8 @@ void nfs4_destroy_session(struct nfs4_session *session) | |||
5809 | static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) | 5522 | static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) |
5810 | { | 5523 | { |
5811 | struct nfs4_session *session = args->client->cl_session; | 5524 | struct nfs4_session *session = args->client->cl_session; |
5812 | unsigned int mxrqst_sz = session->fc_attrs.max_rqst_sz, | 5525 | unsigned int mxrqst_sz = session->fc_target_max_rqst_sz, |
5813 | mxresp_sz = session->fc_attrs.max_resp_sz; | 5526 | mxresp_sz = session->fc_target_max_resp_sz; |
5814 | 5527 | ||
5815 | if (mxrqst_sz == 0) | 5528 | if (mxrqst_sz == 0) |
5816 | mxrqst_sz = NFS_MAX_FILE_IO_SIZE; | 5529 | mxrqst_sz = NFS_MAX_FILE_IO_SIZE; |
@@ -5919,10 +5632,9 @@ static int _nfs4_proc_create_session(struct nfs_client *clp, | |||
5919 | 5632 | ||
5920 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 5633 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
5921 | 5634 | ||
5922 | if (!status) | 5635 | if (!status) { |
5923 | /* Verify the session's negotiated channel_attrs values */ | 5636 | /* Verify the session's negotiated channel_attrs values */ |
5924 | status = nfs4_verify_channel_attrs(&args, session); | 5637 | status = nfs4_verify_channel_attrs(&args, session); |
5925 | if (!status) { | ||
5926 | /* Increment the clientid slot sequence id */ | 5638 | /* Increment the clientid slot sequence id */ |
5927 | clp->cl_seqid++; | 5639 | clp->cl_seqid++; |
5928 | } | 5640 | } |
@@ -5992,83 +5704,6 @@ int nfs4_proc_destroy_session(struct nfs4_session *session, | |||
5992 | } | 5704 | } |
5993 | 5705 | ||
5994 | /* | 5706 | /* |
5995 | * With sessions, the client is not marked ready until after a | ||
5996 | * successful EXCHANGE_ID and CREATE_SESSION. | ||
5997 | * | ||
5998 | * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate | ||
5999 | * other versions of NFS can be tried. | ||
6000 | */ | ||
6001 | static int nfs41_check_session_ready(struct nfs_client *clp) | ||
6002 | { | ||
6003 | int ret; | ||
6004 | |||
6005 | if (clp->cl_cons_state == NFS_CS_SESSION_INITING) { | ||
6006 | ret = nfs4_client_recover_expired_lease(clp); | ||
6007 | if (ret) | ||
6008 | return ret; | ||
6009 | } | ||
6010 | if (clp->cl_cons_state < NFS_CS_READY) | ||
6011 | return -EPROTONOSUPPORT; | ||
6012 | smp_rmb(); | ||
6013 | return 0; | ||
6014 | } | ||
6015 | |||
6016 | int nfs4_init_session(struct nfs_server *server) | ||
6017 | { | ||
6018 | struct nfs_client *clp = server->nfs_client; | ||
6019 | struct nfs4_session *session; | ||
6020 | unsigned int rsize, wsize; | ||
6021 | |||
6022 | if (!nfs4_has_session(clp)) | ||
6023 | return 0; | ||
6024 | |||
6025 | session = clp->cl_session; | ||
6026 | spin_lock(&clp->cl_lock); | ||
6027 | if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) { | ||
6028 | |||
6029 | rsize = server->rsize; | ||
6030 | if (rsize == 0) | ||
6031 | rsize = NFS_MAX_FILE_IO_SIZE; | ||
6032 | wsize = server->wsize; | ||
6033 | if (wsize == 0) | ||
6034 | wsize = NFS_MAX_FILE_IO_SIZE; | ||
6035 | |||
6036 | session->fc_attrs.max_rqst_sz = wsize + nfs41_maxwrite_overhead; | ||
6037 | session->fc_attrs.max_resp_sz = rsize + nfs41_maxread_overhead; | ||
6038 | } | ||
6039 | spin_unlock(&clp->cl_lock); | ||
6040 | |||
6041 | return nfs41_check_session_ready(clp); | ||
6042 | } | ||
6043 | |||
6044 | int nfs4_init_ds_session(struct nfs_client *clp, unsigned long lease_time) | ||
6045 | { | ||
6046 | struct nfs4_session *session = clp->cl_session; | ||
6047 | int ret; | ||
6048 | |||
6049 | spin_lock(&clp->cl_lock); | ||
6050 | if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) { | ||
6051 | /* | ||
6052 | * Do not set NFS_CS_CHECK_LEASE_TIME instead set the | ||
6053 | * DS lease to be equal to the MDS lease. | ||
6054 | */ | ||
6055 | clp->cl_lease_time = lease_time; | ||
6056 | clp->cl_last_renewal = jiffies; | ||
6057 | } | ||
6058 | spin_unlock(&clp->cl_lock); | ||
6059 | |||
6060 | ret = nfs41_check_session_ready(clp); | ||
6061 | if (ret) | ||
6062 | return ret; | ||
6063 | /* Test for the DS role */ | ||
6064 | if (!is_ds_client(clp)) | ||
6065 | return -ENODEV; | ||
6066 | return 0; | ||
6067 | } | ||
6068 | EXPORT_SYMBOL_GPL(nfs4_init_ds_session); | ||
6069 | |||
6070 | |||
6071 | /* | ||
6072 | * Renew the cl_session lease. | 5707 | * Renew the cl_session lease. |
6073 | */ | 5708 | */ |
6074 | struct nfs4_sequence_data { | 5709 | struct nfs4_sequence_data { |
@@ -6133,9 +5768,7 @@ static void nfs41_sequence_prepare(struct rpc_task *task, void *data) | |||
6133 | args = task->tk_msg.rpc_argp; | 5768 | args = task->tk_msg.rpc_argp; |
6134 | res = task->tk_msg.rpc_resp; | 5769 | res = task->tk_msg.rpc_resp; |
6135 | 5770 | ||
6136 | if (nfs41_setup_sequence(clp->cl_session, args, res, task)) | 5771 | nfs41_setup_sequence(clp->cl_session, args, res, task); |
6137 | return; | ||
6138 | rpc_call_start(task); | ||
6139 | } | 5772 | } |
6140 | 5773 | ||
6141 | static const struct rpc_call_ops nfs41_sequence_ops = { | 5774 | static const struct rpc_call_ops nfs41_sequence_ops = { |
@@ -6144,7 +5777,9 @@ static const struct rpc_call_ops nfs41_sequence_ops = { | |||
6144 | .rpc_release = nfs41_sequence_release, | 5777 | .rpc_release = nfs41_sequence_release, |
6145 | }; | 5778 | }; |
6146 | 5779 | ||
6147 | static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) | 5780 | static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, |
5781 | struct rpc_cred *cred, | ||
5782 | bool is_privileged) | ||
6148 | { | 5783 | { |
6149 | struct nfs4_sequence_data *calldata; | 5784 | struct nfs4_sequence_data *calldata; |
6150 | struct rpc_message msg = { | 5785 | struct rpc_message msg = { |
@@ -6166,6 +5801,8 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_ | |||
6166 | return ERR_PTR(-ENOMEM); | 5801 | return ERR_PTR(-ENOMEM); |
6167 | } | 5802 | } |
6168 | nfs41_init_sequence(&calldata->args, &calldata->res, 0); | 5803 | nfs41_init_sequence(&calldata->args, &calldata->res, 0); |
5804 | if (is_privileged) | ||
5805 | nfs4_set_sequence_privileged(&calldata->args); | ||
6169 | msg.rpc_argp = &calldata->args; | 5806 | msg.rpc_argp = &calldata->args; |
6170 | msg.rpc_resp = &calldata->res; | 5807 | msg.rpc_resp = &calldata->res; |
6171 | calldata->clp = clp; | 5808 | calldata->clp = clp; |
@@ -6181,7 +5818,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr | |||
6181 | 5818 | ||
6182 | if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) | 5819 | if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) |
6183 | return 0; | 5820 | return 0; |
6184 | task = _nfs41_proc_sequence(clp, cred); | 5821 | task = _nfs41_proc_sequence(clp, cred, false); |
6185 | if (IS_ERR(task)) | 5822 | if (IS_ERR(task)) |
6186 | ret = PTR_ERR(task); | 5823 | ret = PTR_ERR(task); |
6187 | else | 5824 | else |
@@ -6195,7 +5832,7 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) | |||
6195 | struct rpc_task *task; | 5832 | struct rpc_task *task; |
6196 | int ret; | 5833 | int ret; |
6197 | 5834 | ||
6198 | task = _nfs41_proc_sequence(clp, cred); | 5835 | task = _nfs41_proc_sequence(clp, cred, true); |
6199 | if (IS_ERR(task)) { | 5836 | if (IS_ERR(task)) { |
6200 | ret = PTR_ERR(task); | 5837 | ret = PTR_ERR(task); |
6201 | goto out; | 5838 | goto out; |
@@ -6224,13 +5861,10 @@ static void nfs4_reclaim_complete_prepare(struct rpc_task *task, void *data) | |||
6224 | { | 5861 | { |
6225 | struct nfs4_reclaim_complete_data *calldata = data; | 5862 | struct nfs4_reclaim_complete_data *calldata = data; |
6226 | 5863 | ||
6227 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | 5864 | nfs41_setup_sequence(calldata->clp->cl_session, |
6228 | if (nfs41_setup_sequence(calldata->clp->cl_session, | 5865 | &calldata->arg.seq_args, |
6229 | &calldata->arg.seq_args, | 5866 | &calldata->res.seq_res, |
6230 | &calldata->res.seq_res, task)) | 5867 | task); |
6231 | return; | ||
6232 | |||
6233 | rpc_call_start(task); | ||
6234 | } | 5868 | } |
6235 | 5869 | ||
6236 | static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nfs_client *clp) | 5870 | static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nfs_client *clp) |
@@ -6307,6 +5941,7 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp) | |||
6307 | calldata->arg.one_fs = 0; | 5941 | calldata->arg.one_fs = 0; |
6308 | 5942 | ||
6309 | nfs41_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0); | 5943 | nfs41_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0); |
5944 | nfs4_set_sequence_privileged(&calldata->arg.seq_args); | ||
6310 | msg.rpc_argp = &calldata->arg; | 5945 | msg.rpc_argp = &calldata->arg; |
6311 | msg.rpc_resp = &calldata->res; | 5946 | msg.rpc_resp = &calldata->res; |
6312 | task_setup_data.callback_data = calldata; | 5947 | task_setup_data.callback_data = calldata; |
@@ -6330,6 +5965,7 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata) | |||
6330 | { | 5965 | { |
6331 | struct nfs4_layoutget *lgp = calldata; | 5966 | struct nfs4_layoutget *lgp = calldata; |
6332 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); | 5967 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); |
5968 | struct nfs4_session *session = nfs4_get_session(server); | ||
6333 | 5969 | ||
6334 | dprintk("--> %s\n", __func__); | 5970 | dprintk("--> %s\n", __func__); |
6335 | /* Note the is a race here, where a CB_LAYOUTRECALL can come in | 5971 | /* Note the is a race here, where a CB_LAYOUTRECALL can come in |
@@ -6337,16 +5973,14 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata) | |||
6337 | * However, that is not so catastrophic, and there seems | 5973 | * However, that is not so catastrophic, and there seems |
6338 | * to be no way to prevent it completely. | 5974 | * to be no way to prevent it completely. |
6339 | */ | 5975 | */ |
6340 | if (nfs4_setup_sequence(server, &lgp->args.seq_args, | 5976 | if (nfs41_setup_sequence(session, &lgp->args.seq_args, |
6341 | &lgp->res.seq_res, task)) | 5977 | &lgp->res.seq_res, task)) |
6342 | return; | 5978 | return; |
6343 | if (pnfs_choose_layoutget_stateid(&lgp->args.stateid, | 5979 | if (pnfs_choose_layoutget_stateid(&lgp->args.stateid, |
6344 | NFS_I(lgp->args.inode)->layout, | 5980 | NFS_I(lgp->args.inode)->layout, |
6345 | lgp->args.ctx->state)) { | 5981 | lgp->args.ctx->state)) { |
6346 | rpc_exit(task, NFS4_OK); | 5982 | rpc_exit(task, NFS4_OK); |
6347 | return; | ||
6348 | } | 5983 | } |
6349 | rpc_call_start(task); | ||
6350 | } | 5984 | } |
6351 | 5985 | ||
6352 | static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | 5986 | static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) |
@@ -6359,7 +5993,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | |||
6359 | 5993 | ||
6360 | dprintk("--> %s\n", __func__); | 5994 | dprintk("--> %s\n", __func__); |
6361 | 5995 | ||
6362 | if (!nfs4_sequence_done(task, &lgp->res.seq_res)) | 5996 | if (!nfs41_sequence_done(task, &lgp->res.seq_res)) |
6363 | goto out; | 5997 | goto out; |
6364 | 5998 | ||
6365 | switch (task->tk_status) { | 5999 | switch (task->tk_status) { |
@@ -6510,10 +6144,10 @@ nfs4_layoutreturn_prepare(struct rpc_task *task, void *calldata) | |||
6510 | struct nfs4_layoutreturn *lrp = calldata; | 6144 | struct nfs4_layoutreturn *lrp = calldata; |
6511 | 6145 | ||
6512 | dprintk("--> %s\n", __func__); | 6146 | dprintk("--> %s\n", __func__); |
6513 | if (nfs41_setup_sequence(lrp->clp->cl_session, &lrp->args.seq_args, | 6147 | nfs41_setup_sequence(lrp->clp->cl_session, |
6514 | &lrp->res.seq_res, task)) | 6148 | &lrp->args.seq_args, |
6515 | return; | 6149 | &lrp->res.seq_res, |
6516 | rpc_call_start(task); | 6150 | task); |
6517 | } | 6151 | } |
6518 | 6152 | ||
6519 | static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | 6153 | static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) |
@@ -6523,7 +6157,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | |||
6523 | 6157 | ||
6524 | dprintk("--> %s\n", __func__); | 6158 | dprintk("--> %s\n", __func__); |
6525 | 6159 | ||
6526 | if (!nfs4_sequence_done(task, &lrp->res.seq_res)) | 6160 | if (!nfs41_sequence_done(task, &lrp->res.seq_res)) |
6527 | return; | 6161 | return; |
6528 | 6162 | ||
6529 | server = NFS_SERVER(lrp->args.inode); | 6163 | server = NFS_SERVER(lrp->args.inode); |
@@ -6672,11 +6306,12 @@ static void nfs4_layoutcommit_prepare(struct rpc_task *task, void *calldata) | |||
6672 | { | 6306 | { |
6673 | struct nfs4_layoutcommit_data *data = calldata; | 6307 | struct nfs4_layoutcommit_data *data = calldata; |
6674 | struct nfs_server *server = NFS_SERVER(data->args.inode); | 6308 | struct nfs_server *server = NFS_SERVER(data->args.inode); |
6309 | struct nfs4_session *session = nfs4_get_session(server); | ||
6675 | 6310 | ||
6676 | if (nfs4_setup_sequence(server, &data->args.seq_args, | 6311 | nfs41_setup_sequence(session, |
6677 | &data->res.seq_res, task)) | 6312 | &data->args.seq_args, |
6678 | return; | 6313 | &data->res.seq_res, |
6679 | rpc_call_start(task); | 6314 | task); |
6680 | } | 6315 | } |
6681 | 6316 | ||
6682 | static void | 6317 | static void |
@@ -6685,7 +6320,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) | |||
6685 | struct nfs4_layoutcommit_data *data = calldata; | 6320 | struct nfs4_layoutcommit_data *data = calldata; |
6686 | struct nfs_server *server = NFS_SERVER(data->args.inode); | 6321 | struct nfs_server *server = NFS_SERVER(data->args.inode); |
6687 | 6322 | ||
6688 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | 6323 | if (!nfs41_sequence_done(task, &data->res.seq_res)) |
6689 | return; | 6324 | return; |
6690 | 6325 | ||
6691 | switch (task->tk_status) { /* Just ignore these failures */ | 6326 | switch (task->tk_status) { /* Just ignore these failures */ |
@@ -6873,7 +6508,9 @@ static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
6873 | 6508 | ||
6874 | dprintk("NFS call test_stateid %p\n", stateid); | 6509 | dprintk("NFS call test_stateid %p\n", stateid); |
6875 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); | 6510 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); |
6876 | status = nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); | 6511 | nfs4_set_sequence_privileged(&args.seq_args); |
6512 | status = nfs4_call_sync_sequence(server->client, server, &msg, | ||
6513 | &args.seq_args, &res.seq_res); | ||
6877 | if (status != NFS_OK) { | 6514 | if (status != NFS_OK) { |
6878 | dprintk("NFS reply test_stateid: failed, %d\n", status); | 6515 | dprintk("NFS reply test_stateid: failed, %d\n", status); |
6879 | return status; | 6516 | return status; |
@@ -6920,8 +6557,9 @@ static int _nfs4_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
6920 | 6557 | ||
6921 | dprintk("NFS call free_stateid %p\n", stateid); | 6558 | dprintk("NFS call free_stateid %p\n", stateid); |
6922 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); | 6559 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); |
6560 | nfs4_set_sequence_privileged(&args.seq_args); | ||
6923 | status = nfs4_call_sync_sequence(server->client, server, &msg, | 6561 | status = nfs4_call_sync_sequence(server->client, server, &msg, |
6924 | &args.seq_args, &res.seq_res, 1); | 6562 | &args.seq_args, &res.seq_res); |
6925 | dprintk("NFS reply free_stateid: %d\n", status); | 6563 | dprintk("NFS reply free_stateid: %d\n", status); |
6926 | return status; | 6564 | return status; |
6927 | } | 6565 | } |
@@ -7041,7 +6679,7 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = { | |||
7041 | #if defined(CONFIG_NFS_V4_1) | 6679 | #if defined(CONFIG_NFS_V4_1) |
7042 | static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { | 6680 | static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { |
7043 | .minor_version = 1, | 6681 | .minor_version = 1, |
7044 | .call_sync = _nfs4_call_sync_session, | 6682 | .call_sync = nfs4_call_sync_sequence, |
7045 | .match_stateid = nfs41_match_stateid, | 6683 | .match_stateid = nfs41_match_stateid, |
7046 | .find_root_sec = nfs41_find_root_sec, | 6684 | .find_root_sec = nfs41_find_root_sec, |
7047 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, | 6685 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, |
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c new file mode 100644 index 00000000000..ebda5f4a031 --- /dev/null +++ b/fs/nfs/nfs4session.c | |||
@@ -0,0 +1,552 @@ | |||
1 | /* | ||
2 | * fs/nfs/nfs4session.c | ||
3 | * | ||
4 | * Copyright (c) 2012 Trond Myklebust <Trond.Myklebust@netapp.com> | ||
5 | * | ||
6 | */ | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/errno.h> | ||
9 | #include <linux/string.h> | ||
10 | #include <linux/printk.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/sunrpc/sched.h> | ||
13 | #include <linux/sunrpc/bc_xprt.h> | ||
14 | #include <linux/nfs.h> | ||
15 | #include <linux/nfs4.h> | ||
16 | #include <linux/nfs_fs.h> | ||
17 | #include <linux/module.h> | ||
18 | |||
19 | #include "nfs4_fs.h" | ||
20 | #include "internal.h" | ||
21 | #include "nfs4session.h" | ||
22 | #include "callback.h" | ||
23 | |||
24 | #define NFSDBG_FACILITY NFSDBG_STATE | ||
25 | |||
26 | /* | ||
27 | * nfs4_shrink_slot_table - free retired slots from the slot table | ||
28 | */ | ||
29 | static void nfs4_shrink_slot_table(struct nfs4_slot_table *tbl, u32 newsize) | ||
30 | { | ||
31 | struct nfs4_slot **p; | ||
32 | if (newsize >= tbl->max_slots) | ||
33 | return; | ||
34 | |||
35 | p = &tbl->slots; | ||
36 | while (newsize--) | ||
37 | p = &(*p)->next; | ||
38 | while (*p) { | ||
39 | struct nfs4_slot *slot = *p; | ||
40 | |||
41 | *p = slot->next; | ||
42 | kfree(slot); | ||
43 | tbl->max_slots--; | ||
44 | } | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | * nfs4_free_slot - free a slot and efficiently update slot table. | ||
49 | * | ||
50 | * freeing a slot is trivially done by clearing its respective bit | ||
51 | * in the bitmap. | ||
52 | * If the freed slotid equals highest_used_slotid we want to update it | ||
53 | * so that the server would be able to size down the slot table if needed, | ||
54 | * otherwise we know that the highest_used_slotid is still in use. | ||
55 | * When updating highest_used_slotid there may be "holes" in the bitmap | ||
56 | * so we need to scan down from highest_used_slotid to 0 looking for the now | ||
57 | * highest slotid in use. | ||
58 | * If none found, highest_used_slotid is set to NFS4_NO_SLOT. | ||
59 | * | ||
60 | * Must be called while holding tbl->slot_tbl_lock | ||
61 | */ | ||
62 | void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot) | ||
63 | { | ||
64 | u32 slotid = slot->slot_nr; | ||
65 | |||
66 | /* clear used bit in bitmap */ | ||
67 | __clear_bit(slotid, tbl->used_slots); | ||
68 | |||
69 | /* update highest_used_slotid when it is freed */ | ||
70 | if (slotid == tbl->highest_used_slotid) { | ||
71 | u32 new_max = find_last_bit(tbl->used_slots, slotid); | ||
72 | if (new_max < slotid) | ||
73 | tbl->highest_used_slotid = new_max; | ||
74 | else { | ||
75 | tbl->highest_used_slotid = NFS4_NO_SLOT; | ||
76 | nfs4_session_drain_complete(tbl->session, tbl); | ||
77 | } | ||
78 | } | ||
79 | dprintk("%s: slotid %u highest_used_slotid %d\n", __func__, | ||
80 | slotid, tbl->highest_used_slotid); | ||
81 | } | ||
82 | |||
83 | static struct nfs4_slot *nfs4_new_slot(struct nfs4_slot_table *tbl, | ||
84 | u32 slotid, u32 seq_init, gfp_t gfp_mask) | ||
85 | { | ||
86 | struct nfs4_slot *slot; | ||
87 | |||
88 | slot = kzalloc(sizeof(*slot), gfp_mask); | ||
89 | if (slot) { | ||
90 | slot->table = tbl; | ||
91 | slot->slot_nr = slotid; | ||
92 | slot->seq_nr = seq_init; | ||
93 | } | ||
94 | return slot; | ||
95 | } | ||
96 | |||
97 | static struct nfs4_slot *nfs4_find_or_create_slot(struct nfs4_slot_table *tbl, | ||
98 | u32 slotid, u32 seq_init, gfp_t gfp_mask) | ||
99 | { | ||
100 | struct nfs4_slot **p, *slot; | ||
101 | |||
102 | p = &tbl->slots; | ||
103 | for (;;) { | ||
104 | if (*p == NULL) { | ||
105 | *p = nfs4_new_slot(tbl, tbl->max_slots, | ||
106 | seq_init, gfp_mask); | ||
107 | if (*p == NULL) | ||
108 | break; | ||
109 | tbl->max_slots++; | ||
110 | } | ||
111 | slot = *p; | ||
112 | if (slot->slot_nr == slotid) | ||
113 | return slot; | ||
114 | p = &slot->next; | ||
115 | } | ||
116 | return ERR_PTR(-ENOMEM); | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * nfs4_alloc_slot - efficiently look for a free slot | ||
121 | * | ||
122 | * nfs4_alloc_slot looks for an unset bit in the used_slots bitmap. | ||
123 | * If found, we mark the slot as used, update the highest_used_slotid, | ||
124 | * and respectively set up the sequence operation args. | ||
125 | * | ||
126 | * Note: must be called with under the slot_tbl_lock. | ||
127 | */ | ||
128 | struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl) | ||
129 | { | ||
130 | struct nfs4_slot *ret = ERR_PTR(-EBUSY); | ||
131 | u32 slotid; | ||
132 | |||
133 | dprintk("--> %s used_slots=%04lx highest_used=%u max_slots=%u\n", | ||
134 | __func__, tbl->used_slots[0], tbl->highest_used_slotid, | ||
135 | tbl->max_slotid + 1); | ||
136 | slotid = find_first_zero_bit(tbl->used_slots, tbl->max_slotid + 1); | ||
137 | if (slotid > tbl->max_slotid) | ||
138 | goto out; | ||
139 | ret = nfs4_find_or_create_slot(tbl, slotid, 1, GFP_NOWAIT); | ||
140 | if (IS_ERR(ret)) | ||
141 | goto out; | ||
142 | __set_bit(slotid, tbl->used_slots); | ||
143 | if (slotid > tbl->highest_used_slotid || | ||
144 | tbl->highest_used_slotid == NFS4_NO_SLOT) | ||
145 | tbl->highest_used_slotid = slotid; | ||
146 | ret->generation = tbl->generation; | ||
147 | |||
148 | out: | ||
149 | dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n", | ||
150 | __func__, tbl->used_slots[0], tbl->highest_used_slotid, | ||
151 | !IS_ERR(ret) ? ret->slot_nr : -1); | ||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | static int nfs4_grow_slot_table(struct nfs4_slot_table *tbl, | ||
156 | u32 max_reqs, u32 ivalue) | ||
157 | { | ||
158 | if (max_reqs <= tbl->max_slots) | ||
159 | return 0; | ||
160 | if (!IS_ERR(nfs4_find_or_create_slot(tbl, max_reqs - 1, ivalue, GFP_NOFS))) | ||
161 | return 0; | ||
162 | return -ENOMEM; | ||
163 | } | ||
164 | |||
165 | static void nfs4_reset_slot_table(struct nfs4_slot_table *tbl, | ||
166 | u32 server_highest_slotid, | ||
167 | u32 ivalue) | ||
168 | { | ||
169 | struct nfs4_slot **p; | ||
170 | |||
171 | nfs4_shrink_slot_table(tbl, server_highest_slotid + 1); | ||
172 | p = &tbl->slots; | ||
173 | while (*p) { | ||
174 | (*p)->seq_nr = ivalue; | ||
175 | (*p)->interrupted = 0; | ||
176 | p = &(*p)->next; | ||
177 | } | ||
178 | tbl->highest_used_slotid = NFS4_NO_SLOT; | ||
179 | tbl->target_highest_slotid = server_highest_slotid; | ||
180 | tbl->server_highest_slotid = server_highest_slotid; | ||
181 | tbl->d_target_highest_slotid = 0; | ||
182 | tbl->d2_target_highest_slotid = 0; | ||
183 | tbl->max_slotid = server_highest_slotid; | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * (re)Initialise a slot table | ||
188 | */ | ||
189 | static int nfs4_realloc_slot_table(struct nfs4_slot_table *tbl, | ||
190 | u32 max_reqs, u32 ivalue) | ||
191 | { | ||
192 | int ret; | ||
193 | |||
194 | dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__, | ||
195 | max_reqs, tbl->max_slots); | ||
196 | |||
197 | if (max_reqs > NFS4_MAX_SLOT_TABLE) | ||
198 | max_reqs = NFS4_MAX_SLOT_TABLE; | ||
199 | |||
200 | ret = nfs4_grow_slot_table(tbl, max_reqs, ivalue); | ||
201 | if (ret) | ||
202 | goto out; | ||
203 | |||
204 | spin_lock(&tbl->slot_tbl_lock); | ||
205 | nfs4_reset_slot_table(tbl, max_reqs - 1, ivalue); | ||
206 | spin_unlock(&tbl->slot_tbl_lock); | ||
207 | |||
208 | dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__, | ||
209 | tbl, tbl->slots, tbl->max_slots); | ||
210 | out: | ||
211 | dprintk("<-- %s: return %d\n", __func__, ret); | ||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | /* Destroy the slot table */ | ||
216 | static void nfs4_destroy_slot_tables(struct nfs4_session *session) | ||
217 | { | ||
218 | nfs4_shrink_slot_table(&session->fc_slot_table, 0); | ||
219 | nfs4_shrink_slot_table(&session->bc_slot_table, 0); | ||
220 | } | ||
221 | |||
222 | static bool nfs41_assign_slot(struct rpc_task *task, void *pslot) | ||
223 | { | ||
224 | struct nfs4_sequence_args *args = task->tk_msg.rpc_argp; | ||
225 | struct nfs4_sequence_res *res = task->tk_msg.rpc_resp; | ||
226 | struct nfs4_slot *slot = pslot; | ||
227 | struct nfs4_slot_table *tbl = slot->table; | ||
228 | |||
229 | if (nfs4_session_draining(tbl->session) && !args->sa_privileged) | ||
230 | return false; | ||
231 | slot->generation = tbl->generation; | ||
232 | args->sa_slot = slot; | ||
233 | res->sr_timestamp = jiffies; | ||
234 | res->sr_slot = slot; | ||
235 | res->sr_status_flags = 0; | ||
236 | res->sr_status = 1; | ||
237 | return true; | ||
238 | } | ||
239 | |||
240 | static bool __nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl, | ||
241 | struct nfs4_slot *slot) | ||
242 | { | ||
243 | if (rpc_wake_up_first(&tbl->slot_tbl_waitq, nfs41_assign_slot, slot)) | ||
244 | return true; | ||
245 | return false; | ||
246 | } | ||
247 | |||
248 | bool nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl, | ||
249 | struct nfs4_slot *slot) | ||
250 | { | ||
251 | if (slot->slot_nr > tbl->max_slotid) | ||
252 | return false; | ||
253 | return __nfs41_wake_and_assign_slot(tbl, slot); | ||
254 | } | ||
255 | |||
256 | static bool nfs41_try_wake_next_slot_table_entry(struct nfs4_slot_table *tbl) | ||
257 | { | ||
258 | struct nfs4_slot *slot = nfs4_alloc_slot(tbl); | ||
259 | if (!IS_ERR(slot)) { | ||
260 | bool ret = __nfs41_wake_and_assign_slot(tbl, slot); | ||
261 | if (ret) | ||
262 | return ret; | ||
263 | nfs4_free_slot(tbl, slot); | ||
264 | } | ||
265 | return false; | ||
266 | } | ||
267 | |||
268 | void nfs41_wake_slot_table(struct nfs4_slot_table *tbl) | ||
269 | { | ||
270 | for (;;) { | ||
271 | if (!nfs41_try_wake_next_slot_table_entry(tbl)) | ||
272 | break; | ||
273 | } | ||
274 | } | ||
275 | |||
276 | static void nfs41_set_max_slotid_locked(struct nfs4_slot_table *tbl, | ||
277 | u32 target_highest_slotid) | ||
278 | { | ||
279 | u32 max_slotid; | ||
280 | |||
281 | max_slotid = min(NFS4_MAX_SLOT_TABLE - 1, target_highest_slotid); | ||
282 | if (max_slotid > tbl->server_highest_slotid) | ||
283 | max_slotid = tbl->server_highest_slotid; | ||
284 | if (max_slotid > tbl->target_highest_slotid) | ||
285 | max_slotid = tbl->target_highest_slotid; | ||
286 | tbl->max_slotid = max_slotid; | ||
287 | nfs41_wake_slot_table(tbl); | ||
288 | } | ||
289 | |||
290 | /* Update the client's idea of target_highest_slotid */ | ||
291 | static void nfs41_set_target_slotid_locked(struct nfs4_slot_table *tbl, | ||
292 | u32 target_highest_slotid) | ||
293 | { | ||
294 | if (tbl->target_highest_slotid == target_highest_slotid) | ||
295 | return; | ||
296 | tbl->target_highest_slotid = target_highest_slotid; | ||
297 | tbl->generation++; | ||
298 | } | ||
299 | |||
300 | void nfs41_set_target_slotid(struct nfs4_slot_table *tbl, | ||
301 | u32 target_highest_slotid) | ||
302 | { | ||
303 | spin_lock(&tbl->slot_tbl_lock); | ||
304 | nfs41_set_target_slotid_locked(tbl, target_highest_slotid); | ||
305 | tbl->d_target_highest_slotid = 0; | ||
306 | tbl->d2_target_highest_slotid = 0; | ||
307 | nfs41_set_max_slotid_locked(tbl, target_highest_slotid); | ||
308 | spin_unlock(&tbl->slot_tbl_lock); | ||
309 | } | ||
310 | |||
311 | static void nfs41_set_server_slotid_locked(struct nfs4_slot_table *tbl, | ||
312 | u32 highest_slotid) | ||
313 | { | ||
314 | if (tbl->server_highest_slotid == highest_slotid) | ||
315 | return; | ||
316 | if (tbl->highest_used_slotid > highest_slotid) | ||
317 | return; | ||
318 | /* Deallocate slots */ | ||
319 | nfs4_shrink_slot_table(tbl, highest_slotid + 1); | ||
320 | tbl->server_highest_slotid = highest_slotid; | ||
321 | } | ||
322 | |||
323 | static s32 nfs41_derivative_target_slotid(s32 s1, s32 s2) | ||
324 | { | ||
325 | s1 -= s2; | ||
326 | if (s1 == 0) | ||
327 | return 0; | ||
328 | if (s1 < 0) | ||
329 | return (s1 - 1) >> 1; | ||
330 | return (s1 + 1) >> 1; | ||
331 | } | ||
332 | |||
333 | static int nfs41_sign_s32(s32 s1) | ||
334 | { | ||
335 | if (s1 > 0) | ||
336 | return 1; | ||
337 | if (s1 < 0) | ||
338 | return -1; | ||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static bool nfs41_same_sign_or_zero_s32(s32 s1, s32 s2) | ||
343 | { | ||
344 | if (!s1 || !s2) | ||
345 | return true; | ||
346 | return nfs41_sign_s32(s1) == nfs41_sign_s32(s2); | ||
347 | } | ||
348 | |||
349 | /* Try to eliminate outliers by checking for sharp changes in the | ||
350 | * derivatives and second derivatives | ||
351 | */ | ||
352 | static bool nfs41_is_outlier_target_slotid(struct nfs4_slot_table *tbl, | ||
353 | u32 new_target) | ||
354 | { | ||
355 | s32 d_target, d2_target; | ||
356 | bool ret = true; | ||
357 | |||
358 | d_target = nfs41_derivative_target_slotid(new_target, | ||
359 | tbl->target_highest_slotid); | ||
360 | d2_target = nfs41_derivative_target_slotid(d_target, | ||
361 | tbl->d_target_highest_slotid); | ||
362 | /* Is first derivative same sign? */ | ||
363 | if (nfs41_same_sign_or_zero_s32(d_target, tbl->d_target_highest_slotid)) | ||
364 | ret = false; | ||
365 | /* Is second derivative same sign? */ | ||
366 | if (nfs41_same_sign_or_zero_s32(d2_target, tbl->d2_target_highest_slotid)) | ||
367 | ret = false; | ||
368 | tbl->d_target_highest_slotid = d_target; | ||
369 | tbl->d2_target_highest_slotid = d2_target; | ||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | void nfs41_update_target_slotid(struct nfs4_slot_table *tbl, | ||
374 | struct nfs4_slot *slot, | ||
375 | struct nfs4_sequence_res *res) | ||
376 | { | ||
377 | spin_lock(&tbl->slot_tbl_lock); | ||
378 | if (!nfs41_is_outlier_target_slotid(tbl, res->sr_target_highest_slotid)) | ||
379 | nfs41_set_target_slotid_locked(tbl, res->sr_target_highest_slotid); | ||
380 | if (tbl->generation == slot->generation) | ||
381 | nfs41_set_server_slotid_locked(tbl, res->sr_highest_slotid); | ||
382 | nfs41_set_max_slotid_locked(tbl, res->sr_target_highest_slotid); | ||
383 | spin_unlock(&tbl->slot_tbl_lock); | ||
384 | } | ||
385 | |||
386 | /* | ||
387 | * Initialize or reset the forechannel and backchannel tables | ||
388 | */ | ||
389 | int nfs4_setup_session_slot_tables(struct nfs4_session *ses) | ||
390 | { | ||
391 | struct nfs4_slot_table *tbl; | ||
392 | int status; | ||
393 | |||
394 | dprintk("--> %s\n", __func__); | ||
395 | /* Fore channel */ | ||
396 | tbl = &ses->fc_slot_table; | ||
397 | tbl->session = ses; | ||
398 | status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1); | ||
399 | if (status) /* -ENOMEM */ | ||
400 | return status; | ||
401 | /* Back channel */ | ||
402 | tbl = &ses->bc_slot_table; | ||
403 | tbl->session = ses; | ||
404 | status = nfs4_realloc_slot_table(tbl, ses->bc_attrs.max_reqs, 0); | ||
405 | if (status && tbl->slots == NULL) | ||
406 | /* Fore and back channel share a connection so get | ||
407 | * both slot tables or neither */ | ||
408 | nfs4_destroy_slot_tables(ses); | ||
409 | return status; | ||
410 | } | ||
411 | |||
412 | struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | ||
413 | { | ||
414 | struct nfs4_session *session; | ||
415 | struct nfs4_slot_table *tbl; | ||
416 | |||
417 | session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); | ||
418 | if (!session) | ||
419 | return NULL; | ||
420 | |||
421 | tbl = &session->fc_slot_table; | ||
422 | tbl->highest_used_slotid = NFS4_NO_SLOT; | ||
423 | spin_lock_init(&tbl->slot_tbl_lock); | ||
424 | rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table"); | ||
425 | init_completion(&tbl->complete); | ||
426 | |||
427 | tbl = &session->bc_slot_table; | ||
428 | tbl->highest_used_slotid = NFS4_NO_SLOT; | ||
429 | spin_lock_init(&tbl->slot_tbl_lock); | ||
430 | rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table"); | ||
431 | init_completion(&tbl->complete); | ||
432 | |||
433 | session->session_state = 1<<NFS4_SESSION_INITING; | ||
434 | |||
435 | session->clp = clp; | ||
436 | return session; | ||
437 | } | ||
438 | |||
439 | void nfs4_destroy_session(struct nfs4_session *session) | ||
440 | { | ||
441 | struct rpc_xprt *xprt; | ||
442 | struct rpc_cred *cred; | ||
443 | |||
444 | cred = nfs4_get_exchange_id_cred(session->clp); | ||
445 | nfs4_proc_destroy_session(session, cred); | ||
446 | if (cred) | ||
447 | put_rpccred(cred); | ||
448 | |||
449 | rcu_read_lock(); | ||
450 | xprt = rcu_dereference(session->clp->cl_rpcclient->cl_xprt); | ||
451 | rcu_read_unlock(); | ||
452 | dprintk("%s Destroy backchannel for xprt %p\n", | ||
453 | __func__, xprt); | ||
454 | xprt_destroy_backchannel(xprt, NFS41_BC_MIN_CALLBACKS); | ||
455 | nfs4_destroy_slot_tables(session); | ||
456 | kfree(session); | ||
457 | } | ||
458 | |||
459 | /* | ||
460 | * With sessions, the client is not marked ready until after a | ||
461 | * successful EXCHANGE_ID and CREATE_SESSION. | ||
462 | * | ||
463 | * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate | ||
464 | * other versions of NFS can be tried. | ||
465 | */ | ||
466 | static int nfs41_check_session_ready(struct nfs_client *clp) | ||
467 | { | ||
468 | int ret; | ||
469 | |||
470 | if (clp->cl_cons_state == NFS_CS_SESSION_INITING) { | ||
471 | ret = nfs4_client_recover_expired_lease(clp); | ||
472 | if (ret) | ||
473 | return ret; | ||
474 | } | ||
475 | if (clp->cl_cons_state < NFS_CS_READY) | ||
476 | return -EPROTONOSUPPORT; | ||
477 | smp_rmb(); | ||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | int nfs4_init_session(struct nfs_server *server) | ||
482 | { | ||
483 | struct nfs_client *clp = server->nfs_client; | ||
484 | struct nfs4_session *session; | ||
485 | unsigned int target_max_rqst_sz = NFS_MAX_FILE_IO_SIZE; | ||
486 | unsigned int target_max_resp_sz = NFS_MAX_FILE_IO_SIZE; | ||
487 | |||
488 | if (!nfs4_has_session(clp)) | ||
489 | return 0; | ||
490 | |||
491 | if (server->rsize != 0) | ||
492 | target_max_resp_sz = server->rsize; | ||
493 | target_max_resp_sz += nfs41_maxread_overhead; | ||
494 | |||
495 | if (server->wsize != 0) | ||
496 | target_max_rqst_sz = server->wsize; | ||
497 | target_max_rqst_sz += nfs41_maxwrite_overhead; | ||
498 | |||
499 | session = clp->cl_session; | ||
500 | spin_lock(&clp->cl_lock); | ||
501 | if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) { | ||
502 | /* Initialise targets and channel attributes */ | ||
503 | session->fc_target_max_rqst_sz = target_max_rqst_sz; | ||
504 | session->fc_attrs.max_rqst_sz = target_max_rqst_sz; | ||
505 | session->fc_target_max_resp_sz = target_max_resp_sz; | ||
506 | session->fc_attrs.max_resp_sz = target_max_resp_sz; | ||
507 | } else { | ||
508 | /* Just adjust the targets */ | ||
509 | if (target_max_rqst_sz > session->fc_target_max_rqst_sz) { | ||
510 | session->fc_target_max_rqst_sz = target_max_rqst_sz; | ||
511 | set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); | ||
512 | } | ||
513 | if (target_max_resp_sz > session->fc_target_max_resp_sz) { | ||
514 | session->fc_target_max_resp_sz = target_max_resp_sz; | ||
515 | set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); | ||
516 | } | ||
517 | } | ||
518 | spin_unlock(&clp->cl_lock); | ||
519 | |||
520 | if (test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) | ||
521 | nfs4_schedule_lease_recovery(clp); | ||
522 | |||
523 | return nfs41_check_session_ready(clp); | ||
524 | } | ||
525 | |||
526 | int nfs4_init_ds_session(struct nfs_client *clp, unsigned long lease_time) | ||
527 | { | ||
528 | struct nfs4_session *session = clp->cl_session; | ||
529 | int ret; | ||
530 | |||
531 | spin_lock(&clp->cl_lock); | ||
532 | if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) { | ||
533 | /* | ||
534 | * Do not set NFS_CS_CHECK_LEASE_TIME instead set the | ||
535 | * DS lease to be equal to the MDS lease. | ||
536 | */ | ||
537 | clp->cl_lease_time = lease_time; | ||
538 | clp->cl_last_renewal = jiffies; | ||
539 | } | ||
540 | spin_unlock(&clp->cl_lock); | ||
541 | |||
542 | ret = nfs41_check_session_ready(clp); | ||
543 | if (ret) | ||
544 | return ret; | ||
545 | /* Test for the DS role */ | ||
546 | if (!is_ds_client(clp)) | ||
547 | return -ENODEV; | ||
548 | return 0; | ||
549 | } | ||
550 | EXPORT_SYMBOL_GPL(nfs4_init_ds_session); | ||
551 | |||
552 | |||
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h new file mode 100644 index 00000000000..6f3cb39386d --- /dev/null +++ b/fs/nfs/nfs4session.h | |||
@@ -0,0 +1,142 @@ | |||
1 | /* | ||
2 | * fs/nfs/nfs4session.h | ||
3 | * | ||
4 | * Copyright (c) 2012 Trond Myklebust <Trond.Myklebust@netapp.com> | ||
5 | * | ||
6 | */ | ||
7 | #ifndef __LINUX_FS_NFS_NFS4SESSION_H | ||
8 | #define __LINUX_FS_NFS_NFS4SESSION_H | ||
9 | |||
10 | /* maximum number of slots to use */ | ||
11 | #define NFS4_DEF_SLOT_TABLE_SIZE (16U) | ||
12 | #define NFS4_MAX_SLOT_TABLE (1024U) | ||
13 | #define NFS4_NO_SLOT ((u32)-1) | ||
14 | |||
15 | #if IS_ENABLED(CONFIG_NFS_V4) | ||
16 | |||
17 | /* Sessions slot seqid */ | ||
18 | struct nfs4_slot { | ||
19 | struct nfs4_slot_table *table; | ||
20 | struct nfs4_slot *next; | ||
21 | unsigned long generation; | ||
22 | u32 slot_nr; | ||
23 | u32 seq_nr; | ||
24 | unsigned int interrupted : 1; | ||
25 | }; | ||
26 | |||
27 | /* Sessions */ | ||
28 | #define SLOT_TABLE_SZ DIV_ROUND_UP(NFS4_MAX_SLOT_TABLE, 8*sizeof(long)) | ||
29 | struct nfs4_slot_table { | ||
30 | struct nfs4_session *session; /* Parent session */ | ||
31 | struct nfs4_slot *slots; /* seqid per slot */ | ||
32 | unsigned long used_slots[SLOT_TABLE_SZ]; /* used/unused bitmap */ | ||
33 | spinlock_t slot_tbl_lock; | ||
34 | struct rpc_wait_queue slot_tbl_waitq; /* allocators may wait here */ | ||
35 | u32 max_slots; /* # slots in table */ | ||
36 | u32 max_slotid; /* Max allowed slotid value */ | ||
37 | u32 highest_used_slotid; /* sent to server on each SEQ. | ||
38 | * op for dynamic resizing */ | ||
39 | u32 target_highest_slotid; /* Server max_slot target */ | ||
40 | u32 server_highest_slotid; /* Server highest slotid */ | ||
41 | s32 d_target_highest_slotid; /* Derivative */ | ||
42 | s32 d2_target_highest_slotid; /* 2nd derivative */ | ||
43 | unsigned long generation; /* Generation counter for | ||
44 | target_highest_slotid */ | ||
45 | struct completion complete; | ||
46 | }; | ||
47 | |||
48 | /* | ||
49 | * Session related parameters | ||
50 | */ | ||
51 | struct nfs4_session { | ||
52 | struct nfs4_sessionid sess_id; | ||
53 | u32 flags; | ||
54 | unsigned long session_state; | ||
55 | u32 hash_alg; | ||
56 | u32 ssv_len; | ||
57 | |||
58 | /* The fore and back channel */ | ||
59 | struct nfs4_channel_attrs fc_attrs; | ||
60 | struct nfs4_slot_table fc_slot_table; | ||
61 | struct nfs4_channel_attrs bc_attrs; | ||
62 | struct nfs4_slot_table bc_slot_table; | ||
63 | struct nfs_client *clp; | ||
64 | /* Create session arguments */ | ||
65 | unsigned int fc_target_max_rqst_sz; | ||
66 | unsigned int fc_target_max_resp_sz; | ||
67 | }; | ||
68 | |||
69 | enum nfs4_session_state { | ||
70 | NFS4_SESSION_INITING, | ||
71 | NFS4_SESSION_DRAINING, | ||
72 | }; | ||
73 | |||
74 | #if defined(CONFIG_NFS_V4_1) | ||
75 | extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl); | ||
76 | extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot); | ||
77 | |||
78 | extern void nfs41_set_target_slotid(struct nfs4_slot_table *tbl, | ||
79 | u32 target_highest_slotid); | ||
80 | extern void nfs41_update_target_slotid(struct nfs4_slot_table *tbl, | ||
81 | struct nfs4_slot *slot, | ||
82 | struct nfs4_sequence_res *res); | ||
83 | |||
84 | extern int nfs4_setup_session_slot_tables(struct nfs4_session *ses); | ||
85 | |||
86 | extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); | ||
87 | extern void nfs4_destroy_session(struct nfs4_session *session); | ||
88 | extern int nfs4_init_session(struct nfs_server *server); | ||
89 | extern int nfs4_init_ds_session(struct nfs_client *, unsigned long); | ||
90 | |||
91 | extern void nfs4_session_drain_complete(struct nfs4_session *session, | ||
92 | struct nfs4_slot_table *tbl); | ||
93 | |||
94 | static inline bool nfs4_session_draining(struct nfs4_session *session) | ||
95 | { | ||
96 | return !!test_bit(NFS4_SESSION_DRAINING, &session->session_state); | ||
97 | } | ||
98 | |||
99 | bool nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl, | ||
100 | struct nfs4_slot *slot); | ||
101 | void nfs41_wake_slot_table(struct nfs4_slot_table *tbl); | ||
102 | |||
103 | /* | ||
104 | * Determine if sessions are in use. | ||
105 | */ | ||
106 | static inline int nfs4_has_session(const struct nfs_client *clp) | ||
107 | { | ||
108 | if (clp->cl_session) | ||
109 | return 1; | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static inline int nfs4_has_persistent_session(const struct nfs_client *clp) | ||
114 | { | ||
115 | if (nfs4_has_session(clp)) | ||
116 | return (clp->cl_session->flags & SESSION4_PERSIST); | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | #else /* defined(CONFIG_NFS_V4_1) */ | ||
121 | |||
122 | static inline int nfs4_init_session(struct nfs_server *server) | ||
123 | { | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * Determine if sessions are in use. | ||
129 | */ | ||
130 | static inline int nfs4_has_session(const struct nfs_client *clp) | ||
131 | { | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static inline int nfs4_has_persistent_session(const struct nfs_client *clp) | ||
136 | { | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | #endif /* defined(CONFIG_NFS_V4_1) */ | ||
141 | #endif /* IS_ENABLED(CONFIG_NFS_V4) */ | ||
142 | #endif /* __LINUX_FS_NFS_NFS4SESSION_H */ | ||
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index c351e6b3983..9448c579d41 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include "callback.h" | 57 | #include "callback.h" |
58 | #include "delegation.h" | 58 | #include "delegation.h" |
59 | #include "internal.h" | 59 | #include "internal.h" |
60 | #include "nfs4session.h" | ||
60 | #include "pnfs.h" | 61 | #include "pnfs.h" |
61 | #include "netns.h" | 62 | #include "netns.h" |
62 | 63 | ||
@@ -66,7 +67,6 @@ | |||
66 | 67 | ||
67 | const nfs4_stateid zero_stateid; | 68 | const nfs4_stateid zero_stateid; |
68 | static DEFINE_MUTEX(nfs_clid_init_mutex); | 69 | static DEFINE_MUTEX(nfs_clid_init_mutex); |
69 | static LIST_HEAD(nfs4_clientid_list); | ||
70 | 70 | ||
71 | int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) | 71 | int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) |
72 | { | 72 | { |
@@ -254,24 +254,27 @@ static void nfs4_end_drain_session(struct nfs_client *clp) | |||
254 | { | 254 | { |
255 | struct nfs4_session *ses = clp->cl_session; | 255 | struct nfs4_session *ses = clp->cl_session; |
256 | struct nfs4_slot_table *tbl; | 256 | struct nfs4_slot_table *tbl; |
257 | int max_slots; | ||
258 | 257 | ||
259 | if (ses == NULL) | 258 | if (ses == NULL) |
260 | return; | 259 | return; |
261 | tbl = &ses->fc_slot_table; | 260 | tbl = &ses->fc_slot_table; |
262 | if (test_and_clear_bit(NFS4_SESSION_DRAINING, &ses->session_state)) { | 261 | if (test_and_clear_bit(NFS4_SESSION_DRAINING, &ses->session_state)) { |
263 | spin_lock(&tbl->slot_tbl_lock); | 262 | spin_lock(&tbl->slot_tbl_lock); |
264 | max_slots = tbl->max_slots; | 263 | nfs41_wake_slot_table(tbl); |
265 | while (max_slots--) { | ||
266 | if (rpc_wake_up_first(&tbl->slot_tbl_waitq, | ||
267 | nfs4_set_task_privileged, | ||
268 | NULL) == NULL) | ||
269 | break; | ||
270 | } | ||
271 | spin_unlock(&tbl->slot_tbl_lock); | 264 | spin_unlock(&tbl->slot_tbl_lock); |
272 | } | 265 | } |
273 | } | 266 | } |
274 | 267 | ||
268 | /* | ||
269 | * Signal state manager thread if session fore channel is drained | ||
270 | */ | ||
271 | void nfs4_session_drain_complete(struct nfs4_session *session, | ||
272 | struct nfs4_slot_table *tbl) | ||
273 | { | ||
274 | if (nfs4_session_draining(session)) | ||
275 | complete(&tbl->complete); | ||
276 | } | ||
277 | |||
275 | static int nfs4_wait_on_slot_tbl(struct nfs4_slot_table *tbl) | 278 | static int nfs4_wait_on_slot_tbl(struct nfs4_slot_table *tbl) |
276 | { | 279 | { |
277 | spin_lock(&tbl->slot_tbl_lock); | 280 | spin_lock(&tbl->slot_tbl_lock); |
@@ -303,7 +306,6 @@ static void nfs41_finish_session_reset(struct nfs_client *clp) | |||
303 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | 306 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
304 | clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); | 307 | clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); |
305 | /* create_session negotiated new slot table */ | 308 | /* create_session negotiated new slot table */ |
306 | clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); | ||
307 | clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); | 309 | clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); |
308 | nfs41_setup_state_renewal(clp); | 310 | nfs41_setup_state_renewal(clp); |
309 | } | 311 | } |
@@ -1086,7 +1088,6 @@ void nfs_free_seqid(struct nfs_seqid *seqid) | |||
1086 | */ | 1088 | */ |
1087 | static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) | 1089 | static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) |
1088 | { | 1090 | { |
1089 | BUG_ON(list_first_entry(&seqid->sequence->list, struct nfs_seqid, list) != seqid); | ||
1090 | switch (status) { | 1091 | switch (status) { |
1091 | case 0: | 1092 | case 0: |
1092 | break; | 1093 | break; |
@@ -1209,6 +1210,40 @@ void nfs4_schedule_lease_recovery(struct nfs_client *clp) | |||
1209 | } | 1210 | } |
1210 | EXPORT_SYMBOL_GPL(nfs4_schedule_lease_recovery); | 1211 | EXPORT_SYMBOL_GPL(nfs4_schedule_lease_recovery); |
1211 | 1212 | ||
1213 | int nfs4_wait_clnt_recover(struct nfs_client *clp) | ||
1214 | { | ||
1215 | int res; | ||
1216 | |||
1217 | might_sleep(); | ||
1218 | |||
1219 | res = wait_on_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING, | ||
1220 | nfs_wait_bit_killable, TASK_KILLABLE); | ||
1221 | if (res) | ||
1222 | return res; | ||
1223 | |||
1224 | if (clp->cl_cons_state < 0) | ||
1225 | return clp->cl_cons_state; | ||
1226 | return 0; | ||
1227 | } | ||
1228 | |||
1229 | int nfs4_client_recover_expired_lease(struct nfs_client *clp) | ||
1230 | { | ||
1231 | unsigned int loop; | ||
1232 | int ret; | ||
1233 | |||
1234 | for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) { | ||
1235 | ret = nfs4_wait_clnt_recover(clp); | ||
1236 | if (ret != 0) | ||
1237 | break; | ||
1238 | if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) && | ||
1239 | !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state)) | ||
1240 | break; | ||
1241 | nfs4_schedule_state_manager(clp); | ||
1242 | ret = -EIO; | ||
1243 | } | ||
1244 | return ret; | ||
1245 | } | ||
1246 | |||
1212 | /* | 1247 | /* |
1213 | * nfs40_handle_cb_pathdown - return all delegations after NFS4ERR_CB_PATH_DOWN | 1248 | * nfs40_handle_cb_pathdown - return all delegations after NFS4ERR_CB_PATH_DOWN |
1214 | * @clp: client to process | 1249 | * @clp: client to process |
@@ -1401,14 +1436,6 @@ restart: | |||
1401 | /* Mark the file as being 'closed' */ | 1436 | /* Mark the file as being 'closed' */ |
1402 | state->state = 0; | 1437 | state->state = 0; |
1403 | break; | 1438 | break; |
1404 | case -EKEYEXPIRED: | ||
1405 | /* | ||
1406 | * User RPCSEC_GSS context has expired. | ||
1407 | * We cannot recover this stateid now, so | ||
1408 | * skip it and allow recovery thread to | ||
1409 | * proceed. | ||
1410 | */ | ||
1411 | break; | ||
1412 | case -NFS4ERR_ADMIN_REVOKED: | 1439 | case -NFS4ERR_ADMIN_REVOKED: |
1413 | case -NFS4ERR_STALE_STATEID: | 1440 | case -NFS4ERR_STALE_STATEID: |
1414 | case -NFS4ERR_BAD_STATEID: | 1441 | case -NFS4ERR_BAD_STATEID: |
@@ -1561,14 +1588,6 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp) | |||
1561 | nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); | 1588 | nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); |
1562 | } | 1589 | } |
1563 | 1590 | ||
1564 | static void nfs4_warn_keyexpired(const char *s) | ||
1565 | { | ||
1566 | printk_ratelimited(KERN_WARNING "Error: state manager" | ||
1567 | " encountered RPCSEC_GSS session" | ||
1568 | " expired against NFSv4 server %s.\n", | ||
1569 | s); | ||
1570 | } | ||
1571 | |||
1572 | static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) | 1591 | static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) |
1573 | { | 1592 | { |
1574 | switch (error) { | 1593 | switch (error) { |
@@ -1602,10 +1621,6 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) | |||
1602 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | 1621 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: |
1603 | set_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); | 1622 | set_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); |
1604 | break; | 1623 | break; |
1605 | case -EKEYEXPIRED: | ||
1606 | /* Nothing we can do */ | ||
1607 | nfs4_warn_keyexpired(clp->cl_hostname); | ||
1608 | break; | ||
1609 | default: | 1624 | default: |
1610 | dprintk("%s: failed to handle error %d for server %s\n", | 1625 | dprintk("%s: failed to handle error %d for server %s\n", |
1611 | __func__, error, clp->cl_hostname); | 1626 | __func__, error, clp->cl_hostname); |
@@ -1722,8 +1737,6 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status) | |||
1722 | dprintk("%s: exit with error %d for server %s\n", | 1737 | dprintk("%s: exit with error %d for server %s\n", |
1723 | __func__, -EPROTONOSUPPORT, clp->cl_hostname); | 1738 | __func__, -EPROTONOSUPPORT, clp->cl_hostname); |
1724 | return -EPROTONOSUPPORT; | 1739 | return -EPROTONOSUPPORT; |
1725 | case -EKEYEXPIRED: | ||
1726 | nfs4_warn_keyexpired(clp->cl_hostname); | ||
1727 | case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery | 1740 | case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery |
1728 | * in nfs4_exchange_id */ | 1741 | * in nfs4_exchange_id */ |
1729 | default: | 1742 | default: |
@@ -1876,7 +1889,6 @@ again: | |||
1876 | break; | 1889 | break; |
1877 | 1890 | ||
1878 | case -EKEYEXPIRED: | 1891 | case -EKEYEXPIRED: |
1879 | nfs4_warn_keyexpired(clp->cl_hostname); | ||
1880 | case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery | 1892 | case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery |
1881 | * in nfs4_exchange_id */ | 1893 | * in nfs4_exchange_id */ |
1882 | status = -EKEYEXPIRED; | 1894 | status = -EKEYEXPIRED; |
@@ -1907,14 +1919,23 @@ void nfs4_schedule_session_recovery(struct nfs4_session *session, int err) | |||
1907 | } | 1919 | } |
1908 | EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery); | 1920 | EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery); |
1909 | 1921 | ||
1910 | void nfs41_handle_recall_slot(struct nfs_client *clp) | 1922 | static void nfs41_ping_server(struct nfs_client *clp) |
1911 | { | 1923 | { |
1912 | set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); | 1924 | /* Use CHECK_LEASE to ping the server with a SEQUENCE */ |
1913 | dprintk("%s: scheduling slot recall for server %s\n", __func__, | 1925 | set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); |
1914 | clp->cl_hostname); | ||
1915 | nfs4_schedule_state_manager(clp); | 1926 | nfs4_schedule_state_manager(clp); |
1916 | } | 1927 | } |
1917 | 1928 | ||
1929 | void nfs41_server_notify_target_slotid_update(struct nfs_client *clp) | ||
1930 | { | ||
1931 | nfs41_ping_server(clp); | ||
1932 | } | ||
1933 | |||
1934 | void nfs41_server_notify_highest_slotid_update(struct nfs_client *clp) | ||
1935 | { | ||
1936 | nfs41_ping_server(clp); | ||
1937 | } | ||
1938 | |||
1918 | static void nfs4_reset_all_state(struct nfs_client *clp) | 1939 | static void nfs4_reset_all_state(struct nfs_client *clp) |
1919 | { | 1940 | { |
1920 | if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { | 1941 | if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { |
@@ -2024,35 +2045,6 @@ out: | |||
2024 | return status; | 2045 | return status; |
2025 | } | 2046 | } |
2026 | 2047 | ||
2027 | static int nfs4_recall_slot(struct nfs_client *clp) | ||
2028 | { | ||
2029 | struct nfs4_slot_table *fc_tbl; | ||
2030 | struct nfs4_slot *new, *old; | ||
2031 | int i; | ||
2032 | |||
2033 | if (!nfs4_has_session(clp)) | ||
2034 | return 0; | ||
2035 | nfs4_begin_drain_session(clp); | ||
2036 | fc_tbl = &clp->cl_session->fc_slot_table; | ||
2037 | new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot), | ||
2038 | GFP_NOFS); | ||
2039 | if (!new) | ||
2040 | return -ENOMEM; | ||
2041 | |||
2042 | spin_lock(&fc_tbl->slot_tbl_lock); | ||
2043 | for (i = 0; i < fc_tbl->target_max_slots; i++) | ||
2044 | new[i].seq_nr = fc_tbl->slots[i].seq_nr; | ||
2045 | old = fc_tbl->slots; | ||
2046 | fc_tbl->slots = new; | ||
2047 | fc_tbl->max_slots = fc_tbl->target_max_slots; | ||
2048 | fc_tbl->target_max_slots = 0; | ||
2049 | clp->cl_session->fc_attrs.max_reqs = fc_tbl->max_slots; | ||
2050 | spin_unlock(&fc_tbl->slot_tbl_lock); | ||
2051 | |||
2052 | kfree(old); | ||
2053 | return 0; | ||
2054 | } | ||
2055 | |||
2056 | static int nfs4_bind_conn_to_session(struct nfs_client *clp) | 2048 | static int nfs4_bind_conn_to_session(struct nfs_client *clp) |
2057 | { | 2049 | { |
2058 | struct rpc_cred *cred; | 2050 | struct rpc_cred *cred; |
@@ -2083,7 +2075,6 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp) | |||
2083 | #else /* CONFIG_NFS_V4_1 */ | 2075 | #else /* CONFIG_NFS_V4_1 */ |
2084 | static int nfs4_reset_session(struct nfs_client *clp) { return 0; } | 2076 | static int nfs4_reset_session(struct nfs_client *clp) { return 0; } |
2085 | static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } | 2077 | static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } |
2086 | static int nfs4_recall_slot(struct nfs_client *clp) { return 0; } | ||
2087 | 2078 | ||
2088 | static int nfs4_bind_conn_to_session(struct nfs_client *clp) | 2079 | static int nfs4_bind_conn_to_session(struct nfs_client *clp) |
2089 | { | 2080 | { |
@@ -2115,15 +2106,6 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
2115 | continue; | 2106 | continue; |
2116 | } | 2107 | } |
2117 | 2108 | ||
2118 | if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { | ||
2119 | section = "check lease"; | ||
2120 | status = nfs4_check_lease(clp); | ||
2121 | if (status < 0) | ||
2122 | goto out_error; | ||
2123 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) | ||
2124 | continue; | ||
2125 | } | ||
2126 | |||
2127 | /* Initialize or reset the session */ | 2109 | /* Initialize or reset the session */ |
2128 | if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) { | 2110 | if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) { |
2129 | section = "reset session"; | 2111 | section = "reset session"; |
@@ -2144,10 +2126,9 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
2144 | continue; | 2126 | continue; |
2145 | } | 2127 | } |
2146 | 2128 | ||
2147 | /* Recall session slots */ | 2129 | if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { |
2148 | if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state)) { | 2130 | section = "check lease"; |
2149 | section = "recall slot"; | 2131 | status = nfs4_check_lease(clp); |
2150 | status = nfs4_recall_slot(clp); | ||
2151 | if (status < 0) | 2132 | if (status < 0) |
2152 | goto out_error; | 2133 | goto out_error; |
2153 | continue; | 2134 | continue; |
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index bd61221ad2c..84d2e9e2f31 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c | |||
@@ -51,6 +51,7 @@ static const struct super_operations nfs4_sops = { | |||
51 | .alloc_inode = nfs_alloc_inode, | 51 | .alloc_inode = nfs_alloc_inode, |
52 | .destroy_inode = nfs_destroy_inode, | 52 | .destroy_inode = nfs_destroy_inode, |
53 | .write_inode = nfs4_write_inode, | 53 | .write_inode = nfs4_write_inode, |
54 | .drop_inode = nfs_drop_inode, | ||
54 | .put_super = nfs_put_super, | 55 | .put_super = nfs_put_super, |
55 | .statfs = nfs_statfs, | 56 | .statfs = nfs_statfs, |
56 | .evict_inode = nfs4_evict_inode, | 57 | .evict_inode = nfs4_evict_inode, |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 40836ee5dc3..26b14392043 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -56,6 +56,7 @@ | |||
56 | 56 | ||
57 | #include "nfs4_fs.h" | 57 | #include "nfs4_fs.h" |
58 | #include "internal.h" | 58 | #include "internal.h" |
59 | #include "nfs4session.h" | ||
59 | #include "pnfs.h" | 60 | #include "pnfs.h" |
60 | #include "netns.h" | 61 | #include "netns.h" |
61 | 62 | ||
@@ -270,6 +271,8 @@ static int nfs4_stat_to_errno(int); | |||
270 | 271 | ||
271 | #if defined(CONFIG_NFS_V4_1) | 272 | #if defined(CONFIG_NFS_V4_1) |
272 | #define NFS4_MAX_MACHINE_NAME_LEN (64) | 273 | #define NFS4_MAX_MACHINE_NAME_LEN (64) |
274 | #define IMPL_NAME_LIMIT (sizeof(utsname()->sysname) + sizeof(utsname()->release) + \ | ||
275 | sizeof(utsname()->version) + sizeof(utsname()->machine) + 8) | ||
273 | 276 | ||
274 | #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \ | 277 | #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \ |
275 | encode_verifier_maxsz + \ | 278 | encode_verifier_maxsz + \ |
@@ -282,7 +285,7 @@ static int nfs4_stat_to_errno(int); | |||
282 | 1 /* nii_domain */ + \ | 285 | 1 /* nii_domain */ + \ |
283 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ | 286 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ |
284 | 1 /* nii_name */ + \ | 287 | 1 /* nii_name */ + \ |
285 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ | 288 | XDR_QUADLEN(IMPL_NAME_LIMIT) + \ |
286 | 3 /* nii_date */) | 289 | 3 /* nii_date */) |
287 | #define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \ | 290 | #define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \ |
288 | 2 /* eir_clientid */ + \ | 291 | 2 /* eir_clientid */ + \ |
@@ -936,7 +939,7 @@ static void encode_compound_hdr(struct xdr_stream *xdr, | |||
936 | * but this is not required as a MUST for the server to do so. */ | 939 | * but this is not required as a MUST for the server to do so. */ |
937 | hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen; | 940 | hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen; |
938 | 941 | ||
939 | BUG_ON(hdr->taglen > NFS4_MAXTAGLEN); | 942 | WARN_ON_ONCE(hdr->taglen > NFS4_MAXTAGLEN); |
940 | encode_string(xdr, hdr->taglen, hdr->tag); | 943 | encode_string(xdr, hdr->taglen, hdr->tag); |
941 | p = reserve_space(xdr, 8); | 944 | p = reserve_space(xdr, 8); |
942 | *p++ = cpu_to_be32(hdr->minorversion); | 945 | *p++ = cpu_to_be32(hdr->minorversion); |
@@ -955,7 +958,7 @@ static void encode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 op, | |||
955 | 958 | ||
956 | static void encode_nops(struct compound_hdr *hdr) | 959 | static void encode_nops(struct compound_hdr *hdr) |
957 | { | 960 | { |
958 | BUG_ON(hdr->nops > NFS4_MAX_OPS); | 961 | WARN_ON_ONCE(hdr->nops > NFS4_MAX_OPS); |
959 | *hdr->nops_p = htonl(hdr->nops); | 962 | *hdr->nops_p = htonl(hdr->nops); |
960 | } | 963 | } |
961 | 964 | ||
@@ -1403,7 +1406,6 @@ static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *a | |||
1403 | *p = cpu_to_be32(NFS4_OPEN_NOCREATE); | 1406 | *p = cpu_to_be32(NFS4_OPEN_NOCREATE); |
1404 | break; | 1407 | break; |
1405 | default: | 1408 | default: |
1406 | BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL); | ||
1407 | *p = cpu_to_be32(NFS4_OPEN_CREATE); | 1409 | *p = cpu_to_be32(NFS4_OPEN_CREATE); |
1408 | encode_createmode(xdr, arg); | 1410 | encode_createmode(xdr, arg); |
1409 | } | 1411 | } |
@@ -1621,7 +1623,6 @@ encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compoun | |||
1621 | p = reserve_space(xdr, 2*4); | 1623 | p = reserve_space(xdr, 2*4); |
1622 | *p++ = cpu_to_be32(1); | 1624 | *p++ = cpu_to_be32(1); |
1623 | *p = cpu_to_be32(FATTR4_WORD0_ACL); | 1625 | *p = cpu_to_be32(FATTR4_WORD0_ACL); |
1624 | BUG_ON(arg->acl_len % 4); | ||
1625 | p = reserve_space(xdr, 4); | 1626 | p = reserve_space(xdr, 4); |
1626 | *p = cpu_to_be32(arg->acl_len); | 1627 | *p = cpu_to_be32(arg->acl_len); |
1627 | xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len); | 1628 | xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len); |
@@ -1713,7 +1714,7 @@ static void encode_exchange_id(struct xdr_stream *xdr, | |||
1713 | struct compound_hdr *hdr) | 1714 | struct compound_hdr *hdr) |
1714 | { | 1715 | { |
1715 | __be32 *p; | 1716 | __be32 *p; |
1716 | char impl_name[NFS4_OPAQUE_LIMIT]; | 1717 | char impl_name[IMPL_NAME_LIMIT]; |
1717 | int len = 0; | 1718 | int len = 0; |
1718 | 1719 | ||
1719 | encode_op_hdr(xdr, OP_EXCHANGE_ID, decode_exchange_id_maxsz, hdr); | 1720 | encode_op_hdr(xdr, OP_EXCHANGE_ID, decode_exchange_id_maxsz, hdr); |
@@ -1728,7 +1729,7 @@ static void encode_exchange_id(struct xdr_stream *xdr, | |||
1728 | if (send_implementation_id && | 1729 | if (send_implementation_id && |
1729 | sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 && | 1730 | sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 && |
1730 | sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) | 1731 | sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) |
1731 | <= NFS4_OPAQUE_LIMIT + 1) | 1732 | <= sizeof(impl_name) + 1) |
1732 | len = snprintf(impl_name, sizeof(impl_name), "%s %s %s %s", | 1733 | len = snprintf(impl_name, sizeof(impl_name), "%s %s %s %s", |
1733 | utsname()->sysname, utsname()->release, | 1734 | utsname()->sysname, utsname()->release, |
1734 | utsname()->version, utsname()->machine); | 1735 | utsname()->version, utsname()->machine); |
@@ -1835,18 +1836,16 @@ static void encode_sequence(struct xdr_stream *xdr, | |||
1835 | struct compound_hdr *hdr) | 1836 | struct compound_hdr *hdr) |
1836 | { | 1837 | { |
1837 | #if defined(CONFIG_NFS_V4_1) | 1838 | #if defined(CONFIG_NFS_V4_1) |
1838 | struct nfs4_session *session = args->sa_session; | 1839 | struct nfs4_session *session; |
1839 | struct nfs4_slot_table *tp; | 1840 | struct nfs4_slot_table *tp; |
1840 | struct nfs4_slot *slot; | 1841 | struct nfs4_slot *slot = args->sa_slot; |
1841 | __be32 *p; | 1842 | __be32 *p; |
1842 | 1843 | ||
1843 | if (!session) | 1844 | if (slot == NULL) |
1844 | return; | 1845 | return; |
1845 | 1846 | ||
1846 | tp = &session->fc_slot_table; | 1847 | tp = slot->table; |
1847 | 1848 | session = tp->session; | |
1848 | WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE); | ||
1849 | slot = tp->slots + args->sa_slotid; | ||
1850 | 1849 | ||
1851 | encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr); | 1850 | encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr); |
1852 | 1851 | ||
@@ -1860,12 +1859,12 @@ static void encode_sequence(struct xdr_stream *xdr, | |||
1860 | ((u32 *)session->sess_id.data)[1], | 1859 | ((u32 *)session->sess_id.data)[1], |
1861 | ((u32 *)session->sess_id.data)[2], | 1860 | ((u32 *)session->sess_id.data)[2], |
1862 | ((u32 *)session->sess_id.data)[3], | 1861 | ((u32 *)session->sess_id.data)[3], |
1863 | slot->seq_nr, args->sa_slotid, | 1862 | slot->seq_nr, slot->slot_nr, |
1864 | tp->highest_used_slotid, args->sa_cache_this); | 1863 | tp->highest_used_slotid, args->sa_cache_this); |
1865 | p = reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 16); | 1864 | p = reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 16); |
1866 | p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); | 1865 | p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); |
1867 | *p++ = cpu_to_be32(slot->seq_nr); | 1866 | *p++ = cpu_to_be32(slot->seq_nr); |
1868 | *p++ = cpu_to_be32(args->sa_slotid); | 1867 | *p++ = cpu_to_be32(slot->slot_nr); |
1869 | *p++ = cpu_to_be32(tp->highest_used_slotid); | 1868 | *p++ = cpu_to_be32(tp->highest_used_slotid); |
1870 | *p = cpu_to_be32(args->sa_cache_this); | 1869 | *p = cpu_to_be32(args->sa_cache_this); |
1871 | #endif /* CONFIG_NFS_V4_1 */ | 1870 | #endif /* CONFIG_NFS_V4_1 */ |
@@ -2027,8 +2026,9 @@ static void encode_free_stateid(struct xdr_stream *xdr, | |||
2027 | static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args) | 2026 | static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args) |
2028 | { | 2027 | { |
2029 | #if defined(CONFIG_NFS_V4_1) | 2028 | #if defined(CONFIG_NFS_V4_1) |
2030 | if (args->sa_session) | 2029 | |
2031 | return args->sa_session->clp->cl_mvops->minor_version; | 2030 | if (args->sa_slot) |
2031 | return args->sa_slot->table->session->clp->cl_mvops->minor_version; | ||
2032 | #endif /* CONFIG_NFS_V4_1 */ | 2032 | #endif /* CONFIG_NFS_V4_1 */ |
2033 | return 0; | 2033 | return 0; |
2034 | } | 2034 | } |
@@ -5509,12 +5509,13 @@ static int decode_sequence(struct xdr_stream *xdr, | |||
5509 | struct rpc_rqst *rqstp) | 5509 | struct rpc_rqst *rqstp) |
5510 | { | 5510 | { |
5511 | #if defined(CONFIG_NFS_V4_1) | 5511 | #if defined(CONFIG_NFS_V4_1) |
5512 | struct nfs4_session *session; | ||
5512 | struct nfs4_sessionid id; | 5513 | struct nfs4_sessionid id; |
5513 | u32 dummy; | 5514 | u32 dummy; |
5514 | int status; | 5515 | int status; |
5515 | __be32 *p; | 5516 | __be32 *p; |
5516 | 5517 | ||
5517 | if (!res->sr_session) | 5518 | if (res->sr_slot == NULL) |
5518 | return 0; | 5519 | return 0; |
5519 | 5520 | ||
5520 | status = decode_op_hdr(xdr, OP_SEQUENCE); | 5521 | status = decode_op_hdr(xdr, OP_SEQUENCE); |
@@ -5528,8 +5529,9 @@ static int decode_sequence(struct xdr_stream *xdr, | |||
5528 | * sequence number, the server is looney tunes. | 5529 | * sequence number, the server is looney tunes. |
5529 | */ | 5530 | */ |
5530 | status = -EREMOTEIO; | 5531 | status = -EREMOTEIO; |
5532 | session = res->sr_slot->table->session; | ||
5531 | 5533 | ||
5532 | if (memcmp(id.data, res->sr_session->sess_id.data, | 5534 | if (memcmp(id.data, session->sess_id.data, |
5533 | NFS4_MAX_SESSIONID_LEN)) { | 5535 | NFS4_MAX_SESSIONID_LEN)) { |
5534 | dprintk("%s Invalid session id\n", __func__); | 5536 | dprintk("%s Invalid session id\n", __func__); |
5535 | goto out_err; | 5537 | goto out_err; |
@@ -5547,14 +5549,14 @@ static int decode_sequence(struct xdr_stream *xdr, | |||
5547 | } | 5549 | } |
5548 | /* slot id */ | 5550 | /* slot id */ |
5549 | dummy = be32_to_cpup(p++); | 5551 | dummy = be32_to_cpup(p++); |
5550 | if (dummy != res->sr_slot - res->sr_session->fc_slot_table.slots) { | 5552 | if (dummy != res->sr_slot->slot_nr) { |
5551 | dprintk("%s Invalid slot id\n", __func__); | 5553 | dprintk("%s Invalid slot id\n", __func__); |
5552 | goto out_err; | 5554 | goto out_err; |
5553 | } | 5555 | } |
5554 | /* highest slot id - currently not processed */ | 5556 | /* highest slot id */ |
5555 | dummy = be32_to_cpup(p++); | 5557 | res->sr_highest_slotid = be32_to_cpup(p++); |
5556 | /* target highest slot id - currently not processed */ | 5558 | /* target highest slot id */ |
5557 | dummy = be32_to_cpup(p++); | 5559 | res->sr_target_highest_slotid = be32_to_cpup(p++); |
5558 | /* result flags */ | 5560 | /* result flags */ |
5559 | res->sr_status_flags = be32_to_cpup(p); | 5561 | res->sr_status_flags = be32_to_cpup(p); |
5560 | status = 0; | 5562 | status = 0; |
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c index 87461354530..a9ebd817278 100644 --- a/fs/nfs/objlayout/objlayout.c +++ b/fs/nfs/objlayout/objlayout.c | |||
@@ -148,17 +148,6 @@ end_offset(u64 start, u64 len) | |||
148 | return end >= start ? end : NFS4_MAX_UINT64; | 148 | return end >= start ? end : NFS4_MAX_UINT64; |
149 | } | 149 | } |
150 | 150 | ||
151 | /* last octet in a range */ | ||
152 | static inline u64 | ||
153 | last_byte_offset(u64 start, u64 len) | ||
154 | { | ||
155 | u64 end; | ||
156 | |||
157 | BUG_ON(!len); | ||
158 | end = start + len; | ||
159 | return end > start ? end - 1 : NFS4_MAX_UINT64; | ||
160 | } | ||
161 | |||
162 | static void _fix_verify_io_params(struct pnfs_layout_segment *lseg, | 151 | static void _fix_verify_io_params(struct pnfs_layout_segment *lseg, |
163 | struct page ***p_pages, unsigned *p_pgbase, | 152 | struct page ***p_pages, unsigned *p_pgbase, |
164 | u64 offset, unsigned long count) | 153 | u64 offset, unsigned long count) |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 2878f97bd78..e7165d91536 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -369,17 +369,6 @@ end_offset(u64 start, u64 len) | |||
369 | return end >= start ? end : NFS4_MAX_UINT64; | 369 | return end >= start ? end : NFS4_MAX_UINT64; |
370 | } | 370 | } |
371 | 371 | ||
372 | /* last octet in a range */ | ||
373 | static inline u64 | ||
374 | last_byte_offset(u64 start, u64 len) | ||
375 | { | ||
376 | u64 end; | ||
377 | |||
378 | BUG_ON(!len); | ||
379 | end = start + len; | ||
380 | return end > start ? end - 1 : NFS4_MAX_UINT64; | ||
381 | } | ||
382 | |||
383 | /* | 372 | /* |
384 | * is l2 fully contained in l1? | 373 | * is l2 fully contained in l1? |
385 | * start1 end1 | 374 | * start1 end1 |
@@ -645,7 +634,6 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
645 | 634 | ||
646 | dprintk("--> %s\n", __func__); | 635 | dprintk("--> %s\n", __func__); |
647 | 636 | ||
648 | BUG_ON(ctx == NULL); | ||
649 | lgp = kzalloc(sizeof(*lgp), gfp_flags); | 637 | lgp = kzalloc(sizeof(*lgp), gfp_flags); |
650 | if (lgp == NULL) | 638 | if (lgp == NULL) |
651 | return NULL; | 639 | return NULL; |
@@ -1126,7 +1114,6 @@ pnfs_update_layout(struct inode *ino, | |||
1126 | * chance of a CB_LAYOUTRECALL(FILE) coming in. | 1114 | * chance of a CB_LAYOUTRECALL(FILE) coming in. |
1127 | */ | 1115 | */ |
1128 | spin_lock(&clp->cl_lock); | 1116 | spin_lock(&clp->cl_lock); |
1129 | BUG_ON(!list_empty(&lo->plh_layouts)); | ||
1130 | list_add_tail(&lo->plh_layouts, &server->layouts); | 1117 | list_add_tail(&lo->plh_layouts, &server->layouts); |
1131 | spin_unlock(&clp->cl_lock); | 1118 | spin_unlock(&clp->cl_lock); |
1132 | } | 1119 | } |
@@ -1222,7 +1209,7 @@ pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *r | |||
1222 | { | 1209 | { |
1223 | u64 rd_size = req->wb_bytes; | 1210 | u64 rd_size = req->wb_bytes; |
1224 | 1211 | ||
1225 | BUG_ON(pgio->pg_lseg != NULL); | 1212 | WARN_ON_ONCE(pgio->pg_lseg != NULL); |
1226 | 1213 | ||
1227 | if (req->wb_offset != req->wb_pgbase) { | 1214 | if (req->wb_offset != req->wb_pgbase) { |
1228 | nfs_pageio_reset_read_mds(pgio); | 1215 | nfs_pageio_reset_read_mds(pgio); |
@@ -1251,7 +1238,7 @@ void | |||
1251 | pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, | 1238 | pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, |
1252 | struct nfs_page *req, u64 wb_size) | 1239 | struct nfs_page *req, u64 wb_size) |
1253 | { | 1240 | { |
1254 | BUG_ON(pgio->pg_lseg != NULL); | 1241 | WARN_ON_ONCE(pgio->pg_lseg != NULL); |
1255 | 1242 | ||
1256 | if (req->wb_offset != req->wb_pgbase) { | 1243 | if (req->wb_offset != req->wb_pgbase) { |
1257 | nfs_pageio_reset_write_mds(pgio); | 1244 | nfs_pageio_reset_write_mds(pgio); |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 50a88c3546e..f084dac948e 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -47,39 +47,6 @@ | |||
47 | #define NFSDBG_FACILITY NFSDBG_PROC | 47 | #define NFSDBG_FACILITY NFSDBG_PROC |
48 | 48 | ||
49 | /* | 49 | /* |
50 | * wrapper to handle the -EKEYEXPIRED error message. This should generally | ||
51 | * only happen if using krb5 auth and a user's TGT expires. NFSv2 doesn't | ||
52 | * support the NFSERR_JUKEBOX error code, but we handle this situation in the | ||
53 | * same way that we handle that error with NFSv3. | ||
54 | */ | ||
55 | static int | ||
56 | nfs_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) | ||
57 | { | ||
58 | int res; | ||
59 | do { | ||
60 | res = rpc_call_sync(clnt, msg, flags); | ||
61 | if (res != -EKEYEXPIRED) | ||
62 | break; | ||
63 | freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); | ||
64 | res = -ERESTARTSYS; | ||
65 | } while (!fatal_signal_pending(current)); | ||
66 | return res; | ||
67 | } | ||
68 | |||
69 | #define rpc_call_sync(clnt, msg, flags) nfs_rpc_wrapper(clnt, msg, flags) | ||
70 | |||
71 | static int | ||
72 | nfs_async_handle_expired_key(struct rpc_task *task) | ||
73 | { | ||
74 | if (task->tk_status != -EKEYEXPIRED) | ||
75 | return 0; | ||
76 | task->tk_status = 0; | ||
77 | rpc_restart_call(task); | ||
78 | rpc_delay(task, NFS_JUKEBOX_RETRY_TIME); | ||
79 | return 1; | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Bare-bones access to getattr: this is for nfs_read_super. | 50 | * Bare-bones access to getattr: this is for nfs_read_super. |
84 | */ | 51 | */ |
85 | static int | 52 | static int |
@@ -364,8 +331,6 @@ static void nfs_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlink | |||
364 | 331 | ||
365 | static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir) | 332 | static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir) |
366 | { | 333 | { |
367 | if (nfs_async_handle_expired_key(task)) | ||
368 | return 0; | ||
369 | nfs_mark_for_revalidate(dir); | 334 | nfs_mark_for_revalidate(dir); |
370 | return 1; | 335 | return 1; |
371 | } | 336 | } |
@@ -385,8 +350,6 @@ static int | |||
385 | nfs_proc_rename_done(struct rpc_task *task, struct inode *old_dir, | 350 | nfs_proc_rename_done(struct rpc_task *task, struct inode *old_dir, |
386 | struct inode *new_dir) | 351 | struct inode *new_dir) |
387 | { | 352 | { |
388 | if (nfs_async_handle_expired_key(task)) | ||
389 | return 0; | ||
390 | nfs_mark_for_revalidate(old_dir); | 353 | nfs_mark_for_revalidate(old_dir); |
391 | nfs_mark_for_revalidate(new_dir); | 354 | nfs_mark_for_revalidate(new_dir); |
392 | return 1; | 355 | return 1; |
@@ -642,9 +605,6 @@ static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data) | |||
642 | { | 605 | { |
643 | struct inode *inode = data->header->inode; | 606 | struct inode *inode = data->header->inode; |
644 | 607 | ||
645 | if (nfs_async_handle_expired_key(task)) | ||
646 | return -EAGAIN; | ||
647 | |||
648 | nfs_invalidate_atime(inode); | 608 | nfs_invalidate_atime(inode); |
649 | if (task->tk_status >= 0) { | 609 | if (task->tk_status >= 0) { |
650 | nfs_refresh_inode(inode, data->res.fattr); | 610 | nfs_refresh_inode(inode, data->res.fattr); |
@@ -671,9 +631,6 @@ static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) | |||
671 | { | 631 | { |
672 | struct inode *inode = data->header->inode; | 632 | struct inode *inode = data->header->inode; |
673 | 633 | ||
674 | if (nfs_async_handle_expired_key(task)) | ||
675 | return -EAGAIN; | ||
676 | |||
677 | if (task->tk_status >= 0) | 634 | if (task->tk_status >= 0) |
678 | nfs_post_op_update_inode_force_wcc(inode, data->res.fattr); | 635 | nfs_post_op_update_inode_force_wcc(inode, data->res.fattr); |
679 | return 0; | 636 | return 0; |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 652d3f7176a..aa5315bb366 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include "iostat.h" | 64 | #include "iostat.h" |
65 | #include "internal.h" | 65 | #include "internal.h" |
66 | #include "fscache.h" | 66 | #include "fscache.h" |
67 | #include "nfs4session.h" | ||
67 | #include "pnfs.h" | 68 | #include "pnfs.h" |
68 | #include "nfs.h" | 69 | #include "nfs.h" |
69 | 70 | ||
@@ -307,6 +308,7 @@ const struct super_operations nfs_sops = { | |||
307 | .alloc_inode = nfs_alloc_inode, | 308 | .alloc_inode = nfs_alloc_inode, |
308 | .destroy_inode = nfs_destroy_inode, | 309 | .destroy_inode = nfs_destroy_inode, |
309 | .write_inode = nfs_write_inode, | 310 | .write_inode = nfs_write_inode, |
311 | .drop_inode = nfs_drop_inode, | ||
310 | .put_super = nfs_put_super, | 312 | .put_super = nfs_put_super, |
311 | .statfs = nfs_statfs, | 313 | .statfs = nfs_statfs, |
312 | .evict_inode = nfs_evict_inode, | 314 | .evict_inode = nfs_evict_inode, |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 9347ab7c957..5209916e122 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -202,7 +202,6 @@ out: | |||
202 | /* A writeback failed: mark the page as bad, and invalidate the page cache */ | 202 | /* A writeback failed: mark the page as bad, and invalidate the page cache */ |
203 | static void nfs_set_pageerror(struct page *page) | 203 | static void nfs_set_pageerror(struct page *page) |
204 | { | 204 | { |
205 | SetPageError(page); | ||
206 | nfs_zap_mapping(page_file_mapping(page)->host, page_file_mapping(page)); | 205 | nfs_zap_mapping(page_file_mapping(page)->host, page_file_mapping(page)); |
207 | } | 206 | } |
208 | 207 | ||
@@ -239,21 +238,18 @@ int nfs_congestion_kb; | |||
239 | #define NFS_CONGESTION_OFF_THRESH \ | 238 | #define NFS_CONGESTION_OFF_THRESH \ |
240 | (NFS_CONGESTION_ON_THRESH - (NFS_CONGESTION_ON_THRESH >> 2)) | 239 | (NFS_CONGESTION_ON_THRESH - (NFS_CONGESTION_ON_THRESH >> 2)) |
241 | 240 | ||
242 | static int nfs_set_page_writeback(struct page *page) | 241 | static void nfs_set_page_writeback(struct page *page) |
243 | { | 242 | { |
243 | struct nfs_server *nfss = NFS_SERVER(page_file_mapping(page)->host); | ||
244 | int ret = test_set_page_writeback(page); | 244 | int ret = test_set_page_writeback(page); |
245 | 245 | ||
246 | if (!ret) { | 246 | WARN_ON_ONCE(ret != 0); |
247 | struct inode *inode = page_file_mapping(page)->host; | ||
248 | struct nfs_server *nfss = NFS_SERVER(inode); | ||
249 | 247 | ||
250 | if (atomic_long_inc_return(&nfss->writeback) > | 248 | if (atomic_long_inc_return(&nfss->writeback) > |
251 | NFS_CONGESTION_ON_THRESH) { | 249 | NFS_CONGESTION_ON_THRESH) { |
252 | set_bdi_congested(&nfss->backing_dev_info, | 250 | set_bdi_congested(&nfss->backing_dev_info, |
253 | BLK_RW_ASYNC); | 251 | BLK_RW_ASYNC); |
254 | } | ||
255 | } | 252 | } |
256 | return ret; | ||
257 | } | 253 | } |
258 | 254 | ||
259 | static void nfs_end_page_writeback(struct page *page) | 255 | static void nfs_end_page_writeback(struct page *page) |
@@ -315,10 +311,10 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
315 | if (IS_ERR(req)) | 311 | if (IS_ERR(req)) |
316 | goto out; | 312 | goto out; |
317 | 313 | ||
318 | ret = nfs_set_page_writeback(page); | 314 | nfs_set_page_writeback(page); |
319 | BUG_ON(ret != 0); | 315 | WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags)); |
320 | BUG_ON(test_bit(PG_CLEAN, &req->wb_flags)); | ||
321 | 316 | ||
317 | ret = 0; | ||
322 | if (!nfs_pageio_add_request(pgio, req)) { | 318 | if (!nfs_pageio_add_request(pgio, req)) { |
323 | nfs_redirty_request(req); | 319 | nfs_redirty_request(req); |
324 | ret = pgio->pg_error; | 320 | ret = pgio->pg_error; |
@@ -451,8 +447,6 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
451 | struct inode *inode = req->wb_context->dentry->d_inode; | 447 | struct inode *inode = req->wb_context->dentry->d_inode; |
452 | struct nfs_inode *nfsi = NFS_I(inode); | 448 | struct nfs_inode *nfsi = NFS_I(inode); |
453 | 449 | ||
454 | BUG_ON (!NFS_WBACK_BUSY(req)); | ||
455 | |||
456 | spin_lock(&inode->i_lock); | 450 | spin_lock(&inode->i_lock); |
457 | if (likely(!PageSwapCache(req->wb_page))) { | 451 | if (likely(!PageSwapCache(req->wb_page))) { |
458 | set_page_private(req->wb_page, 0); | 452 | set_page_private(req->wb_page, 0); |
@@ -884,7 +878,7 @@ static bool nfs_write_pageuptodate(struct page *page, struct inode *inode) | |||
884 | { | 878 | { |
885 | if (nfs_have_delegated_attributes(inode)) | 879 | if (nfs_have_delegated_attributes(inode)) |
886 | goto out; | 880 | goto out; |
887 | if (NFS_I(inode)->cache_validity & NFS_INO_REVAL_PAGECACHE) | 881 | if (NFS_I(inode)->cache_validity & (NFS_INO_INVALID_DATA|NFS_INO_REVAL_PAGECACHE)) |
888 | return false; | 882 | return false; |
889 | out: | 883 | out: |
890 | return PageUptodate(page) != 0; | 884 | return PageUptodate(page) != 0; |
@@ -1727,7 +1721,6 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page) | |||
1727 | struct nfs_page *req; | 1721 | struct nfs_page *req; |
1728 | int ret = 0; | 1722 | int ret = 0; |
1729 | 1723 | ||
1730 | BUG_ON(!PageLocked(page)); | ||
1731 | for (;;) { | 1724 | for (;;) { |
1732 | wait_on_page_writeback(page); | 1725 | wait_on_page_writeback(page); |
1733 | req = nfs_page_find_request(page); | 1726 | req = nfs_page_find_request(page); |
@@ -1829,7 +1822,7 @@ int __init nfs_init_writepagecache(void) | |||
1829 | goto out_destroy_write_mempool; | 1822 | goto out_destroy_write_mempool; |
1830 | 1823 | ||
1831 | nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT, | 1824 | nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT, |
1832 | nfs_wdata_cachep); | 1825 | nfs_cdata_cachep); |
1833 | if (nfs_commit_mempool == NULL) | 1826 | if (nfs_commit_mempool == NULL) |
1834 | goto out_destroy_commit_cache; | 1827 | goto out_destroy_commit_cache; |
1835 | 1828 | ||
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index a9e76ee1adc..6c6ed153a9b 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h | |||
@@ -198,51 +198,4 @@ struct nfs_server { | |||
198 | #define NFS_CAP_POSIX_LOCK (1U << 14) | 198 | #define NFS_CAP_POSIX_LOCK (1U << 14) |
199 | #define NFS_CAP_UIDGID_NOMAP (1U << 15) | 199 | #define NFS_CAP_UIDGID_NOMAP (1U << 15) |
200 | 200 | ||
201 | |||
202 | /* maximum number of slots to use */ | ||
203 | #define NFS4_DEF_SLOT_TABLE_SIZE (16U) | ||
204 | #define NFS4_MAX_SLOT_TABLE (256U) | ||
205 | #define NFS4_NO_SLOT ((u32)-1) | ||
206 | |||
207 | #if IS_ENABLED(CONFIG_NFS_V4) | ||
208 | |||
209 | /* Sessions */ | ||
210 | #define SLOT_TABLE_SZ DIV_ROUND_UP(NFS4_MAX_SLOT_TABLE, 8*sizeof(long)) | ||
211 | struct nfs4_slot_table { | ||
212 | struct nfs4_slot *slots; /* seqid per slot */ | ||
213 | unsigned long used_slots[SLOT_TABLE_SZ]; /* used/unused bitmap */ | ||
214 | spinlock_t slot_tbl_lock; | ||
215 | struct rpc_wait_queue slot_tbl_waitq; /* allocators may wait here */ | ||
216 | u32 max_slots; /* # slots in table */ | ||
217 | u32 highest_used_slotid; /* sent to server on each SEQ. | ||
218 | * op for dynamic resizing */ | ||
219 | u32 target_max_slots; /* Set by CB_RECALL_SLOT as | ||
220 | * the new max_slots */ | ||
221 | struct completion complete; | ||
222 | }; | ||
223 | |||
224 | static inline int slot_idx(struct nfs4_slot_table *tbl, struct nfs4_slot *sp) | ||
225 | { | ||
226 | return sp - tbl->slots; | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * Session related parameters | ||
231 | */ | ||
232 | struct nfs4_session { | ||
233 | struct nfs4_sessionid sess_id; | ||
234 | u32 flags; | ||
235 | unsigned long session_state; | ||
236 | u32 hash_alg; | ||
237 | u32 ssv_len; | ||
238 | |||
239 | /* The fore and back channel */ | ||
240 | struct nfs4_channel_attrs fc_attrs; | ||
241 | struct nfs4_slot_table fc_slot_table; | ||
242 | struct nfs4_channel_attrs bc_attrs; | ||
243 | struct nfs4_slot_table bc_slot_table; | ||
244 | struct nfs_client *clp; | ||
245 | }; | ||
246 | |||
247 | #endif /* CONFIG_NFS_V4 */ | ||
248 | #endif | 201 | #endif |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index a73ea89789d..29adb12c7ec 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -185,23 +185,20 @@ struct nfs4_channel_attrs { | |||
185 | u32 max_reqs; | 185 | u32 max_reqs; |
186 | }; | 186 | }; |
187 | 187 | ||
188 | /* nfs41 sessions slot seqid */ | 188 | struct nfs4_slot; |
189 | struct nfs4_slot { | ||
190 | u32 seq_nr; | ||
191 | }; | ||
192 | |||
193 | struct nfs4_sequence_args { | 189 | struct nfs4_sequence_args { |
194 | struct nfs4_session *sa_session; | 190 | struct nfs4_slot *sa_slot; |
195 | u32 sa_slotid; | 191 | u8 sa_cache_this : 1, |
196 | u8 sa_cache_this; | 192 | sa_privileged : 1; |
197 | }; | 193 | }; |
198 | 194 | ||
199 | struct nfs4_sequence_res { | 195 | struct nfs4_sequence_res { |
200 | struct nfs4_session *sr_session; | ||
201 | struct nfs4_slot *sr_slot; /* slot used to send request */ | 196 | struct nfs4_slot *sr_slot; /* slot used to send request */ |
197 | unsigned long sr_timestamp; | ||
202 | int sr_status; /* sequence operation status */ | 198 | int sr_status; /* sequence operation status */ |
203 | unsigned long sr_renewal_time; | ||
204 | u32 sr_status_flags; | 199 | u32 sr_status_flags; |
200 | u32 sr_highest_slotid; | ||
201 | u32 sr_target_highest_slotid; | ||
205 | }; | 202 | }; |
206 | 203 | ||
207 | struct nfs4_get_lease_time_args { | 204 | struct nfs4_get_lease_time_args { |
@@ -209,8 +206,8 @@ struct nfs4_get_lease_time_args { | |||
209 | }; | 206 | }; |
210 | 207 | ||
211 | struct nfs4_get_lease_time_res { | 208 | struct nfs4_get_lease_time_res { |
212 | struct nfs_fsinfo *lr_fsinfo; | ||
213 | struct nfs4_sequence_res lr_seq_res; | 209 | struct nfs4_sequence_res lr_seq_res; |
210 | struct nfs_fsinfo *lr_fsinfo; | ||
214 | }; | 211 | }; |
215 | 212 | ||
216 | #define PNFS_LAYOUT_MAXSIZE 4096 | 213 | #define PNFS_LAYOUT_MAXSIZE 4096 |
@@ -228,23 +225,23 @@ struct pnfs_layout_range { | |||
228 | }; | 225 | }; |
229 | 226 | ||
230 | struct nfs4_layoutget_args { | 227 | struct nfs4_layoutget_args { |
228 | struct nfs4_sequence_args seq_args; | ||
231 | __u32 type; | 229 | __u32 type; |
232 | struct pnfs_layout_range range; | 230 | struct pnfs_layout_range range; |
233 | __u64 minlength; | 231 | __u64 minlength; |
234 | __u32 maxcount; | 232 | __u32 maxcount; |
235 | struct inode *inode; | 233 | struct inode *inode; |
236 | struct nfs_open_context *ctx; | 234 | struct nfs_open_context *ctx; |
237 | struct nfs4_sequence_args seq_args; | ||
238 | nfs4_stateid stateid; | 235 | nfs4_stateid stateid; |
239 | struct nfs4_layoutdriver_data layout; | 236 | struct nfs4_layoutdriver_data layout; |
240 | }; | 237 | }; |
241 | 238 | ||
242 | struct nfs4_layoutget_res { | 239 | struct nfs4_layoutget_res { |
240 | struct nfs4_sequence_res seq_res; | ||
243 | __u32 return_on_close; | 241 | __u32 return_on_close; |
244 | struct pnfs_layout_range range; | 242 | struct pnfs_layout_range range; |
245 | __u32 type; | 243 | __u32 type; |
246 | nfs4_stateid stateid; | 244 | nfs4_stateid stateid; |
247 | struct nfs4_sequence_res seq_res; | ||
248 | struct nfs4_layoutdriver_data *layoutp; | 245 | struct nfs4_layoutdriver_data *layoutp; |
249 | }; | 246 | }; |
250 | 247 | ||
@@ -255,38 +252,38 @@ struct nfs4_layoutget { | |||
255 | }; | 252 | }; |
256 | 253 | ||
257 | struct nfs4_getdevicelist_args { | 254 | struct nfs4_getdevicelist_args { |
255 | struct nfs4_sequence_args seq_args; | ||
258 | const struct nfs_fh *fh; | 256 | const struct nfs_fh *fh; |
259 | u32 layoutclass; | 257 | u32 layoutclass; |
260 | struct nfs4_sequence_args seq_args; | ||
261 | }; | 258 | }; |
262 | 259 | ||
263 | struct nfs4_getdevicelist_res { | 260 | struct nfs4_getdevicelist_res { |
264 | struct pnfs_devicelist *devlist; | ||
265 | struct nfs4_sequence_res seq_res; | 261 | struct nfs4_sequence_res seq_res; |
262 | struct pnfs_devicelist *devlist; | ||
266 | }; | 263 | }; |
267 | 264 | ||
268 | struct nfs4_getdeviceinfo_args { | 265 | struct nfs4_getdeviceinfo_args { |
269 | struct pnfs_device *pdev; | ||
270 | struct nfs4_sequence_args seq_args; | 266 | struct nfs4_sequence_args seq_args; |
267 | struct pnfs_device *pdev; | ||
271 | }; | 268 | }; |
272 | 269 | ||
273 | struct nfs4_getdeviceinfo_res { | 270 | struct nfs4_getdeviceinfo_res { |
274 | struct pnfs_device *pdev; | ||
275 | struct nfs4_sequence_res seq_res; | 271 | struct nfs4_sequence_res seq_res; |
272 | struct pnfs_device *pdev; | ||
276 | }; | 273 | }; |
277 | 274 | ||
278 | struct nfs4_layoutcommit_args { | 275 | struct nfs4_layoutcommit_args { |
276 | struct nfs4_sequence_args seq_args; | ||
279 | nfs4_stateid stateid; | 277 | nfs4_stateid stateid; |
280 | __u64 lastbytewritten; | 278 | __u64 lastbytewritten; |
281 | struct inode *inode; | 279 | struct inode *inode; |
282 | const u32 *bitmask; | 280 | const u32 *bitmask; |
283 | struct nfs4_sequence_args seq_args; | ||
284 | }; | 281 | }; |
285 | 282 | ||
286 | struct nfs4_layoutcommit_res { | 283 | struct nfs4_layoutcommit_res { |
284 | struct nfs4_sequence_res seq_res; | ||
287 | struct nfs_fattr *fattr; | 285 | struct nfs_fattr *fattr; |
288 | const struct nfs_server *server; | 286 | const struct nfs_server *server; |
289 | struct nfs4_sequence_res seq_res; | ||
290 | int status; | 287 | int status; |
291 | }; | 288 | }; |
292 | 289 | ||
@@ -300,11 +297,11 @@ struct nfs4_layoutcommit_data { | |||
300 | }; | 297 | }; |
301 | 298 | ||
302 | struct nfs4_layoutreturn_args { | 299 | struct nfs4_layoutreturn_args { |
300 | struct nfs4_sequence_args seq_args; | ||
303 | struct pnfs_layout_hdr *layout; | 301 | struct pnfs_layout_hdr *layout; |
304 | struct inode *inode; | 302 | struct inode *inode; |
305 | nfs4_stateid stateid; | 303 | nfs4_stateid stateid; |
306 | __u32 layout_type; | 304 | __u32 layout_type; |
307 | struct nfs4_sequence_args seq_args; | ||
308 | }; | 305 | }; |
309 | 306 | ||
310 | struct nfs4_layoutreturn_res { | 307 | struct nfs4_layoutreturn_res { |
@@ -330,6 +327,7 @@ struct stateowner_id { | |||
330 | * Arguments to the open call. | 327 | * Arguments to the open call. |
331 | */ | 328 | */ |
332 | struct nfs_openargs { | 329 | struct nfs_openargs { |
330 | struct nfs4_sequence_args seq_args; | ||
333 | const struct nfs_fh * fh; | 331 | const struct nfs_fh * fh; |
334 | struct nfs_seqid * seqid; | 332 | struct nfs_seqid * seqid; |
335 | int open_flags; | 333 | int open_flags; |
@@ -350,10 +348,10 @@ struct nfs_openargs { | |||
350 | const u32 * bitmask; | 348 | const u32 * bitmask; |
351 | const u32 * open_bitmap; | 349 | const u32 * open_bitmap; |
352 | __u32 claim; | 350 | __u32 claim; |
353 | struct nfs4_sequence_args seq_args; | ||
354 | }; | 351 | }; |
355 | 352 | ||
356 | struct nfs_openres { | 353 | struct nfs_openres { |
354 | struct nfs4_sequence_res seq_res; | ||
357 | nfs4_stateid stateid; | 355 | nfs4_stateid stateid; |
358 | struct nfs_fh fh; | 356 | struct nfs_fh fh; |
359 | struct nfs4_change_info cinfo; | 357 | struct nfs4_change_info cinfo; |
@@ -368,7 +366,6 @@ struct nfs_openres { | |||
368 | __u32 attrset[NFS4_BITMAP_SIZE]; | 366 | __u32 attrset[NFS4_BITMAP_SIZE]; |
369 | struct nfs4_string *owner; | 367 | struct nfs4_string *owner; |
370 | struct nfs4_string *group_owner; | 368 | struct nfs4_string *group_owner; |
371 | struct nfs4_sequence_res seq_res; | ||
372 | __u32 access_request; | 369 | __u32 access_request; |
373 | __u32 access_supported; | 370 | __u32 access_supported; |
374 | __u32 access_result; | 371 | __u32 access_result; |
@@ -392,20 +389,20 @@ struct nfs_open_confirmres { | |||
392 | * Arguments to the close call. | 389 | * Arguments to the close call. |
393 | */ | 390 | */ |
394 | struct nfs_closeargs { | 391 | struct nfs_closeargs { |
392 | struct nfs4_sequence_args seq_args; | ||
395 | struct nfs_fh * fh; | 393 | struct nfs_fh * fh; |
396 | nfs4_stateid * stateid; | 394 | nfs4_stateid * stateid; |
397 | struct nfs_seqid * seqid; | 395 | struct nfs_seqid * seqid; |
398 | fmode_t fmode; | 396 | fmode_t fmode; |
399 | const u32 * bitmask; | 397 | const u32 * bitmask; |
400 | struct nfs4_sequence_args seq_args; | ||
401 | }; | 398 | }; |
402 | 399 | ||
403 | struct nfs_closeres { | 400 | struct nfs_closeres { |
401 | struct nfs4_sequence_res seq_res; | ||
404 | nfs4_stateid stateid; | 402 | nfs4_stateid stateid; |
405 | struct nfs_fattr * fattr; | 403 | struct nfs_fattr * fattr; |
406 | struct nfs_seqid * seqid; | 404 | struct nfs_seqid * seqid; |
407 | const struct nfs_server *server; | 405 | const struct nfs_server *server; |
408 | struct nfs4_sequence_res seq_res; | ||
409 | }; | 406 | }; |
410 | /* | 407 | /* |
411 | * * Arguments to the lock,lockt, and locku call. | 408 | * * Arguments to the lock,lockt, and locku call. |
@@ -417,6 +414,7 @@ struct nfs_lowner { | |||
417 | }; | 414 | }; |
418 | 415 | ||
419 | struct nfs_lock_args { | 416 | struct nfs_lock_args { |
417 | struct nfs4_sequence_args seq_args; | ||
420 | struct nfs_fh * fh; | 418 | struct nfs_fh * fh; |
421 | struct file_lock * fl; | 419 | struct file_lock * fl; |
422 | struct nfs_seqid * lock_seqid; | 420 | struct nfs_seqid * lock_seqid; |
@@ -427,40 +425,39 @@ struct nfs_lock_args { | |||
427 | unsigned char block : 1; | 425 | unsigned char block : 1; |
428 | unsigned char reclaim : 1; | 426 | unsigned char reclaim : 1; |
429 | unsigned char new_lock_owner : 1; | 427 | unsigned char new_lock_owner : 1; |
430 | struct nfs4_sequence_args seq_args; | ||
431 | }; | 428 | }; |
432 | 429 | ||
433 | struct nfs_lock_res { | 430 | struct nfs_lock_res { |
431 | struct nfs4_sequence_res seq_res; | ||
434 | nfs4_stateid stateid; | 432 | nfs4_stateid stateid; |
435 | struct nfs_seqid * lock_seqid; | 433 | struct nfs_seqid * lock_seqid; |
436 | struct nfs_seqid * open_seqid; | 434 | struct nfs_seqid * open_seqid; |
437 | struct nfs4_sequence_res seq_res; | ||
438 | }; | 435 | }; |
439 | 436 | ||
440 | struct nfs_locku_args { | 437 | struct nfs_locku_args { |
438 | struct nfs4_sequence_args seq_args; | ||
441 | struct nfs_fh * fh; | 439 | struct nfs_fh * fh; |
442 | struct file_lock * fl; | 440 | struct file_lock * fl; |
443 | struct nfs_seqid * seqid; | 441 | struct nfs_seqid * seqid; |
444 | nfs4_stateid * stateid; | 442 | nfs4_stateid * stateid; |
445 | struct nfs4_sequence_args seq_args; | ||
446 | }; | 443 | }; |
447 | 444 | ||
448 | struct nfs_locku_res { | 445 | struct nfs_locku_res { |
446 | struct nfs4_sequence_res seq_res; | ||
449 | nfs4_stateid stateid; | 447 | nfs4_stateid stateid; |
450 | struct nfs_seqid * seqid; | 448 | struct nfs_seqid * seqid; |
451 | struct nfs4_sequence_res seq_res; | ||
452 | }; | 449 | }; |
453 | 450 | ||
454 | struct nfs_lockt_args { | 451 | struct nfs_lockt_args { |
452 | struct nfs4_sequence_args seq_args; | ||
455 | struct nfs_fh * fh; | 453 | struct nfs_fh * fh; |
456 | struct file_lock * fl; | 454 | struct file_lock * fl; |
457 | struct nfs_lowner lock_owner; | 455 | struct nfs_lowner lock_owner; |
458 | struct nfs4_sequence_args seq_args; | ||
459 | }; | 456 | }; |
460 | 457 | ||
461 | struct nfs_lockt_res { | 458 | struct nfs_lockt_res { |
462 | struct file_lock * denied; /* LOCK, LOCKT failed */ | ||
463 | struct nfs4_sequence_res seq_res; | 459 | struct nfs4_sequence_res seq_res; |
460 | struct file_lock * denied; /* LOCK, LOCKT failed */ | ||
464 | }; | 461 | }; |
465 | 462 | ||
466 | struct nfs_release_lockowner_args { | 463 | struct nfs_release_lockowner_args { |
@@ -468,22 +465,23 @@ struct nfs_release_lockowner_args { | |||
468 | }; | 465 | }; |
469 | 466 | ||
470 | struct nfs4_delegreturnargs { | 467 | struct nfs4_delegreturnargs { |
468 | struct nfs4_sequence_args seq_args; | ||
471 | const struct nfs_fh *fhandle; | 469 | const struct nfs_fh *fhandle; |
472 | const nfs4_stateid *stateid; | 470 | const nfs4_stateid *stateid; |
473 | const u32 * bitmask; | 471 | const u32 * bitmask; |
474 | struct nfs4_sequence_args seq_args; | ||
475 | }; | 472 | }; |
476 | 473 | ||
477 | struct nfs4_delegreturnres { | 474 | struct nfs4_delegreturnres { |
475 | struct nfs4_sequence_res seq_res; | ||
478 | struct nfs_fattr * fattr; | 476 | struct nfs_fattr * fattr; |
479 | const struct nfs_server *server; | 477 | const struct nfs_server *server; |
480 | struct nfs4_sequence_res seq_res; | ||
481 | }; | 478 | }; |
482 | 479 | ||
483 | /* | 480 | /* |
484 | * Arguments to the read call. | 481 | * Arguments to the read call. |
485 | */ | 482 | */ |
486 | struct nfs_readargs { | 483 | struct nfs_readargs { |
484 | struct nfs4_sequence_args seq_args; | ||
487 | struct nfs_fh * fh; | 485 | struct nfs_fh * fh; |
488 | struct nfs_open_context *context; | 486 | struct nfs_open_context *context; |
489 | struct nfs_lock_context *lock_context; | 487 | struct nfs_lock_context *lock_context; |
@@ -491,20 +489,20 @@ struct nfs_readargs { | |||
491 | __u32 count; | 489 | __u32 count; |
492 | unsigned int pgbase; | 490 | unsigned int pgbase; |
493 | struct page ** pages; | 491 | struct page ** pages; |
494 | struct nfs4_sequence_args seq_args; | ||
495 | }; | 492 | }; |
496 | 493 | ||
497 | struct nfs_readres { | 494 | struct nfs_readres { |
495 | struct nfs4_sequence_res seq_res; | ||
498 | struct nfs_fattr * fattr; | 496 | struct nfs_fattr * fattr; |
499 | __u32 count; | 497 | __u32 count; |
500 | int eof; | 498 | int eof; |
501 | struct nfs4_sequence_res seq_res; | ||
502 | }; | 499 | }; |
503 | 500 | ||
504 | /* | 501 | /* |
505 | * Arguments to the write call. | 502 | * Arguments to the write call. |
506 | */ | 503 | */ |
507 | struct nfs_writeargs { | 504 | struct nfs_writeargs { |
505 | struct nfs4_sequence_args seq_args; | ||
508 | struct nfs_fh * fh; | 506 | struct nfs_fh * fh; |
509 | struct nfs_open_context *context; | 507 | struct nfs_open_context *context; |
510 | struct nfs_lock_context *lock_context; | 508 | struct nfs_lock_context *lock_context; |
@@ -514,7 +512,6 @@ struct nfs_writeargs { | |||
514 | unsigned int pgbase; | 512 | unsigned int pgbase; |
515 | struct page ** pages; | 513 | struct page ** pages; |
516 | const u32 * bitmask; | 514 | const u32 * bitmask; |
517 | struct nfs4_sequence_args seq_args; | ||
518 | }; | 515 | }; |
519 | 516 | ||
520 | struct nfs_write_verifier { | 517 | struct nfs_write_verifier { |
@@ -527,65 +524,65 @@ struct nfs_writeverf { | |||
527 | }; | 524 | }; |
528 | 525 | ||
529 | struct nfs_writeres { | 526 | struct nfs_writeres { |
527 | struct nfs4_sequence_res seq_res; | ||
530 | struct nfs_fattr * fattr; | 528 | struct nfs_fattr * fattr; |
531 | struct nfs_writeverf * verf; | 529 | struct nfs_writeverf * verf; |
532 | __u32 count; | 530 | __u32 count; |
533 | const struct nfs_server *server; | 531 | const struct nfs_server *server; |
534 | struct nfs4_sequence_res seq_res; | ||
535 | }; | 532 | }; |
536 | 533 | ||
537 | /* | 534 | /* |
538 | * Arguments to the commit call. | 535 | * Arguments to the commit call. |
539 | */ | 536 | */ |
540 | struct nfs_commitargs { | 537 | struct nfs_commitargs { |
538 | struct nfs4_sequence_args seq_args; | ||
541 | struct nfs_fh *fh; | 539 | struct nfs_fh *fh; |
542 | __u64 offset; | 540 | __u64 offset; |
543 | __u32 count; | 541 | __u32 count; |
544 | const u32 *bitmask; | 542 | const u32 *bitmask; |
545 | struct nfs4_sequence_args seq_args; | ||
546 | }; | 543 | }; |
547 | 544 | ||
548 | struct nfs_commitres { | 545 | struct nfs_commitres { |
546 | struct nfs4_sequence_res seq_res; | ||
549 | struct nfs_fattr *fattr; | 547 | struct nfs_fattr *fattr; |
550 | struct nfs_writeverf *verf; | 548 | struct nfs_writeverf *verf; |
551 | const struct nfs_server *server; | 549 | const struct nfs_server *server; |
552 | struct nfs4_sequence_res seq_res; | ||
553 | }; | 550 | }; |
554 | 551 | ||
555 | /* | 552 | /* |
556 | * Common arguments to the unlink call | 553 | * Common arguments to the unlink call |
557 | */ | 554 | */ |
558 | struct nfs_removeargs { | 555 | struct nfs_removeargs { |
556 | struct nfs4_sequence_args seq_args; | ||
559 | const struct nfs_fh *fh; | 557 | const struct nfs_fh *fh; |
560 | struct qstr name; | 558 | struct qstr name; |
561 | struct nfs4_sequence_args seq_args; | ||
562 | }; | 559 | }; |
563 | 560 | ||
564 | struct nfs_removeres { | 561 | struct nfs_removeres { |
562 | struct nfs4_sequence_res seq_res; | ||
565 | const struct nfs_server *server; | 563 | const struct nfs_server *server; |
566 | struct nfs_fattr *dir_attr; | 564 | struct nfs_fattr *dir_attr; |
567 | struct nfs4_change_info cinfo; | 565 | struct nfs4_change_info cinfo; |
568 | struct nfs4_sequence_res seq_res; | ||
569 | }; | 566 | }; |
570 | 567 | ||
571 | /* | 568 | /* |
572 | * Common arguments to the rename call | 569 | * Common arguments to the rename call |
573 | */ | 570 | */ |
574 | struct nfs_renameargs { | 571 | struct nfs_renameargs { |
572 | struct nfs4_sequence_args seq_args; | ||
575 | const struct nfs_fh *old_dir; | 573 | const struct nfs_fh *old_dir; |
576 | const struct nfs_fh *new_dir; | 574 | const struct nfs_fh *new_dir; |
577 | const struct qstr *old_name; | 575 | const struct qstr *old_name; |
578 | const struct qstr *new_name; | 576 | const struct qstr *new_name; |
579 | struct nfs4_sequence_args seq_args; | ||
580 | }; | 577 | }; |
581 | 578 | ||
582 | struct nfs_renameres { | 579 | struct nfs_renameres { |
580 | struct nfs4_sequence_res seq_res; | ||
583 | const struct nfs_server *server; | 581 | const struct nfs_server *server; |
584 | struct nfs4_change_info old_cinfo; | 582 | struct nfs4_change_info old_cinfo; |
585 | struct nfs_fattr *old_fattr; | 583 | struct nfs_fattr *old_fattr; |
586 | struct nfs4_change_info new_cinfo; | 584 | struct nfs4_change_info new_cinfo; |
587 | struct nfs_fattr *new_fattr; | 585 | struct nfs_fattr *new_fattr; |
588 | struct nfs4_sequence_res seq_res; | ||
589 | }; | 586 | }; |
590 | 587 | ||
591 | /* | 588 | /* |
@@ -626,20 +623,20 @@ struct nfs_createargs { | |||
626 | }; | 623 | }; |
627 | 624 | ||
628 | struct nfs_setattrargs { | 625 | struct nfs_setattrargs { |
626 | struct nfs4_sequence_args seq_args; | ||
629 | struct nfs_fh * fh; | 627 | struct nfs_fh * fh; |
630 | nfs4_stateid stateid; | 628 | nfs4_stateid stateid; |
631 | struct iattr * iap; | 629 | struct iattr * iap; |
632 | const struct nfs_server * server; /* Needed for name mapping */ | 630 | const struct nfs_server * server; /* Needed for name mapping */ |
633 | const u32 * bitmask; | 631 | const u32 * bitmask; |
634 | struct nfs4_sequence_args seq_args; | ||
635 | }; | 632 | }; |
636 | 633 | ||
637 | struct nfs_setaclargs { | 634 | struct nfs_setaclargs { |
635 | struct nfs4_sequence_args seq_args; | ||
638 | struct nfs_fh * fh; | 636 | struct nfs_fh * fh; |
639 | size_t acl_len; | 637 | size_t acl_len; |
640 | unsigned int acl_pgbase; | 638 | unsigned int acl_pgbase; |
641 | struct page ** acl_pages; | 639 | struct page ** acl_pages; |
642 | struct nfs4_sequence_args seq_args; | ||
643 | }; | 640 | }; |
644 | 641 | ||
645 | struct nfs_setaclres { | 642 | struct nfs_setaclres { |
@@ -647,27 +644,27 @@ struct nfs_setaclres { | |||
647 | }; | 644 | }; |
648 | 645 | ||
649 | struct nfs_getaclargs { | 646 | struct nfs_getaclargs { |
647 | struct nfs4_sequence_args seq_args; | ||
650 | struct nfs_fh * fh; | 648 | struct nfs_fh * fh; |
651 | size_t acl_len; | 649 | size_t acl_len; |
652 | unsigned int acl_pgbase; | 650 | unsigned int acl_pgbase; |
653 | struct page ** acl_pages; | 651 | struct page ** acl_pages; |
654 | struct nfs4_sequence_args seq_args; | ||
655 | }; | 652 | }; |
656 | 653 | ||
657 | /* getxattr ACL interface flags */ | 654 | /* getxattr ACL interface flags */ |
658 | #define NFS4_ACL_TRUNC 0x0001 /* ACL was truncated */ | 655 | #define NFS4_ACL_TRUNC 0x0001 /* ACL was truncated */ |
659 | struct nfs_getaclres { | 656 | struct nfs_getaclres { |
657 | struct nfs4_sequence_res seq_res; | ||
660 | size_t acl_len; | 658 | size_t acl_len; |
661 | size_t acl_data_offset; | 659 | size_t acl_data_offset; |
662 | int acl_flags; | 660 | int acl_flags; |
663 | struct page * acl_scratch; | 661 | struct page * acl_scratch; |
664 | struct nfs4_sequence_res seq_res; | ||
665 | }; | 662 | }; |
666 | 663 | ||
667 | struct nfs_setattrres { | 664 | struct nfs_setattrres { |
665 | struct nfs4_sequence_res seq_res; | ||
668 | struct nfs_fattr * fattr; | 666 | struct nfs_fattr * fattr; |
669 | const struct nfs_server * server; | 667 | const struct nfs_server * server; |
670 | struct nfs4_sequence_res seq_res; | ||
671 | }; | 668 | }; |
672 | 669 | ||
673 | struct nfs_linkargs { | 670 | struct nfs_linkargs { |
@@ -832,21 +829,22 @@ struct nfs3_getaclres { | |||
832 | typedef u64 clientid4; | 829 | typedef u64 clientid4; |
833 | 830 | ||
834 | struct nfs4_accessargs { | 831 | struct nfs4_accessargs { |
832 | struct nfs4_sequence_args seq_args; | ||
835 | const struct nfs_fh * fh; | 833 | const struct nfs_fh * fh; |
836 | const u32 * bitmask; | 834 | const u32 * bitmask; |
837 | u32 access; | 835 | u32 access; |
838 | struct nfs4_sequence_args seq_args; | ||
839 | }; | 836 | }; |
840 | 837 | ||
841 | struct nfs4_accessres { | 838 | struct nfs4_accessres { |
839 | struct nfs4_sequence_res seq_res; | ||
842 | const struct nfs_server * server; | 840 | const struct nfs_server * server; |
843 | struct nfs_fattr * fattr; | 841 | struct nfs_fattr * fattr; |
844 | u32 supported; | 842 | u32 supported; |
845 | u32 access; | 843 | u32 access; |
846 | struct nfs4_sequence_res seq_res; | ||
847 | }; | 844 | }; |
848 | 845 | ||
849 | struct nfs4_create_arg { | 846 | struct nfs4_create_arg { |
847 | struct nfs4_sequence_args seq_args; | ||
850 | u32 ftype; | 848 | u32 ftype; |
851 | union { | 849 | union { |
852 | struct { | 850 | struct { |
@@ -863,88 +861,88 @@ struct nfs4_create_arg { | |||
863 | const struct iattr * attrs; | 861 | const struct iattr * attrs; |
864 | const struct nfs_fh * dir_fh; | 862 | const struct nfs_fh * dir_fh; |
865 | const u32 * bitmask; | 863 | const u32 * bitmask; |
866 | struct nfs4_sequence_args seq_args; | ||
867 | }; | 864 | }; |
868 | 865 | ||
869 | struct nfs4_create_res { | 866 | struct nfs4_create_res { |
867 | struct nfs4_sequence_res seq_res; | ||
870 | const struct nfs_server * server; | 868 | const struct nfs_server * server; |
871 | struct nfs_fh * fh; | 869 | struct nfs_fh * fh; |
872 | struct nfs_fattr * fattr; | 870 | struct nfs_fattr * fattr; |
873 | struct nfs4_change_info dir_cinfo; | 871 | struct nfs4_change_info dir_cinfo; |
874 | struct nfs4_sequence_res seq_res; | ||
875 | }; | 872 | }; |
876 | 873 | ||
877 | struct nfs4_fsinfo_arg { | 874 | struct nfs4_fsinfo_arg { |
875 | struct nfs4_sequence_args seq_args; | ||
878 | const struct nfs_fh * fh; | 876 | const struct nfs_fh * fh; |
879 | const u32 * bitmask; | 877 | const u32 * bitmask; |
880 | struct nfs4_sequence_args seq_args; | ||
881 | }; | 878 | }; |
882 | 879 | ||
883 | struct nfs4_fsinfo_res { | 880 | struct nfs4_fsinfo_res { |
884 | struct nfs_fsinfo *fsinfo; | ||
885 | struct nfs4_sequence_res seq_res; | 881 | struct nfs4_sequence_res seq_res; |
882 | struct nfs_fsinfo *fsinfo; | ||
886 | }; | 883 | }; |
887 | 884 | ||
888 | struct nfs4_getattr_arg { | 885 | struct nfs4_getattr_arg { |
886 | struct nfs4_sequence_args seq_args; | ||
889 | const struct nfs_fh * fh; | 887 | const struct nfs_fh * fh; |
890 | const u32 * bitmask; | 888 | const u32 * bitmask; |
891 | struct nfs4_sequence_args seq_args; | ||
892 | }; | 889 | }; |
893 | 890 | ||
894 | struct nfs4_getattr_res { | 891 | struct nfs4_getattr_res { |
892 | struct nfs4_sequence_res seq_res; | ||
895 | const struct nfs_server * server; | 893 | const struct nfs_server * server; |
896 | struct nfs_fattr * fattr; | 894 | struct nfs_fattr * fattr; |
897 | struct nfs4_sequence_res seq_res; | ||
898 | }; | 895 | }; |
899 | 896 | ||
900 | struct nfs4_link_arg { | 897 | struct nfs4_link_arg { |
898 | struct nfs4_sequence_args seq_args; | ||
901 | const struct nfs_fh * fh; | 899 | const struct nfs_fh * fh; |
902 | const struct nfs_fh * dir_fh; | 900 | const struct nfs_fh * dir_fh; |
903 | const struct qstr * name; | 901 | const struct qstr * name; |
904 | const u32 * bitmask; | 902 | const u32 * bitmask; |
905 | struct nfs4_sequence_args seq_args; | ||
906 | }; | 903 | }; |
907 | 904 | ||
908 | struct nfs4_link_res { | 905 | struct nfs4_link_res { |
906 | struct nfs4_sequence_res seq_res; | ||
909 | const struct nfs_server * server; | 907 | const struct nfs_server * server; |
910 | struct nfs_fattr * fattr; | 908 | struct nfs_fattr * fattr; |
911 | struct nfs4_change_info cinfo; | 909 | struct nfs4_change_info cinfo; |
912 | struct nfs_fattr * dir_attr; | 910 | struct nfs_fattr * dir_attr; |
913 | struct nfs4_sequence_res seq_res; | ||
914 | }; | 911 | }; |
915 | 912 | ||
916 | 913 | ||
917 | struct nfs4_lookup_arg { | 914 | struct nfs4_lookup_arg { |
915 | struct nfs4_sequence_args seq_args; | ||
918 | const struct nfs_fh * dir_fh; | 916 | const struct nfs_fh * dir_fh; |
919 | const struct qstr * name; | 917 | const struct qstr * name; |
920 | const u32 * bitmask; | 918 | const u32 * bitmask; |
921 | struct nfs4_sequence_args seq_args; | ||
922 | }; | 919 | }; |
923 | 920 | ||
924 | struct nfs4_lookup_res { | 921 | struct nfs4_lookup_res { |
922 | struct nfs4_sequence_res seq_res; | ||
925 | const struct nfs_server * server; | 923 | const struct nfs_server * server; |
926 | struct nfs_fattr * fattr; | 924 | struct nfs_fattr * fattr; |
927 | struct nfs_fh * fh; | 925 | struct nfs_fh * fh; |
928 | struct nfs4_sequence_res seq_res; | ||
929 | }; | 926 | }; |
930 | 927 | ||
931 | struct nfs4_lookup_root_arg { | 928 | struct nfs4_lookup_root_arg { |
932 | const u32 * bitmask; | ||
933 | struct nfs4_sequence_args seq_args; | 929 | struct nfs4_sequence_args seq_args; |
930 | const u32 * bitmask; | ||
934 | }; | 931 | }; |
935 | 932 | ||
936 | struct nfs4_pathconf_arg { | 933 | struct nfs4_pathconf_arg { |
934 | struct nfs4_sequence_args seq_args; | ||
937 | const struct nfs_fh * fh; | 935 | const struct nfs_fh * fh; |
938 | const u32 * bitmask; | 936 | const u32 * bitmask; |
939 | struct nfs4_sequence_args seq_args; | ||
940 | }; | 937 | }; |
941 | 938 | ||
942 | struct nfs4_pathconf_res { | 939 | struct nfs4_pathconf_res { |
943 | struct nfs_pathconf *pathconf; | ||
944 | struct nfs4_sequence_res seq_res; | 940 | struct nfs4_sequence_res seq_res; |
941 | struct nfs_pathconf *pathconf; | ||
945 | }; | 942 | }; |
946 | 943 | ||
947 | struct nfs4_readdir_arg { | 944 | struct nfs4_readdir_arg { |
945 | struct nfs4_sequence_args seq_args; | ||
948 | const struct nfs_fh * fh; | 946 | const struct nfs_fh * fh; |
949 | u64 cookie; | 947 | u64 cookie; |
950 | nfs4_verifier verifier; | 948 | nfs4_verifier verifier; |
@@ -953,21 +951,20 @@ struct nfs4_readdir_arg { | |||
953 | unsigned int pgbase; /* zero-copy data */ | 951 | unsigned int pgbase; /* zero-copy data */ |
954 | const u32 * bitmask; | 952 | const u32 * bitmask; |
955 | int plus; | 953 | int plus; |
956 | struct nfs4_sequence_args seq_args; | ||
957 | }; | 954 | }; |
958 | 955 | ||
959 | struct nfs4_readdir_res { | 956 | struct nfs4_readdir_res { |
957 | struct nfs4_sequence_res seq_res; | ||
960 | nfs4_verifier verifier; | 958 | nfs4_verifier verifier; |
961 | unsigned int pgbase; | 959 | unsigned int pgbase; |
962 | struct nfs4_sequence_res seq_res; | ||
963 | }; | 960 | }; |
964 | 961 | ||
965 | struct nfs4_readlink { | 962 | struct nfs4_readlink { |
963 | struct nfs4_sequence_args seq_args; | ||
966 | const struct nfs_fh * fh; | 964 | const struct nfs_fh * fh; |
967 | unsigned int pgbase; | 965 | unsigned int pgbase; |
968 | unsigned int pglen; /* zero-copy data */ | 966 | unsigned int pglen; /* zero-copy data */ |
969 | struct page ** pages; /* zero-copy data */ | 967 | struct page ** pages; /* zero-copy data */ |
970 | struct nfs4_sequence_args seq_args; | ||
971 | }; | 968 | }; |
972 | 969 | ||
973 | struct nfs4_readlink_res { | 970 | struct nfs4_readlink_res { |
@@ -993,28 +990,28 @@ struct nfs4_setclientid_res { | |||
993 | }; | 990 | }; |
994 | 991 | ||
995 | struct nfs4_statfs_arg { | 992 | struct nfs4_statfs_arg { |
993 | struct nfs4_sequence_args seq_args; | ||
996 | const struct nfs_fh * fh; | 994 | const struct nfs_fh * fh; |
997 | const u32 * bitmask; | 995 | const u32 * bitmask; |
998 | struct nfs4_sequence_args seq_args; | ||
999 | }; | 996 | }; |
1000 | 997 | ||
1001 | struct nfs4_statfs_res { | 998 | struct nfs4_statfs_res { |
1002 | struct nfs_fsstat *fsstat; | ||
1003 | struct nfs4_sequence_res seq_res; | 999 | struct nfs4_sequence_res seq_res; |
1000 | struct nfs_fsstat *fsstat; | ||
1004 | }; | 1001 | }; |
1005 | 1002 | ||
1006 | struct nfs4_server_caps_arg { | 1003 | struct nfs4_server_caps_arg { |
1007 | struct nfs_fh *fhandle; | ||
1008 | struct nfs4_sequence_args seq_args; | 1004 | struct nfs4_sequence_args seq_args; |
1005 | struct nfs_fh *fhandle; | ||
1009 | }; | 1006 | }; |
1010 | 1007 | ||
1011 | struct nfs4_server_caps_res { | 1008 | struct nfs4_server_caps_res { |
1009 | struct nfs4_sequence_res seq_res; | ||
1012 | u32 attr_bitmask[3]; | 1010 | u32 attr_bitmask[3]; |
1013 | u32 acl_bitmask; | 1011 | u32 acl_bitmask; |
1014 | u32 has_links; | 1012 | u32 has_links; |
1015 | u32 has_symlinks; | 1013 | u32 has_symlinks; |
1016 | u32 fh_expire_type; | 1014 | u32 fh_expire_type; |
1017 | struct nfs4_sequence_res seq_res; | ||
1018 | }; | 1015 | }; |
1019 | 1016 | ||
1020 | #define NFS4_PATHNAME_MAXCOMPONENTS 512 | 1017 | #define NFS4_PATHNAME_MAXCOMPONENTS 512 |
@@ -1040,16 +1037,16 @@ struct nfs4_fs_locations { | |||
1040 | }; | 1037 | }; |
1041 | 1038 | ||
1042 | struct nfs4_fs_locations_arg { | 1039 | struct nfs4_fs_locations_arg { |
1040 | struct nfs4_sequence_args seq_args; | ||
1043 | const struct nfs_fh *dir_fh; | 1041 | const struct nfs_fh *dir_fh; |
1044 | const struct qstr *name; | 1042 | const struct qstr *name; |
1045 | struct page *page; | 1043 | struct page *page; |
1046 | const u32 *bitmask; | 1044 | const u32 *bitmask; |
1047 | struct nfs4_sequence_args seq_args; | ||
1048 | }; | 1045 | }; |
1049 | 1046 | ||
1050 | struct nfs4_fs_locations_res { | 1047 | struct nfs4_fs_locations_res { |
1051 | struct nfs4_fs_locations *fs_locations; | ||
1052 | struct nfs4_sequence_res seq_res; | 1048 | struct nfs4_sequence_res seq_res; |
1049 | struct nfs4_fs_locations *fs_locations; | ||
1053 | }; | 1050 | }; |
1054 | 1051 | ||
1055 | struct nfs4_secinfo_oid { | 1052 | struct nfs4_secinfo_oid { |
@@ -1074,14 +1071,14 @@ struct nfs4_secinfo_flavors { | |||
1074 | }; | 1071 | }; |
1075 | 1072 | ||
1076 | struct nfs4_secinfo_arg { | 1073 | struct nfs4_secinfo_arg { |
1074 | struct nfs4_sequence_args seq_args; | ||
1077 | const struct nfs_fh *dir_fh; | 1075 | const struct nfs_fh *dir_fh; |
1078 | const struct qstr *name; | 1076 | const struct qstr *name; |
1079 | struct nfs4_sequence_args seq_args; | ||
1080 | }; | 1077 | }; |
1081 | 1078 | ||
1082 | struct nfs4_secinfo_res { | 1079 | struct nfs4_secinfo_res { |
1083 | struct nfs4_secinfo_flavors *flavors; | ||
1084 | struct nfs4_sequence_res seq_res; | 1080 | struct nfs4_sequence_res seq_res; |
1081 | struct nfs4_secinfo_flavors *flavors; | ||
1085 | }; | 1082 | }; |
1086 | 1083 | ||
1087 | #endif /* CONFIG_NFS_V4 */ | 1084 | #endif /* CONFIG_NFS_V4 */ |
@@ -1161,9 +1158,9 @@ struct nfs41_create_session_res { | |||
1161 | }; | 1158 | }; |
1162 | 1159 | ||
1163 | struct nfs41_reclaim_complete_args { | 1160 | struct nfs41_reclaim_complete_args { |
1161 | struct nfs4_sequence_args seq_args; | ||
1164 | /* In the future extend to include curr_fh for use with migration */ | 1162 | /* In the future extend to include curr_fh for use with migration */ |
1165 | unsigned char one_fs:1; | 1163 | unsigned char one_fs:1; |
1166 | struct nfs4_sequence_args seq_args; | ||
1167 | }; | 1164 | }; |
1168 | 1165 | ||
1169 | struct nfs41_reclaim_complete_res { | 1166 | struct nfs41_reclaim_complete_res { |
@@ -1173,28 +1170,28 @@ struct nfs41_reclaim_complete_res { | |||
1173 | #define SECINFO_STYLE_CURRENT_FH 0 | 1170 | #define SECINFO_STYLE_CURRENT_FH 0 |
1174 | #define SECINFO_STYLE_PARENT 1 | 1171 | #define SECINFO_STYLE_PARENT 1 |
1175 | struct nfs41_secinfo_no_name_args { | 1172 | struct nfs41_secinfo_no_name_args { |
1176 | int style; | ||
1177 | struct nfs4_sequence_args seq_args; | 1173 | struct nfs4_sequence_args seq_args; |
1174 | int style; | ||
1178 | }; | 1175 | }; |
1179 | 1176 | ||
1180 | struct nfs41_test_stateid_args { | 1177 | struct nfs41_test_stateid_args { |
1181 | nfs4_stateid *stateid; | ||
1182 | struct nfs4_sequence_args seq_args; | 1178 | struct nfs4_sequence_args seq_args; |
1179 | nfs4_stateid *stateid; | ||
1183 | }; | 1180 | }; |
1184 | 1181 | ||
1185 | struct nfs41_test_stateid_res { | 1182 | struct nfs41_test_stateid_res { |
1186 | unsigned int status; | ||
1187 | struct nfs4_sequence_res seq_res; | 1183 | struct nfs4_sequence_res seq_res; |
1184 | unsigned int status; | ||
1188 | }; | 1185 | }; |
1189 | 1186 | ||
1190 | struct nfs41_free_stateid_args { | 1187 | struct nfs41_free_stateid_args { |
1191 | nfs4_stateid *stateid; | ||
1192 | struct nfs4_sequence_args seq_args; | 1188 | struct nfs4_sequence_args seq_args; |
1189 | nfs4_stateid *stateid; | ||
1193 | }; | 1190 | }; |
1194 | 1191 | ||
1195 | struct nfs41_free_stateid_res { | 1192 | struct nfs41_free_stateid_res { |
1196 | unsigned int status; | ||
1197 | struct nfs4_sequence_res seq_res; | 1193 | struct nfs4_sequence_res seq_res; |
1194 | unsigned int status; | ||
1198 | }; | 1195 | }; |
1199 | 1196 | ||
1200 | #else | 1197 | #else |
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index dc0c3cc3ada..b64f8eb0b97 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h | |||
@@ -192,7 +192,6 @@ struct rpc_wait_queue { | |||
192 | pid_t owner; /* process id of last task serviced */ | 192 | pid_t owner; /* process id of last task serviced */ |
193 | unsigned char maxpriority; /* maximum priority (0 if queue is not a priority queue) */ | 193 | unsigned char maxpriority; /* maximum priority (0 if queue is not a priority queue) */ |
194 | unsigned char priority; /* current priority */ | 194 | unsigned char priority; /* current priority */ |
195 | unsigned char count; /* # task groups remaining serviced so far */ | ||
196 | unsigned char nr; /* # tasks remaining for cookie */ | 195 | unsigned char nr; /* # tasks remaining for cookie */ |
197 | unsigned short qlen; /* total # tasks waiting in queue */ | 196 | unsigned short qlen; /* total # tasks waiting in queue */ |
198 | struct rpc_timer timer_list; | 197 | struct rpc_timer timer_list; |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 909dc0c31aa..6e5c824b040 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -192,17 +192,23 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct | |||
192 | const void *q; | 192 | const void *q; |
193 | unsigned int seclen; | 193 | unsigned int seclen; |
194 | unsigned int timeout; | 194 | unsigned int timeout; |
195 | unsigned long now = jiffies; | ||
195 | u32 window_size; | 196 | u32 window_size; |
196 | int ret; | 197 | int ret; |
197 | 198 | ||
198 | /* First unsigned int gives the lifetime (in seconds) of the cred */ | 199 | /* First unsigned int gives the remaining lifetime in seconds of the |
200 | * credential - e.g. the remaining TGT lifetime for Kerberos or | ||
201 | * the -t value passed to GSSD. | ||
202 | */ | ||
199 | p = simple_get_bytes(p, end, &timeout, sizeof(timeout)); | 203 | p = simple_get_bytes(p, end, &timeout, sizeof(timeout)); |
200 | if (IS_ERR(p)) | 204 | if (IS_ERR(p)) |
201 | goto err; | 205 | goto err; |
202 | if (timeout == 0) | 206 | if (timeout == 0) |
203 | timeout = GSSD_MIN_TIMEOUT; | 207 | timeout = GSSD_MIN_TIMEOUT; |
204 | ctx->gc_expiry = jiffies + (unsigned long)timeout * HZ * 3 / 4; | 208 | ctx->gc_expiry = now + ((unsigned long)timeout * HZ); |
205 | /* Sequence number window. Determines the maximum number of simultaneous requests */ | 209 | /* Sequence number window. Determines the maximum number of |
210 | * simultaneous requests | ||
211 | */ | ||
206 | p = simple_get_bytes(p, end, &window_size, sizeof(window_size)); | 212 | p = simple_get_bytes(p, end, &window_size, sizeof(window_size)); |
207 | if (IS_ERR(p)) | 213 | if (IS_ERR(p)) |
208 | goto err; | 214 | goto err; |
@@ -237,9 +243,12 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct | |||
237 | p = ERR_PTR(ret); | 243 | p = ERR_PTR(ret); |
238 | goto err; | 244 | goto err; |
239 | } | 245 | } |
246 | dprintk("RPC: %s Success. gc_expiry %lu now %lu timeout %u\n", | ||
247 | __func__, ctx->gc_expiry, now, timeout); | ||
240 | return q; | 248 | return q; |
241 | err: | 249 | err: |
242 | dprintk("RPC: %s returning %ld\n", __func__, -PTR_ERR(p)); | 250 | dprintk("RPC: %s returns %ld gc_expiry %lu now %lu timeout %u\n", |
251 | __func__, -PTR_ERR(p), ctx->gc_expiry, now, timeout); | ||
243 | return p; | 252 | return p; |
244 | } | 253 | } |
245 | 254 | ||
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index a9c0bbccad6..890a29912d5 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c | |||
@@ -59,7 +59,7 @@ static void xprt_free_allocation(struct rpc_rqst *req) | |||
59 | struct xdr_buf *xbufp; | 59 | struct xdr_buf *xbufp; |
60 | 60 | ||
61 | dprintk("RPC: free allocations for req= %p\n", req); | 61 | dprintk("RPC: free allocations for req= %p\n", req); |
62 | BUG_ON(test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); | 62 | WARN_ON_ONCE(test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); |
63 | xbufp = &req->rq_private_buf; | 63 | xbufp = &req->rq_private_buf; |
64 | free_page((unsigned long)xbufp->head[0].iov_base); | 64 | free_page((unsigned long)xbufp->head[0].iov_base); |
65 | xbufp = &req->rq_snd_buf; | 65 | xbufp = &req->rq_snd_buf; |
@@ -191,7 +191,9 @@ void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs) | |||
191 | 191 | ||
192 | dprintk("RPC: destroy backchannel transport\n"); | 192 | dprintk("RPC: destroy backchannel transport\n"); |
193 | 193 | ||
194 | BUG_ON(max_reqs == 0); | 194 | if (max_reqs == 0) |
195 | goto out; | ||
196 | |||
195 | spin_lock_bh(&xprt->bc_pa_lock); | 197 | spin_lock_bh(&xprt->bc_pa_lock); |
196 | xprt_dec_alloc_count(xprt, max_reqs); | 198 | xprt_dec_alloc_count(xprt, max_reqs); |
197 | list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) { | 199 | list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) { |
@@ -202,6 +204,7 @@ void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs) | |||
202 | } | 204 | } |
203 | spin_unlock_bh(&xprt->bc_pa_lock); | 205 | spin_unlock_bh(&xprt->bc_pa_lock); |
204 | 206 | ||
207 | out: | ||
205 | dprintk("RPC: backchannel list empty= %s\n", | 208 | dprintk("RPC: backchannel list empty= %s\n", |
206 | list_empty(&xprt->bc_pa_list) ? "true" : "false"); | 209 | list_empty(&xprt->bc_pa_list) ? "true" : "false"); |
207 | } | 210 | } |
@@ -255,7 +258,7 @@ void xprt_free_bc_request(struct rpc_rqst *req) | |||
255 | dprintk("RPC: free backchannel req=%p\n", req); | 258 | dprintk("RPC: free backchannel req=%p\n", req); |
256 | 259 | ||
257 | smp_mb__before_clear_bit(); | 260 | smp_mb__before_clear_bit(); |
258 | BUG_ON(!test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); | 261 | WARN_ON_ONCE(!test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); |
259 | clear_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); | 262 | clear_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); |
260 | smp_mb__after_clear_bit(); | 263 | smp_mb__after_clear_bit(); |
261 | 264 | ||
diff --git a/net/sunrpc/bc_svc.c b/net/sunrpc/bc_svc.c index 0b2eb388cbd..15c7a8a1c24 100644 --- a/net/sunrpc/bc_svc.c +++ b/net/sunrpc/bc_svc.c | |||
@@ -53,7 +53,7 @@ int bc_send(struct rpc_rqst *req) | |||
53 | if (IS_ERR(task)) | 53 | if (IS_ERR(task)) |
54 | ret = PTR_ERR(task); | 54 | ret = PTR_ERR(task); |
55 | else { | 55 | else { |
56 | BUG_ON(atomic_read(&task->tk_count) != 1); | 56 | WARN_ON_ONCE(atomic_read(&task->tk_count) != 1); |
57 | ret = task->tk_status; | 57 | ret = task->tk_status; |
58 | rpc_put_task(task); | 58 | rpc_put_task(task); |
59 | } | 59 | } |
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index fc2f7aa4dca..9afa4393c21 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -775,11 +775,11 @@ static ssize_t cache_read(struct file *filp, char __user *buf, size_t count, | |||
775 | if (rp->q.list.next == &cd->queue) { | 775 | if (rp->q.list.next == &cd->queue) { |
776 | spin_unlock(&queue_lock); | 776 | spin_unlock(&queue_lock); |
777 | mutex_unlock(&inode->i_mutex); | 777 | mutex_unlock(&inode->i_mutex); |
778 | BUG_ON(rp->offset); | 778 | WARN_ON_ONCE(rp->offset); |
779 | return 0; | 779 | return 0; |
780 | } | 780 | } |
781 | rq = container_of(rp->q.list.next, struct cache_request, q.list); | 781 | rq = container_of(rp->q.list.next, struct cache_request, q.list); |
782 | BUG_ON(rq->q.reader); | 782 | WARN_ON_ONCE(rq->q.reader); |
783 | if (rp->offset == 0) | 783 | if (rp->offset == 0) |
784 | rq->readers++; | 784 | rq->readers++; |
785 | spin_unlock(&queue_lock); | 785 | spin_unlock(&queue_lock); |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index cdc7564b451..822f020fa7f 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -132,8 +132,10 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, | |||
132 | int error; | 132 | int error; |
133 | 133 | ||
134 | dir = rpc_d_lookup_sb(sb, dir_name); | 134 | dir = rpc_d_lookup_sb(sb, dir_name); |
135 | if (dir == NULL) | 135 | if (dir == NULL) { |
136 | pr_info("RPC: pipefs directory doesn't exist: %s\n", dir_name); | ||
136 | return dir; | 137 | return dir; |
138 | } | ||
137 | for (;;) { | 139 | for (;;) { |
138 | q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++); | 140 | q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++); |
139 | name[sizeof(name) - 1] = '\0'; | 141 | name[sizeof(name) - 1] = '\0'; |
@@ -192,7 +194,8 @@ static int __rpc_clnt_handle_event(struct rpc_clnt *clnt, unsigned long event, | |||
192 | case RPC_PIPEFS_MOUNT: | 194 | case RPC_PIPEFS_MOUNT: |
193 | dentry = rpc_setup_pipedir_sb(sb, clnt, | 195 | dentry = rpc_setup_pipedir_sb(sb, clnt, |
194 | clnt->cl_program->pipe_dir_name); | 196 | clnt->cl_program->pipe_dir_name); |
195 | BUG_ON(dentry == NULL); | 197 | if (!dentry) |
198 | return -ENOENT; | ||
196 | if (IS_ERR(dentry)) | 199 | if (IS_ERR(dentry)) |
197 | return PTR_ERR(dentry); | 200 | return PTR_ERR(dentry); |
198 | clnt->cl_dentry = dentry; | 201 | clnt->cl_dentry = dentry; |
@@ -234,7 +237,7 @@ static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event) | |||
234 | spin_lock(&sn->rpc_client_lock); | 237 | spin_lock(&sn->rpc_client_lock); |
235 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { | 238 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { |
236 | if (clnt->cl_program->pipe_dir_name == NULL) | 239 | if (clnt->cl_program->pipe_dir_name == NULL) |
237 | break; | 240 | continue; |
238 | if (rpc_clnt_skip_event(clnt, event)) | 241 | if (rpc_clnt_skip_event(clnt, event)) |
239 | continue; | 242 | continue; |
240 | if (atomic_inc_not_zero(&clnt->cl_count) == 0) | 243 | if (atomic_inc_not_zero(&clnt->cl_count) == 0) |
@@ -607,6 +610,13 @@ EXPORT_SYMBOL_GPL(rpc_killall_tasks); | |||
607 | */ | 610 | */ |
608 | void rpc_shutdown_client(struct rpc_clnt *clnt) | 611 | void rpc_shutdown_client(struct rpc_clnt *clnt) |
609 | { | 612 | { |
613 | /* | ||
614 | * To avoid deadlock, never call rpc_shutdown_client from a | ||
615 | * workqueue context! | ||
616 | */ | ||
617 | WARN_ON_ONCE(current->flags & PF_WQ_WORKER); | ||
618 | might_sleep(); | ||
619 | |||
610 | dprintk_rcu("RPC: shutting down %s client for %s\n", | 620 | dprintk_rcu("RPC: shutting down %s client for %s\n", |
611 | clnt->cl_protname, | 621 | clnt->cl_protname, |
612 | rcu_dereference(clnt->cl_xprt)->servername); | 622 | rcu_dereference(clnt->cl_xprt)->servername); |
@@ -693,21 +703,19 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, | |||
693 | const struct rpc_program *program, | 703 | const struct rpc_program *program, |
694 | u32 vers) | 704 | u32 vers) |
695 | { | 705 | { |
706 | struct rpc_create_args args = { | ||
707 | .program = program, | ||
708 | .prognumber = program->number, | ||
709 | .version = vers, | ||
710 | .authflavor = old->cl_auth->au_flavor, | ||
711 | .client_name = old->cl_principal, | ||
712 | }; | ||
696 | struct rpc_clnt *clnt; | 713 | struct rpc_clnt *clnt; |
697 | const struct rpc_version *version; | ||
698 | int err; | 714 | int err; |
699 | 715 | ||
700 | BUG_ON(vers >= program->nrvers || !program->version[vers]); | 716 | clnt = __rpc_clone_client(&args, old); |
701 | version = program->version[vers]; | ||
702 | clnt = rpc_clone_client(old); | ||
703 | if (IS_ERR(clnt)) | 717 | if (IS_ERR(clnt)) |
704 | goto out; | 718 | goto out; |
705 | clnt->cl_procinfo = version->procs; | ||
706 | clnt->cl_maxproc = version->nrprocs; | ||
707 | clnt->cl_protname = program->name; | ||
708 | clnt->cl_prog = program->number; | ||
709 | clnt->cl_vers = version->number; | ||
710 | clnt->cl_stats = program->stats; | ||
711 | err = rpc_ping(clnt); | 719 | err = rpc_ping(clnt); |
712 | if (err != 0) { | 720 | if (err != 0) { |
713 | rpc_shutdown_client(clnt); | 721 | rpc_shutdown_client(clnt); |
@@ -832,7 +840,12 @@ int rpc_call_sync(struct rpc_clnt *clnt, const struct rpc_message *msg, int flag | |||
832 | }; | 840 | }; |
833 | int status; | 841 | int status; |
834 | 842 | ||
835 | BUG_ON(flags & RPC_TASK_ASYNC); | 843 | WARN_ON_ONCE(flags & RPC_TASK_ASYNC); |
844 | if (flags & RPC_TASK_ASYNC) { | ||
845 | rpc_release_calldata(task_setup_data.callback_ops, | ||
846 | task_setup_data.callback_data); | ||
847 | return -EINVAL; | ||
848 | } | ||
836 | 849 | ||
837 | task = rpc_run_task(&task_setup_data); | 850 | task = rpc_run_task(&task_setup_data); |
838 | if (IS_ERR(task)) | 851 | if (IS_ERR(task)) |
@@ -908,7 +921,7 @@ struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req, | |||
908 | 921 | ||
909 | task->tk_action = call_bc_transmit; | 922 | task->tk_action = call_bc_transmit; |
910 | atomic_inc(&task->tk_count); | 923 | atomic_inc(&task->tk_count); |
911 | BUG_ON(atomic_read(&task->tk_count) != 2); | 924 | WARN_ON_ONCE(atomic_read(&task->tk_count) != 2); |
912 | rpc_execute(task); | 925 | rpc_execute(task); |
913 | 926 | ||
914 | out: | 927 | out: |
@@ -1368,6 +1381,7 @@ call_refreshresult(struct rpc_task *task) | |||
1368 | return; | 1381 | return; |
1369 | case -ETIMEDOUT: | 1382 | case -ETIMEDOUT: |
1370 | rpc_delay(task, 3*HZ); | 1383 | rpc_delay(task, 3*HZ); |
1384 | case -EKEYEXPIRED: | ||
1371 | case -EAGAIN: | 1385 | case -EAGAIN: |
1372 | status = -EACCES; | 1386 | status = -EACCES; |
1373 | if (!task->tk_cred_retry) | 1387 | if (!task->tk_cred_retry) |
@@ -1654,7 +1668,6 @@ call_transmit(struct rpc_task *task) | |||
1654 | task->tk_action = call_transmit_status; | 1668 | task->tk_action = call_transmit_status; |
1655 | /* Encode here so that rpcsec_gss can use correct sequence number. */ | 1669 | /* Encode here so that rpcsec_gss can use correct sequence number. */ |
1656 | if (rpc_task_need_encode(task)) { | 1670 | if (rpc_task_need_encode(task)) { |
1657 | BUG_ON(task->tk_rqstp->rq_bytes_sent != 0); | ||
1658 | rpc_xdr_encode(task); | 1671 | rpc_xdr_encode(task); |
1659 | /* Did the encode result in an error condition? */ | 1672 | /* Did the encode result in an error condition? */ |
1660 | if (task->tk_status != 0) { | 1673 | if (task->tk_status != 0) { |
@@ -1738,7 +1751,6 @@ call_bc_transmit(struct rpc_task *task) | |||
1738 | { | 1751 | { |
1739 | struct rpc_rqst *req = task->tk_rqstp; | 1752 | struct rpc_rqst *req = task->tk_rqstp; |
1740 | 1753 | ||
1741 | BUG_ON(task->tk_status != 0); | ||
1742 | task->tk_status = xprt_prepare_transmit(task); | 1754 | task->tk_status = xprt_prepare_transmit(task); |
1743 | if (task->tk_status == -EAGAIN) { | 1755 | if (task->tk_status == -EAGAIN) { |
1744 | /* | 1756 | /* |
@@ -1785,7 +1797,7 @@ call_bc_transmit(struct rpc_task *task) | |||
1785 | * We were unable to reply and will have to drop the | 1797 | * We were unable to reply and will have to drop the |
1786 | * request. The server should reconnect and retransmit. | 1798 | * request. The server should reconnect and retransmit. |
1787 | */ | 1799 | */ |
1788 | BUG_ON(task->tk_status == -EAGAIN); | 1800 | WARN_ON_ONCE(task->tk_status == -EAGAIN); |
1789 | printk(KERN_NOTICE "RPC: Could not send backchannel reply " | 1801 | printk(KERN_NOTICE "RPC: Could not send backchannel reply " |
1790 | "error: %d\n", task->tk_status); | 1802 | "error: %d\n", task->tk_status); |
1791 | break; | 1803 | break; |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 80f5dd23417..fd10981ea79 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -1093,7 +1093,7 @@ void rpc_put_sb_net(const struct net *net) | |||
1093 | { | 1093 | { |
1094 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 1094 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
1095 | 1095 | ||
1096 | BUG_ON(sn->pipefs_sb == NULL); | 1096 | WARN_ON(sn->pipefs_sb == NULL); |
1097 | mutex_unlock(&sn->pipefs_sb_lock); | 1097 | mutex_unlock(&sn->pipefs_sb_lock); |
1098 | } | 1098 | } |
1099 | EXPORT_SYMBOL_GPL(rpc_put_sb_net); | 1099 | EXPORT_SYMBOL_GPL(rpc_put_sb_net); |
@@ -1152,14 +1152,19 @@ static void rpc_kill_sb(struct super_block *sb) | |||
1152 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 1152 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
1153 | 1153 | ||
1154 | mutex_lock(&sn->pipefs_sb_lock); | 1154 | mutex_lock(&sn->pipefs_sb_lock); |
1155 | if (sn->pipefs_sb != sb) { | ||
1156 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1157 | goto out; | ||
1158 | } | ||
1155 | sn->pipefs_sb = NULL; | 1159 | sn->pipefs_sb = NULL; |
1156 | mutex_unlock(&sn->pipefs_sb_lock); | 1160 | mutex_unlock(&sn->pipefs_sb_lock); |
1157 | put_net(net); | ||
1158 | dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", | 1161 | dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", |
1159 | net, NET_NAME(net)); | 1162 | net, NET_NAME(net)); |
1160 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | 1163 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, |
1161 | RPC_PIPEFS_UMOUNT, | 1164 | RPC_PIPEFS_UMOUNT, |
1162 | sb); | 1165 | sb); |
1166 | put_net(net); | ||
1167 | out: | ||
1163 | kill_litter_super(sb); | 1168 | kill_litter_super(sb); |
1164 | } | 1169 | } |
1165 | 1170 | ||
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index a70acae496e..411f332de0b 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
@@ -884,7 +884,10 @@ static void encode_rpcb_string(struct xdr_stream *xdr, const char *string, | |||
884 | u32 len; | 884 | u32 len; |
885 | 885 | ||
886 | len = strlen(string); | 886 | len = strlen(string); |
887 | BUG_ON(len > maxstrlen); | 887 | WARN_ON_ONCE(len > maxstrlen); |
888 | if (len > maxstrlen) | ||
889 | /* truncate and hope for the best */ | ||
890 | len = maxstrlen; | ||
888 | p = xdr_reserve_space(xdr, 4 + len); | 891 | p = xdr_reserve_space(xdr, 4 + len); |
889 | xdr_encode_opaque(p, string, len); | 892 | xdr_encode_opaque(p, string, len); |
890 | } | 893 | } |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 6357fcb00c7..d17a704aaf5 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -98,6 +98,23 @@ __rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task) | |||
98 | list_add(&task->u.tk_wait.timer_list, &queue->timer_list.list); | 98 | list_add(&task->u.tk_wait.timer_list, &queue->timer_list.list); |
99 | } | 99 | } |
100 | 100 | ||
101 | static void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int priority) | ||
102 | { | ||
103 | queue->priority = priority; | ||
104 | } | ||
105 | |||
106 | static void rpc_set_waitqueue_owner(struct rpc_wait_queue *queue, pid_t pid) | ||
107 | { | ||
108 | queue->owner = pid; | ||
109 | queue->nr = RPC_BATCH_COUNT; | ||
110 | } | ||
111 | |||
112 | static void rpc_reset_waitqueue_priority(struct rpc_wait_queue *queue) | ||
113 | { | ||
114 | rpc_set_waitqueue_priority(queue, queue->maxpriority); | ||
115 | rpc_set_waitqueue_owner(queue, 0); | ||
116 | } | ||
117 | |||
101 | /* | 118 | /* |
102 | * Add new request to a priority queue. | 119 | * Add new request to a priority queue. |
103 | */ | 120 | */ |
@@ -109,9 +126,11 @@ static void __rpc_add_wait_queue_priority(struct rpc_wait_queue *queue, | |||
109 | struct rpc_task *t; | 126 | struct rpc_task *t; |
110 | 127 | ||
111 | INIT_LIST_HEAD(&task->u.tk_wait.links); | 128 | INIT_LIST_HEAD(&task->u.tk_wait.links); |
112 | q = &queue->tasks[queue_priority]; | ||
113 | if (unlikely(queue_priority > queue->maxpriority)) | 129 | if (unlikely(queue_priority > queue->maxpriority)) |
114 | q = &queue->tasks[queue->maxpriority]; | 130 | queue_priority = queue->maxpriority; |
131 | if (queue_priority > queue->priority) | ||
132 | rpc_set_waitqueue_priority(queue, queue_priority); | ||
133 | q = &queue->tasks[queue_priority]; | ||
115 | list_for_each_entry(t, q, u.tk_wait.list) { | 134 | list_for_each_entry(t, q, u.tk_wait.list) { |
116 | if (t->tk_owner == task->tk_owner) { | 135 | if (t->tk_owner == task->tk_owner) { |
117 | list_add_tail(&task->u.tk_wait.list, &t->u.tk_wait.links); | 136 | list_add_tail(&task->u.tk_wait.list, &t->u.tk_wait.links); |
@@ -133,7 +152,9 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue, | |||
133 | struct rpc_task *task, | 152 | struct rpc_task *task, |
134 | unsigned char queue_priority) | 153 | unsigned char queue_priority) |
135 | { | 154 | { |
136 | BUG_ON (RPC_IS_QUEUED(task)); | 155 | WARN_ON_ONCE(RPC_IS_QUEUED(task)); |
156 | if (RPC_IS_QUEUED(task)) | ||
157 | return; | ||
137 | 158 | ||
138 | if (RPC_IS_PRIORITY(queue)) | 159 | if (RPC_IS_PRIORITY(queue)) |
139 | __rpc_add_wait_queue_priority(queue, task, queue_priority); | 160 | __rpc_add_wait_queue_priority(queue, task, queue_priority); |
@@ -178,24 +199,6 @@ static void __rpc_remove_wait_queue(struct rpc_wait_queue *queue, struct rpc_tas | |||
178 | task->tk_pid, queue, rpc_qname(queue)); | 199 | task->tk_pid, queue, rpc_qname(queue)); |
179 | } | 200 | } |
180 | 201 | ||
181 | static inline void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int priority) | ||
182 | { | ||
183 | queue->priority = priority; | ||
184 | queue->count = 1 << (priority * 2); | ||
185 | } | ||
186 | |||
187 | static inline void rpc_set_waitqueue_owner(struct rpc_wait_queue *queue, pid_t pid) | ||
188 | { | ||
189 | queue->owner = pid; | ||
190 | queue->nr = RPC_BATCH_COUNT; | ||
191 | } | ||
192 | |||
193 | static inline void rpc_reset_waitqueue_priority(struct rpc_wait_queue *queue) | ||
194 | { | ||
195 | rpc_set_waitqueue_priority(queue, queue->maxpriority); | ||
196 | rpc_set_waitqueue_owner(queue, 0); | ||
197 | } | ||
198 | |||
199 | static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname, unsigned char nr_queues) | 202 | static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname, unsigned char nr_queues) |
200 | { | 203 | { |
201 | int i; | 204 | int i; |
@@ -334,7 +337,7 @@ static void __rpc_sleep_on_priority(struct rpc_wait_queue *q, | |||
334 | 337 | ||
335 | __rpc_add_wait_queue(q, task, queue_priority); | 338 | __rpc_add_wait_queue(q, task, queue_priority); |
336 | 339 | ||
337 | BUG_ON(task->tk_callback != NULL); | 340 | WARN_ON_ONCE(task->tk_callback != NULL); |
338 | task->tk_callback = action; | 341 | task->tk_callback = action; |
339 | __rpc_add_timer(q, task); | 342 | __rpc_add_timer(q, task); |
340 | } | 343 | } |
@@ -343,7 +346,12 @@ void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, | |||
343 | rpc_action action) | 346 | rpc_action action) |
344 | { | 347 | { |
345 | /* We shouldn't ever put an inactive task to sleep */ | 348 | /* We shouldn't ever put an inactive task to sleep */ |
346 | BUG_ON(!RPC_IS_ACTIVATED(task)); | 349 | WARN_ON_ONCE(!RPC_IS_ACTIVATED(task)); |
350 | if (!RPC_IS_ACTIVATED(task)) { | ||
351 | task->tk_status = -EIO; | ||
352 | rpc_put_task_async(task); | ||
353 | return; | ||
354 | } | ||
347 | 355 | ||
348 | /* | 356 | /* |
349 | * Protect the queue operations. | 357 | * Protect the queue operations. |
@@ -358,7 +366,12 @@ void rpc_sleep_on_priority(struct rpc_wait_queue *q, struct rpc_task *task, | |||
358 | rpc_action action, int priority) | 366 | rpc_action action, int priority) |
359 | { | 367 | { |
360 | /* We shouldn't ever put an inactive task to sleep */ | 368 | /* We shouldn't ever put an inactive task to sleep */ |
361 | BUG_ON(!RPC_IS_ACTIVATED(task)); | 369 | WARN_ON_ONCE(!RPC_IS_ACTIVATED(task)); |
370 | if (!RPC_IS_ACTIVATED(task)) { | ||
371 | task->tk_status = -EIO; | ||
372 | rpc_put_task_async(task); | ||
373 | return; | ||
374 | } | ||
362 | 375 | ||
363 | /* | 376 | /* |
364 | * Protect the queue operations. | 377 | * Protect the queue operations. |
@@ -367,6 +380,7 @@ void rpc_sleep_on_priority(struct rpc_wait_queue *q, struct rpc_task *task, | |||
367 | __rpc_sleep_on_priority(q, task, action, priority - RPC_PRIORITY_LOW); | 380 | __rpc_sleep_on_priority(q, task, action, priority - RPC_PRIORITY_LOW); |
368 | spin_unlock_bh(&q->lock); | 381 | spin_unlock_bh(&q->lock); |
369 | } | 382 | } |
383 | EXPORT_SYMBOL_GPL(rpc_sleep_on_priority); | ||
370 | 384 | ||
371 | /** | 385 | /** |
372 | * __rpc_do_wake_up_task - wake up a single rpc_task | 386 | * __rpc_do_wake_up_task - wake up a single rpc_task |
@@ -451,8 +465,7 @@ static struct rpc_task *__rpc_find_next_queued_priority(struct rpc_wait_queue *q | |||
451 | /* | 465 | /* |
452 | * Check if we need to switch queues. | 466 | * Check if we need to switch queues. |
453 | */ | 467 | */ |
454 | if (--queue->count) | 468 | goto new_owner; |
455 | goto new_owner; | ||
456 | } | 469 | } |
457 | 470 | ||
458 | /* | 471 | /* |
@@ -697,7 +710,9 @@ static void __rpc_execute(struct rpc_task *task) | |||
697 | dprintk("RPC: %5u __rpc_execute flags=0x%x\n", | 710 | dprintk("RPC: %5u __rpc_execute flags=0x%x\n", |
698 | task->tk_pid, task->tk_flags); | 711 | task->tk_pid, task->tk_flags); |
699 | 712 | ||
700 | BUG_ON(RPC_IS_QUEUED(task)); | 713 | WARN_ON_ONCE(RPC_IS_QUEUED(task)); |
714 | if (RPC_IS_QUEUED(task)) | ||
715 | return; | ||
701 | 716 | ||
702 | for (;;) { | 717 | for (;;) { |
703 | void (*do_action)(struct rpc_task *); | 718 | void (*do_action)(struct rpc_task *); |
@@ -981,7 +996,7 @@ static void rpc_release_task(struct rpc_task *task) | |||
981 | { | 996 | { |
982 | dprintk("RPC: %5u release task\n", task->tk_pid); | 997 | dprintk("RPC: %5u release task\n", task->tk_pid); |
983 | 998 | ||
984 | BUG_ON (RPC_IS_QUEUED(task)); | 999 | WARN_ON_ONCE(RPC_IS_QUEUED(task)); |
985 | 1000 | ||
986 | rpc_release_resources_task(task); | 1001 | rpc_release_resources_task(task); |
987 | 1002 | ||
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 3ee7461926d..dfa4ba69ff4 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -324,7 +324,9 @@ svc_pool_map_set_cpumask(struct task_struct *task, unsigned int pidx) | |||
324 | * The caller checks for sv_nrpools > 1, which | 324 | * The caller checks for sv_nrpools > 1, which |
325 | * implies that we've been initialized. | 325 | * implies that we've been initialized. |
326 | */ | 326 | */ |
327 | BUG_ON(m->count == 0); | 327 | WARN_ON_ONCE(m->count == 0); |
328 | if (m->count == 0) | ||
329 | return; | ||
328 | 330 | ||
329 | switch (m->mode) { | 331 | switch (m->mode) { |
330 | case SVC_POOL_PERCPU: | 332 | case SVC_POOL_PERCPU: |
@@ -585,7 +587,9 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size, int node) | |||
585 | * We assume one is at most one page | 587 | * We assume one is at most one page |
586 | */ | 588 | */ |
587 | arghi = 0; | 589 | arghi = 0; |
588 | BUG_ON(pages > RPCSVC_MAXPAGES); | 590 | WARN_ON_ONCE(pages > RPCSVC_MAXPAGES); |
591 | if (pages > RPCSVC_MAXPAGES) | ||
592 | pages = RPCSVC_MAXPAGES; | ||
589 | while (pages) { | 593 | while (pages) { |
590 | struct page *p = alloc_pages_node(node, GFP_KERNEL, 0); | 594 | struct page *p = alloc_pages_node(node, GFP_KERNEL, 0); |
591 | if (!p) | 595 | if (!p) |
@@ -946,7 +950,9 @@ int svc_register(const struct svc_serv *serv, struct net *net, | |||
946 | unsigned int i; | 950 | unsigned int i; |
947 | int error = 0; | 951 | int error = 0; |
948 | 952 | ||
949 | BUG_ON(proto == 0 && port == 0); | 953 | WARN_ON_ONCE(proto == 0 && port == 0); |
954 | if (proto == 0 && port == 0) | ||
955 | return -EINVAL; | ||
950 | 956 | ||
951 | for (progp = serv->sv_program; progp; progp = progp->pg_next) { | 957 | for (progp = serv->sv_program; progp; progp = progp->pg_next) { |
952 | for (i = 0; i < progp->pg_nvers; i++) { | 958 | for (i = 0; i < progp->pg_nvers; i++) { |
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 194d865fae7..b8e47fac731 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -218,7 +218,9 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, | |||
218 | */ | 218 | */ |
219 | static void svc_xprt_received(struct svc_xprt *xprt) | 219 | static void svc_xprt_received(struct svc_xprt *xprt) |
220 | { | 220 | { |
221 | BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags)); | 221 | WARN_ON_ONCE(!test_bit(XPT_BUSY, &xprt->xpt_flags)); |
222 | if (!test_bit(XPT_BUSY, &xprt->xpt_flags)) | ||
223 | return; | ||
222 | /* As soon as we clear busy, the xprt could be closed and | 224 | /* As soon as we clear busy, the xprt could be closed and |
223 | * 'put', so we need a reference to call svc_xprt_enqueue with: | 225 | * 'put', so we need a reference to call svc_xprt_enqueue with: |
224 | */ | 226 | */ |
@@ -577,7 +579,10 @@ int svc_alloc_arg(struct svc_rqst *rqstp) | |||
577 | 579 | ||
578 | /* now allocate needed pages. If we get a failure, sleep briefly */ | 580 | /* now allocate needed pages. If we get a failure, sleep briefly */ |
579 | pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE; | 581 | pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE; |
580 | BUG_ON(pages >= RPCSVC_MAXPAGES); | 582 | WARN_ON_ONCE(pages >= RPCSVC_MAXPAGES); |
583 | if (pages >= RPCSVC_MAXPAGES) | ||
584 | /* use as many pages as possible */ | ||
585 | pages = RPCSVC_MAXPAGES - 1; | ||
581 | for (i = 0; i < pages ; i++) | 586 | for (i = 0; i < pages ; i++) |
582 | while (rqstp->rq_pages[i] == NULL) { | 587 | while (rqstp->rq_pages[i] == NULL) { |
583 | struct page *p = alloc_page(GFP_KERNEL); | 588 | struct page *p = alloc_page(GFP_KERNEL); |
@@ -926,7 +931,7 @@ static void svc_delete_xprt(struct svc_xprt *xprt) | |||
926 | spin_lock_bh(&serv->sv_lock); | 931 | spin_lock_bh(&serv->sv_lock); |
927 | if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags)) | 932 | if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags)) |
928 | list_del_init(&xprt->xpt_list); | 933 | list_del_init(&xprt->xpt_list); |
929 | BUG_ON(!list_empty(&xprt->xpt_ready)); | 934 | WARN_ON_ONCE(!list_empty(&xprt->xpt_ready)); |
930 | if (test_bit(XPT_TEMP, &xprt->xpt_flags)) | 935 | if (test_bit(XPT_TEMP, &xprt->xpt_flags)) |
931 | serv->sv_tmpcnt--; | 936 | serv->sv_tmpcnt--; |
932 | spin_unlock_bh(&serv->sv_lock); | 937 | spin_unlock_bh(&serv->sv_lock); |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 03827cef1fa..cc3020d1678 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -84,7 +84,11 @@ static struct lock_class_key svc_slock_key[2]; | |||
84 | static void svc_reclassify_socket(struct socket *sock) | 84 | static void svc_reclassify_socket(struct socket *sock) |
85 | { | 85 | { |
86 | struct sock *sk = sock->sk; | 86 | struct sock *sk = sock->sk; |
87 | BUG_ON(sock_owned_by_user(sk)); | 87 | |
88 | WARN_ON_ONCE(sock_owned_by_user(sk)); | ||
89 | if (sock_owned_by_user(sk)) | ||
90 | return; | ||
91 | |||
88 | switch (sk->sk_family) { | 92 | switch (sk->sk_family) { |
89 | case AF_INET: | 93 | case AF_INET: |
90 | sock_lock_init_class_and_name(sk, "slock-AF_INET-NFSD", | 94 | sock_lock_init_class_and_name(sk, "slock-AF_INET-NFSD", |
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 08f50afd5f2..56055632f15 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
@@ -318,7 +318,10 @@ xdr_shrink_bufhead(struct xdr_buf *buf, size_t len) | |||
318 | 318 | ||
319 | tail = buf->tail; | 319 | tail = buf->tail; |
320 | head = buf->head; | 320 | head = buf->head; |
321 | BUG_ON (len > head->iov_len); | 321 | |
322 | WARN_ON_ONCE(len > head->iov_len); | ||
323 | if (len > head->iov_len) | ||
324 | len = head->iov_len; | ||
322 | 325 | ||
323 | /* Shift the tail first */ | 326 | /* Shift the tail first */ |
324 | if (tail->iov_len != 0) { | 327 | if (tail->iov_len != 0) { |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 75853cabf4c..68b0a81c31d 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -1746,7 +1746,6 @@ static inline void xs_reclassify_socketu(struct socket *sock) | |||
1746 | { | 1746 | { |
1747 | struct sock *sk = sock->sk; | 1747 | struct sock *sk = sock->sk; |
1748 | 1748 | ||
1749 | BUG_ON(sock_owned_by_user(sk)); | ||
1750 | sock_lock_init_class_and_name(sk, "slock-AF_LOCAL-RPC", | 1749 | sock_lock_init_class_and_name(sk, "slock-AF_LOCAL-RPC", |
1751 | &xs_slock_key[1], "sk_lock-AF_LOCAL-RPC", &xs_key[1]); | 1750 | &xs_slock_key[1], "sk_lock-AF_LOCAL-RPC", &xs_key[1]); |
1752 | } | 1751 | } |
@@ -1755,7 +1754,6 @@ static inline void xs_reclassify_socket4(struct socket *sock) | |||
1755 | { | 1754 | { |
1756 | struct sock *sk = sock->sk; | 1755 | struct sock *sk = sock->sk; |
1757 | 1756 | ||
1758 | BUG_ON(sock_owned_by_user(sk)); | ||
1759 | sock_lock_init_class_and_name(sk, "slock-AF_INET-RPC", | 1757 | sock_lock_init_class_and_name(sk, "slock-AF_INET-RPC", |
1760 | &xs_slock_key[0], "sk_lock-AF_INET-RPC", &xs_key[0]); | 1758 | &xs_slock_key[0], "sk_lock-AF_INET-RPC", &xs_key[0]); |
1761 | } | 1759 | } |
@@ -1764,13 +1762,16 @@ static inline void xs_reclassify_socket6(struct socket *sock) | |||
1764 | { | 1762 | { |
1765 | struct sock *sk = sock->sk; | 1763 | struct sock *sk = sock->sk; |
1766 | 1764 | ||
1767 | BUG_ON(sock_owned_by_user(sk)); | ||
1768 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-RPC", | 1765 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-RPC", |
1769 | &xs_slock_key[1], "sk_lock-AF_INET6-RPC", &xs_key[1]); | 1766 | &xs_slock_key[1], "sk_lock-AF_INET6-RPC", &xs_key[1]); |
1770 | } | 1767 | } |
1771 | 1768 | ||
1772 | static inline void xs_reclassify_socket(int family, struct socket *sock) | 1769 | static inline void xs_reclassify_socket(int family, struct socket *sock) |
1773 | { | 1770 | { |
1771 | WARN_ON_ONCE(sock_owned_by_user(sock->sk)); | ||
1772 | if (sock_owned_by_user(sock->sk)) | ||
1773 | return; | ||
1774 | |||
1774 | switch (family) { | 1775 | switch (family) { |
1775 | case AF_LOCAL: | 1776 | case AF_LOCAL: |
1776 | xs_reclassify_socketu(sock); | 1777 | xs_reclassify_socketu(sock); |
@@ -1901,6 +1902,10 @@ static void xs_local_setup_socket(struct work_struct *work) | |||
1901 | dprintk("RPC: xprt %p: socket %s does not exist\n", | 1902 | dprintk("RPC: xprt %p: socket %s does not exist\n", |
1902 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); | 1903 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); |
1903 | break; | 1904 | break; |
1905 | case -ECONNREFUSED: | ||
1906 | dprintk("RPC: xprt %p: connection refused for %s\n", | ||
1907 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
1908 | break; | ||
1904 | default: | 1909 | default: |
1905 | printk(KERN_ERR "%s: unhandled error (%d) connecting to %s\n", | 1910 | printk(KERN_ERR "%s: unhandled error (%d) connecting to %s\n", |
1906 | __func__, -status, | 1911 | __func__, -status, |
@@ -2329,9 +2334,11 @@ static void *bc_malloc(struct rpc_task *task, size_t size) | |||
2329 | struct page *page; | 2334 | struct page *page; |
2330 | struct rpc_buffer *buf; | 2335 | struct rpc_buffer *buf; |
2331 | 2336 | ||
2332 | BUG_ON(size > PAGE_SIZE - sizeof(struct rpc_buffer)); | 2337 | WARN_ON_ONCE(size > PAGE_SIZE - sizeof(struct rpc_buffer)); |
2333 | page = alloc_page(GFP_KERNEL); | 2338 | if (size > PAGE_SIZE - sizeof(struct rpc_buffer)) |
2339 | return NULL; | ||
2334 | 2340 | ||
2341 | page = alloc_page(GFP_KERNEL); | ||
2335 | if (!page) | 2342 | if (!page) |
2336 | return NULL; | 2343 | return NULL; |
2337 | 2344 | ||
@@ -2393,7 +2400,6 @@ static int bc_send_request(struct rpc_task *task) | |||
2393 | { | 2400 | { |
2394 | struct rpc_rqst *req = task->tk_rqstp; | 2401 | struct rpc_rqst *req = task->tk_rqstp; |
2395 | struct svc_xprt *xprt; | 2402 | struct svc_xprt *xprt; |
2396 | struct svc_sock *svsk; | ||
2397 | u32 len; | 2403 | u32 len; |
2398 | 2404 | ||
2399 | dprintk("sending request with xid: %08x\n", ntohl(req->rq_xid)); | 2405 | dprintk("sending request with xid: %08x\n", ntohl(req->rq_xid)); |
@@ -2401,7 +2407,6 @@ static int bc_send_request(struct rpc_task *task) | |||
2401 | * Get the server socket associated with this callback xprt | 2407 | * Get the server socket associated with this callback xprt |
2402 | */ | 2408 | */ |
2403 | xprt = req->rq_xprt->bc_xprt; | 2409 | xprt = req->rq_xprt->bc_xprt; |
2404 | svsk = container_of(xprt, struct svc_sock, sk_xprt); | ||
2405 | 2410 | ||
2406 | /* | 2411 | /* |
2407 | * Grab the mutex to serialize data as the connection is shared | 2412 | * Grab the mutex to serialize data as the connection is shared |