aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/dir.c214
-rw-r--r--fs/ext4/ext4.h6
-rw-r--r--fs/ext4/hash.c4
-rw-r--r--fs/lockd/svc.c2
-rw-r--r--fs/nfsd/current_stateid.h28
-rw-r--r--fs/nfsd/export.c2
-rw-r--r--fs/nfsd/netns.h34
-rw-r--r--fs/nfsd/nfs4callback.c19
-rw-r--r--fs/nfsd/nfs4idmap.c53
-rw-r--r--fs/nfsd/nfs4proc.c118
-rw-r--r--fs/nfsd/nfs4recover.c647
-rw-r--r--fs/nfsd/nfs4state.c365
-rw-r--r--fs/nfsd/nfs4xdr.c132
-rw-r--r--fs/nfsd/nfsctl.c22
-rw-r--r--fs/nfsd/nfsd.h7
-rw-r--r--fs/nfsd/nfssvc.c44
-rw-r--r--fs/nfsd/state.h47
-rw-r--r--fs/nfsd/vfs.c33
-rw-r--r--fs/nfsd/vfs.h2
-rw-r--r--fs/nfsd/xdr4.h34
20 files changed, 1488 insertions, 325 deletions
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index ad56866d729a..b86786202643 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -32,24 +32,8 @@ static unsigned char ext4_filetype_table[] = {
32 DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK 32 DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
33}; 33};
34 34
35static int ext4_readdir(struct file *, void *, filldir_t);
36static int ext4_dx_readdir(struct file *filp, 35static int ext4_dx_readdir(struct file *filp,
37 void *dirent, filldir_t filldir); 36 void *dirent, filldir_t filldir);
38static int ext4_release_dir(struct inode *inode,
39 struct file *filp);
40
41const struct file_operations ext4_dir_operations = {
42 .llseek = ext4_llseek,
43 .read = generic_read_dir,
44 .readdir = ext4_readdir, /* we take BKL. needed?*/
45 .unlocked_ioctl = ext4_ioctl,
46#ifdef CONFIG_COMPAT
47 .compat_ioctl = ext4_compat_ioctl,
48#endif
49 .fsync = ext4_sync_file,
50 .release = ext4_release_dir,
51};
52
53 37
54static unsigned char get_dtype(struct super_block *sb, int filetype) 38static unsigned char get_dtype(struct super_block *sb, int filetype)
55{ 39{
@@ -60,6 +44,26 @@ static unsigned char get_dtype(struct super_block *sb, int filetype)
60 return (ext4_filetype_table[filetype]); 44 return (ext4_filetype_table[filetype]);
61} 45}
62 46
47/**
48 * Check if the given dir-inode refers to an htree-indexed directory
49 * (or a directory which chould potentially get coverted to use htree
50 * indexing).
51 *
52 * Return 1 if it is a dx dir, 0 if not
53 */
54static int is_dx_dir(struct inode *inode)
55{
56 struct super_block *sb = inode->i_sb;
57
58 if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
59 EXT4_FEATURE_COMPAT_DIR_INDEX) &&
60 ((ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) ||
61 ((inode->i_size >> sb->s_blocksize_bits) == 1)))
62 return 1;
63
64 return 0;
65}
66
63/* 67/*
64 * Return 0 if the directory entry is OK, and 1 if there is a problem 68 * Return 0 if the directory entry is OK, and 1 if there is a problem
65 * 69 *
@@ -115,18 +119,13 @@ static int ext4_readdir(struct file *filp,
115 unsigned int offset; 119 unsigned int offset;
116 int i, stored; 120 int i, stored;
117 struct ext4_dir_entry_2 *de; 121 struct ext4_dir_entry_2 *de;
118 struct super_block *sb;
119 int err; 122 int err;
120 struct inode *inode = filp->f_path.dentry->d_inode; 123 struct inode *inode = filp->f_path.dentry->d_inode;
124 struct super_block *sb = inode->i_sb;
121 int ret = 0; 125 int ret = 0;
122 int dir_has_error = 0; 126 int dir_has_error = 0;
123 127
124 sb = inode->i_sb; 128 if (is_dx_dir(inode)) {
125
126 if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
127 EXT4_FEATURE_COMPAT_DIR_INDEX) &&
128 ((ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) ||
129 ((inode->i_size >> sb->s_blocksize_bits) == 1))) {
130 err = ext4_dx_readdir(filp, dirent, filldir); 129 err = ext4_dx_readdir(filp, dirent, filldir);
131 if (err != ERR_BAD_DX_DIR) { 130 if (err != ERR_BAD_DX_DIR) {
132 ret = err; 131 ret = err;
@@ -254,22 +253,134 @@ out:
254 return ret; 253 return ret;
255} 254}
256 255
256static inline int is_32bit_api(void)
257{
258#ifdef CONFIG_COMPAT
259 return is_compat_task();
260#else
261 return (BITS_PER_LONG == 32);
262#endif
263}
264
257/* 265/*
258 * These functions convert from the major/minor hash to an f_pos 266 * These functions convert from the major/minor hash to an f_pos
259 * value. 267 * value for dx directories
268 *
269 * Upper layer (for example NFS) should specify FMODE_32BITHASH or
270 * FMODE_64BITHASH explicitly. On the other hand, we allow ext4 to be mounted
271 * directly on both 32-bit and 64-bit nodes, under such case, neither
272 * FMODE_32BITHASH nor FMODE_64BITHASH is specified.
273 */
274static inline loff_t hash2pos(struct file *filp, __u32 major, __u32 minor)
275{
276 if ((filp->f_mode & FMODE_32BITHASH) ||
277 (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
278 return major >> 1;
279 else
280 return ((__u64)(major >> 1) << 32) | (__u64)minor;
281}
282
283static inline __u32 pos2maj_hash(struct file *filp, loff_t pos)
284{
285 if ((filp->f_mode & FMODE_32BITHASH) ||
286 (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
287 return (pos << 1) & 0xffffffff;
288 else
289 return ((pos >> 32) << 1) & 0xffffffff;
290}
291
292static inline __u32 pos2min_hash(struct file *filp, loff_t pos)
293{
294 if ((filp->f_mode & FMODE_32BITHASH) ||
295 (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
296 return 0;
297 else
298 return pos & 0xffffffff;
299}
300
301/*
302 * Return 32- or 64-bit end-of-file for dx directories
303 */
304static inline loff_t ext4_get_htree_eof(struct file *filp)
305{
306 if ((filp->f_mode & FMODE_32BITHASH) ||
307 (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
308 return EXT4_HTREE_EOF_32BIT;
309 else
310 return EXT4_HTREE_EOF_64BIT;
311}
312
313
314/*
315 * ext4_dir_llseek() based on generic_file_llseek() to handle both
316 * non-htree and htree directories, where the "offset" is in terms
317 * of the filename hash value instead of the byte offset.
260 * 318 *
261 * Currently we only use major hash numer. This is unfortunate, but 319 * NOTE: offsets obtained *before* ext4_set_inode_flag(dir, EXT4_INODE_INDEX)
262 * on 32-bit machines, the same VFS interface is used for lseek and 320 * will be invalid once the directory was converted into a dx directory
263 * llseek, so if we use the 64 bit offset, then the 32-bit versions of
264 * lseek/telldir/seekdir will blow out spectacularly, and from within
265 * the ext2 low-level routine, we don't know if we're being called by
266 * a 64-bit version of the system call or the 32-bit version of the
267 * system call. Worse yet, NFSv2 only allows for a 32-bit readdir
268 * cookie. Sigh.
269 */ 321 */
270#define hash2pos(major, minor) (major >> 1) 322loff_t ext4_dir_llseek(struct file *file, loff_t offset, int origin)
271#define pos2maj_hash(pos) ((pos << 1) & 0xffffffff) 323{
272#define pos2min_hash(pos) (0) 324 struct inode *inode = file->f_mapping->host;
325 loff_t ret = -EINVAL;
326 int dx_dir = is_dx_dir(inode);
327
328 mutex_lock(&inode->i_mutex);
329
330 /* NOTE: relative offsets with dx directories might not work
331 * as expected, as it is difficult to figure out the
332 * correct offset between dx hashes */
333
334 switch (origin) {
335 case SEEK_END:
336 if (unlikely(offset > 0))
337 goto out_err; /* not supported for directories */
338
339 /* so only negative offsets are left, does that have a
340 * meaning for directories at all? */
341 if (dx_dir)
342 offset += ext4_get_htree_eof(file);
343 else
344 offset += inode->i_size;
345 break;
346 case SEEK_CUR:
347 /*
348 * Here we special-case the lseek(fd, 0, SEEK_CUR)
349 * position-querying operation. Avoid rewriting the "same"
350 * f_pos value back to the file because a concurrent read(),
351 * write() or lseek() might have altered it
352 */
353 if (offset == 0) {
354 offset = file->f_pos;
355 goto out_ok;
356 }
357
358 offset += file->f_pos;
359 break;
360 }
361
362 if (unlikely(offset < 0))
363 goto out_err;
364
365 if (!dx_dir) {
366 if (offset > inode->i_sb->s_maxbytes)
367 goto out_err;
368 } else if (offset > ext4_get_htree_eof(file))
369 goto out_err;
370
371 /* Special lock needed here? */
372 if (offset != file->f_pos) {
373 file->f_pos = offset;
374 file->f_version = 0;
375 }
376
377out_ok:
378 ret = offset;
379out_err:
380 mutex_unlock(&inode->i_mutex);
381
382 return ret;
383}
273 384
274/* 385/*
275 * This structure holds the nodes of the red-black tree used to store 386 * This structure holds the nodes of the red-black tree used to store
@@ -330,15 +441,16 @@ static void free_rb_tree_fname(struct rb_root *root)
330} 441}
331 442
332 443
333static struct dir_private_info *ext4_htree_create_dir_info(loff_t pos) 444static struct dir_private_info *ext4_htree_create_dir_info(struct file *filp,
445 loff_t pos)
334{ 446{
335 struct dir_private_info *p; 447 struct dir_private_info *p;
336 448
337 p = kzalloc(sizeof(struct dir_private_info), GFP_KERNEL); 449 p = kzalloc(sizeof(struct dir_private_info), GFP_KERNEL);
338 if (!p) 450 if (!p)
339 return NULL; 451 return NULL;
340 p->curr_hash = pos2maj_hash(pos); 452 p->curr_hash = pos2maj_hash(filp, pos);
341 p->curr_minor_hash = pos2min_hash(pos); 453 p->curr_minor_hash = pos2min_hash(filp, pos);
342 return p; 454 return p;
343} 455}
344 456
@@ -430,7 +542,7 @@ static int call_filldir(struct file *filp, void *dirent,
430 inode->i_ino, current->comm); 542 inode->i_ino, current->comm);
431 return 0; 543 return 0;
432 } 544 }
433 curr_pos = hash2pos(fname->hash, fname->minor_hash); 545 curr_pos = hash2pos(filp, fname->hash, fname->minor_hash);
434 while (fname) { 546 while (fname) {
435 error = filldir(dirent, fname->name, 547 error = filldir(dirent, fname->name,
436 fname->name_len, curr_pos, 548 fname->name_len, curr_pos,
@@ -455,13 +567,13 @@ static int ext4_dx_readdir(struct file *filp,
455 int ret; 567 int ret;
456 568
457 if (!info) { 569 if (!info) {
458 info = ext4_htree_create_dir_info(filp->f_pos); 570 info = ext4_htree_create_dir_info(filp, filp->f_pos);
459 if (!info) 571 if (!info)
460 return -ENOMEM; 572 return -ENOMEM;
461 filp->private_data = info; 573 filp->private_data = info;
462 } 574 }
463 575
464 if (filp->f_pos == EXT4_HTREE_EOF) 576 if (filp->f_pos == ext4_get_htree_eof(filp))
465 return 0; /* EOF */ 577 return 0; /* EOF */
466 578
467 /* Some one has messed with f_pos; reset the world */ 579 /* Some one has messed with f_pos; reset the world */
@@ -469,8 +581,8 @@ static int ext4_dx_readdir(struct file *filp,
469 free_rb_tree_fname(&info->root); 581 free_rb_tree_fname(&info->root);
470 info->curr_node = NULL; 582 info->curr_node = NULL;
471 info->extra_fname = NULL; 583 info->extra_fname = NULL;
472 info->curr_hash = pos2maj_hash(filp->f_pos); 584 info->curr_hash = pos2maj_hash(filp, filp->f_pos);
473 info->curr_minor_hash = pos2min_hash(filp->f_pos); 585 info->curr_minor_hash = pos2min_hash(filp, filp->f_pos);
474 } 586 }
475 587
476 /* 588 /*
@@ -502,7 +614,7 @@ static int ext4_dx_readdir(struct file *filp,
502 if (ret < 0) 614 if (ret < 0)
503 return ret; 615 return ret;
504 if (ret == 0) { 616 if (ret == 0) {
505 filp->f_pos = EXT4_HTREE_EOF; 617 filp->f_pos = ext4_get_htree_eof(filp);
506 break; 618 break;
507 } 619 }
508 info->curr_node = rb_first(&info->root); 620 info->curr_node = rb_first(&info->root);
@@ -522,7 +634,7 @@ static int ext4_dx_readdir(struct file *filp,
522 info->curr_minor_hash = fname->minor_hash; 634 info->curr_minor_hash = fname->minor_hash;
523 } else { 635 } else {
524 if (info->next_hash == ~0) { 636 if (info->next_hash == ~0) {
525 filp->f_pos = EXT4_HTREE_EOF; 637 filp->f_pos = ext4_get_htree_eof(filp);
526 break; 638 break;
527 } 639 }
528 info->curr_hash = info->next_hash; 640 info->curr_hash = info->next_hash;
@@ -541,3 +653,15 @@ static int ext4_release_dir(struct inode *inode, struct file *filp)
541 653
542 return 0; 654 return 0;
543} 655}
656
657const struct file_operations ext4_dir_operations = {
658 .llseek = ext4_dir_llseek,
659 .read = generic_read_dir,
660 .readdir = ext4_readdir,
661 .unlocked_ioctl = ext4_ioctl,
662#ifdef CONFIG_COMPAT
663 .compat_ioctl = ext4_compat_ioctl,
664#endif
665 .fsync = ext4_sync_file,
666 .release = ext4_release_dir,
667};
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index ded731ac8a32..ab2594a30f86 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1623,7 +1623,11 @@ struct dx_hash_info
1623 u32 *seed; 1623 u32 *seed;
1624}; 1624};
1625 1625
1626#define EXT4_HTREE_EOF 0x7fffffff 1626
1627/* 32 and 64 bit signed EOF for dx directories */
1628#define EXT4_HTREE_EOF_32BIT ((1UL << (32 - 1)) - 1)
1629#define EXT4_HTREE_EOF_64BIT ((1ULL << (64 - 1)) - 1)
1630
1627 1631
1628/* 1632/*
1629 * Control parameters used by ext4_htree_next_block 1633 * Control parameters used by ext4_htree_next_block
diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c
index ac8f168c8ab4..fa8e4911d354 100644
--- a/fs/ext4/hash.c
+++ b/fs/ext4/hash.c
@@ -200,8 +200,8 @@ int ext4fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
200 return -1; 200 return -1;
201 } 201 }
202 hash = hash & ~1; 202 hash = hash & ~1;
203 if (hash == (EXT4_HTREE_EOF << 1)) 203 if (hash == (EXT4_HTREE_EOF_32BIT << 1))
204 hash = (EXT4_HTREE_EOF-1) << 1; 204 hash = (EXT4_HTREE_EOF_32BIT - 1) << 1;
205 hinfo->hash = hash; 205 hinfo->hash = hash;
206 hinfo->minor_hash = minor_hash; 206 hinfo->minor_hash = minor_hash;
207 return 0; 207 return 0;
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 2774e1013b34..f49b9afc4436 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -496,7 +496,7 @@ static int param_set_##name(const char *val, struct kernel_param *kp) \
496 __typeof__(type) num = which_strtol(val, &endp, 0); \ 496 __typeof__(type) num = which_strtol(val, &endp, 0); \
497 if (endp == val || *endp || num < (min) || num > (max)) \ 497 if (endp == val || *endp || num < (min) || num > (max)) \
498 return -EINVAL; \ 498 return -EINVAL; \
499 *((int *) kp->arg) = num; \ 499 *((type *) kp->arg) = num; \
500 return 0; \ 500 return 0; \
501} 501}
502 502
diff --git a/fs/nfsd/current_stateid.h b/fs/nfsd/current_stateid.h
new file mode 100644
index 000000000000..4123551208d8
--- /dev/null
+++ b/fs/nfsd/current_stateid.h
@@ -0,0 +1,28 @@
1#ifndef _NFSD4_CURRENT_STATE_H
2#define _NFSD4_CURRENT_STATE_H
3
4#include "state.h"
5#include "xdr4.h"
6
7extern void clear_current_stateid(struct nfsd4_compound_state *cstate);
8/*
9 * functions to set current state id
10 */
11extern void nfsd4_set_opendowngradestateid(struct nfsd4_compound_state *cstate, struct nfsd4_open_downgrade *);
12extern void nfsd4_set_openstateid(struct nfsd4_compound_state *, struct nfsd4_open *);
13extern void nfsd4_set_lockstateid(struct nfsd4_compound_state *, struct nfsd4_lock *);
14extern void nfsd4_set_closestateid(struct nfsd4_compound_state *, struct nfsd4_close *);
15
16/*
17 * functions to consume current state id
18 */
19extern void nfsd4_get_opendowngradestateid(struct nfsd4_compound_state *cstate, struct nfsd4_open_downgrade *);
20extern void nfsd4_get_delegreturnstateid(struct nfsd4_compound_state *, struct nfsd4_delegreturn *);
21extern void nfsd4_get_freestateid(struct nfsd4_compound_state *, struct nfsd4_free_stateid *);
22extern void nfsd4_get_setattrstateid(struct nfsd4_compound_state *, struct nfsd4_setattr *);
23extern void nfsd4_get_closestateid(struct nfsd4_compound_state *, struct nfsd4_close *);
24extern void nfsd4_get_lockustateid(struct nfsd4_compound_state *, struct nfsd4_locku *);
25extern void nfsd4_get_readstateid(struct nfsd4_compound_state *, struct nfsd4_read *);
26extern void nfsd4_get_writestateid(struct nfsd4_compound_state *, struct nfsd4_write *);
27
28#endif /* _NFSD4_CURRENT_STATE_H */
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index cf8a6bd062fa..8e9689abbc0c 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -87,7 +87,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
87 struct svc_expkey key; 87 struct svc_expkey key;
88 struct svc_expkey *ek = NULL; 88 struct svc_expkey *ek = NULL;
89 89
90 if (mlen < 1 || mesg[mlen-1] != '\n') 90 if (mesg[mlen - 1] != '\n')
91 return -EINVAL; 91 return -EINVAL;
92 mesg[mlen-1] = 0; 92 mesg[mlen-1] = 0;
93 93
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
new file mode 100644
index 000000000000..12e0cff435b4
--- /dev/null
+++ b/fs/nfsd/netns.h
@@ -0,0 +1,34 @@
1/*
2 * per net namespace data structures for nfsd
3 *
4 * Copyright (C) 2012, Jeff Layton <jlayton@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 51
18 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21#ifndef __NFSD_NETNS_H__
22#define __NFSD_NETNS_H__
23
24#include <net/net_namespace.h>
25#include <net/netns/generic.h>
26
27struct cld_net;
28
29struct nfsd_net {
30 struct cld_net *cld_net;
31};
32
33extern int nfsd_net_id;
34#endif /* __NFSD_NETNS_H__ */
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 0e262f32ac41..c8e9f637153a 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -645,7 +645,6 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
645 .timeout = &timeparms, 645 .timeout = &timeparms,
646 .program = &cb_program, 646 .program = &cb_program,
647 .version = 0, 647 .version = 0,
648 .authflavor = clp->cl_flavor,
649 .flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET), 648 .flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
650 }; 649 };
651 struct rpc_clnt *client; 650 struct rpc_clnt *client;
@@ -656,6 +655,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
656 args.client_name = clp->cl_principal; 655 args.client_name = clp->cl_principal;
657 args.prognumber = conn->cb_prog, 656 args.prognumber = conn->cb_prog,
658 args.protocol = XPRT_TRANSPORT_TCP; 657 args.protocol = XPRT_TRANSPORT_TCP;
658 args.authflavor = clp->cl_flavor;
659 clp->cl_cb_ident = conn->cb_ident; 659 clp->cl_cb_ident = conn->cb_ident;
660 } else { 660 } else {
661 if (!conn->cb_xprt) 661 if (!conn->cb_xprt)
@@ -665,6 +665,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
665 args.bc_xprt = conn->cb_xprt; 665 args.bc_xprt = conn->cb_xprt;
666 args.prognumber = clp->cl_cb_session->se_cb_prog; 666 args.prognumber = clp->cl_cb_session->se_cb_prog;
667 args.protocol = XPRT_TRANSPORT_BC_TCP; 667 args.protocol = XPRT_TRANSPORT_BC_TCP;
668 args.authflavor = RPC_AUTH_UNIX;
668 } 669 }
669 /* Create RPC client */ 670 /* Create RPC client */
670 client = rpc_create(&args); 671 client = rpc_create(&args);
@@ -754,9 +755,9 @@ static void do_probe_callback(struct nfs4_client *clp)
754 */ 755 */
755void nfsd4_probe_callback(struct nfs4_client *clp) 756void nfsd4_probe_callback(struct nfs4_client *clp)
756{ 757{
757 /* XXX: atomicity? Also, should we be using cl_cb_flags? */ 758 /* XXX: atomicity? Also, should we be using cl_flags? */
758 clp->cl_cb_state = NFSD4_CB_UNKNOWN; 759 clp->cl_cb_state = NFSD4_CB_UNKNOWN;
759 set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); 760 set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags);
760 do_probe_callback(clp); 761 do_probe_callback(clp);
761} 762}
762 763
@@ -915,7 +916,7 @@ void nfsd4_destroy_callback_queue(void)
915/* must be called under the state lock */ 916/* must be called under the state lock */
916void nfsd4_shutdown_callback(struct nfs4_client *clp) 917void nfsd4_shutdown_callback(struct nfs4_client *clp)
917{ 918{
918 set_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags); 919 set_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags);
919 /* 920 /*
920 * Note this won't actually result in a null callback; 921 * Note this won't actually result in a null callback;
921 * instead, nfsd4_do_callback_rpc() will detect the killed 922 * instead, nfsd4_do_callback_rpc() will detect the killed
@@ -966,15 +967,15 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
966 svc_xprt_put(clp->cl_cb_conn.cb_xprt); 967 svc_xprt_put(clp->cl_cb_conn.cb_xprt);
967 clp->cl_cb_conn.cb_xprt = NULL; 968 clp->cl_cb_conn.cb_xprt = NULL;
968 } 969 }
969 if (test_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags)) 970 if (test_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags))
970 return; 971 return;
971 spin_lock(&clp->cl_lock); 972 spin_lock(&clp->cl_lock);
972 /* 973 /*
973 * Only serialized callback code is allowed to clear these 974 * Only serialized callback code is allowed to clear these
974 * flags; main nfsd code can only set them: 975 * flags; main nfsd code can only set them:
975 */ 976 */
976 BUG_ON(!clp->cl_cb_flags); 977 BUG_ON(!(clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK));
977 clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); 978 clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags);
978 memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn)); 979 memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn));
979 c = __nfsd4_find_backchannel(clp); 980 c = __nfsd4_find_backchannel(clp);
980 if (c) { 981 if (c) {
@@ -986,7 +987,7 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
986 987
987 err = setup_callback_client(clp, &conn, ses); 988 err = setup_callback_client(clp, &conn, ses);
988 if (err) { 989 if (err) {
989 warn_no_callback_path(clp, err); 990 nfsd4_mark_cb_down(clp, err);
990 return; 991 return;
991 } 992 }
992 /* Yay, the callback channel's back! Restart any callbacks: */ 993 /* Yay, the callback channel's back! Restart any callbacks: */
@@ -1000,7 +1001,7 @@ void nfsd4_do_callback_rpc(struct work_struct *w)
1000 struct nfs4_client *clp = cb->cb_clp; 1001 struct nfs4_client *clp = cb->cb_clp;
1001 struct rpc_clnt *clnt; 1002 struct rpc_clnt *clnt;
1002 1003
1003 if (clp->cl_cb_flags) 1004 if (clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK)
1004 nfsd4_process_cb_update(cb); 1005 nfsd4_process_cb_update(cb);
1005 1006
1006 clnt = clp->cl_cb_client; 1007 clnt = clp->cl_cb_client;
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 94096273cd6c..322d11ce06a4 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -41,6 +41,14 @@
41#include "nfsd.h" 41#include "nfsd.h"
42 42
43/* 43/*
44 * Turn off idmapping when using AUTH_SYS.
45 */
46static bool nfs4_disable_idmapping = true;
47module_param(nfs4_disable_idmapping, bool, 0644);
48MODULE_PARM_DESC(nfs4_disable_idmapping,
49 "Turn off server's NFSv4 idmapping when using 'sec=sys'");
50
51/*
44 * Cache entry 52 * Cache entry
45 */ 53 */
46 54
@@ -561,28 +569,65 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
561 return ret; 569 return ret;
562} 570}
563 571
572static bool
573numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, uid_t *id)
574{
575 int ret;
576 char buf[11];
577
578 if (namelen + 1 > sizeof(buf))
579 /* too long to represent a 32-bit id: */
580 return false;
581 /* Just to make sure it's null-terminated: */
582 memcpy(buf, name, namelen);
583 buf[namelen] = '\0';
584 ret = kstrtouint(name, 10, id);
585 return ret == 0;
586}
587
588static __be32
589do_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, uid_t *id)
590{
591 if (nfs4_disable_idmapping && rqstp->rq_flavor < RPC_AUTH_GSS)
592 if (numeric_name_to_id(rqstp, type, name, namelen, id))
593 return 0;
594 /*
595 * otherwise, fall through and try idmapping, for
596 * backwards compatibility with clients sending names:
597 */
598 return idmap_name_to_id(rqstp, type, name, namelen, id);
599}
600
601static int
602do_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
603{
604 if (nfs4_disable_idmapping && rqstp->rq_flavor < RPC_AUTH_GSS)
605 return sprintf(name, "%u", id);
606 return idmap_id_to_name(rqstp, type, id, name);
607}
608
564__be32 609__be32
565nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen, 610nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
566 __u32 *id) 611 __u32 *id)
567{ 612{
568 return idmap_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id); 613 return do_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id);
569} 614}
570 615
571__be32 616__be32
572nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen, 617nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
573 __u32 *id) 618 __u32 *id)
574{ 619{
575 return idmap_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, id); 620 return do_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, id);
576} 621}
577 622
578int 623int
579nfsd_map_uid_to_name(struct svc_rqst *rqstp, __u32 id, char *name) 624nfsd_map_uid_to_name(struct svc_rqst *rqstp, __u32 id, char *name)
580{ 625{
581 return idmap_id_to_name(rqstp, IDMAP_TYPE_USER, id, name); 626 return do_id_to_name(rqstp, IDMAP_TYPE_USER, id, name);
582} 627}
583 628
584int 629int
585nfsd_map_gid_to_name(struct svc_rqst *rqstp, __u32 id, char *name) 630nfsd_map_gid_to_name(struct svc_rqst *rqstp, __u32 id, char *name)
586{ 631{
587 return idmap_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name); 632 return do_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name);
588} 633}
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 896da74ec563..2ed14dfd00a2 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -39,6 +39,7 @@
39#include "cache.h" 39#include "cache.h"
40#include "xdr4.h" 40#include "xdr4.h"
41#include "vfs.h" 41#include "vfs.h"
42#include "current_stateid.h"
42 43
43#define NFSDDBG_FACILITY NFSDDBG_PROC 44#define NFSDDBG_FACILITY NFSDDBG_PROC
44 45
@@ -192,10 +193,13 @@ static __be32 nfsd_check_obj_isreg(struct svc_fh *fh)
192static __be32 193static __be32
193do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) 194do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
194{ 195{
195 struct svc_fh resfh; 196 struct svc_fh *resfh;
196 __be32 status; 197 __be32 status;
197 198
198 fh_init(&resfh, NFS4_FHSIZE); 199 resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
200 if (!resfh)
201 return nfserr_jukebox;
202 fh_init(resfh, NFS4_FHSIZE);
199 open->op_truncate = 0; 203 open->op_truncate = 0;
200 204
201 if (open->op_create) { 205 if (open->op_create) {
@@ -220,7 +224,7 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
220 */ 224 */
221 status = do_nfsd_create(rqstp, current_fh, open->op_fname.data, 225 status = do_nfsd_create(rqstp, current_fh, open->op_fname.data,
222 open->op_fname.len, &open->op_iattr, 226 open->op_fname.len, &open->op_iattr,
223 &resfh, open->op_createmode, 227 resfh, open->op_createmode,
224 (u32 *)open->op_verf.data, 228 (u32 *)open->op_verf.data,
225 &open->op_truncate, &open->op_created); 229 &open->op_truncate, &open->op_created);
226 230
@@ -234,30 +238,29 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
234 FATTR4_WORD1_TIME_MODIFY); 238 FATTR4_WORD1_TIME_MODIFY);
235 } else { 239 } else {
236 status = nfsd_lookup(rqstp, current_fh, 240 status = nfsd_lookup(rqstp, current_fh,
237 open->op_fname.data, open->op_fname.len, &resfh); 241 open->op_fname.data, open->op_fname.len, resfh);
238 fh_unlock(current_fh); 242 fh_unlock(current_fh);
239 if (status) 243 if (status)
240 goto out; 244 goto out;
241 status = nfsd_check_obj_isreg(&resfh); 245 status = nfsd_check_obj_isreg(resfh);
242 } 246 }
243 if (status) 247 if (status)
244 goto out; 248 goto out;
245 249
246 if (is_create_with_attrs(open) && open->op_acl != NULL) 250 if (is_create_with_attrs(open) && open->op_acl != NULL)
247 do_set_nfs4_acl(rqstp, &resfh, open->op_acl, open->op_bmval); 251 do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval);
248
249 set_change_info(&open->op_cinfo, current_fh);
250 fh_dup2(current_fh, &resfh);
251 252
252 /* set reply cache */ 253 /* set reply cache */
253 fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh, 254 fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
254 &resfh.fh_handle); 255 &resfh->fh_handle);
255 if (!open->op_created) 256 if (!open->op_created)
256 status = do_open_permission(rqstp, current_fh, open, 257 status = do_open_permission(rqstp, resfh, open,
257 NFSD_MAY_NOP); 258 NFSD_MAY_NOP);
258 259 set_change_info(&open->op_cinfo, current_fh);
260 fh_dup2(current_fh, resfh);
259out: 261out:
260 fh_put(&resfh); 262 fh_put(resfh);
263 kfree(resfh);
261 return status; 264 return status;
262} 265}
263 266
@@ -310,16 +313,14 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
310 if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL) 313 if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
311 return nfserr_inval; 314 return nfserr_inval;
312 315
313 /* We don't yet support WANT bits: */
314 open->op_share_access &= NFS4_SHARE_ACCESS_MASK;
315
316 open->op_created = 0; 316 open->op_created = 0;
317 /* 317 /*
318 * RFC5661 18.51.3 318 * RFC5661 18.51.3
319 * Before RECLAIM_COMPLETE done, server should deny new lock 319 * Before RECLAIM_COMPLETE done, server should deny new lock
320 */ 320 */
321 if (nfsd4_has_session(cstate) && 321 if (nfsd4_has_session(cstate) &&
322 !cstate->session->se_client->cl_firststate && 322 !test_bit(NFSD4_CLIENT_RECLAIM_COMPLETE,
323 &cstate->session->se_client->cl_flags) &&
323 open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) 324 open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
324 return nfserr_grace; 325 return nfserr_grace;
325 326
@@ -452,6 +453,10 @@ nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
452 return nfserr_restorefh; 453 return nfserr_restorefh;
453 454
454 fh_dup2(&cstate->current_fh, &cstate->save_fh); 455 fh_dup2(&cstate->current_fh, &cstate->save_fh);
456 if (HAS_STATE_ID(cstate, SAVED_STATE_ID_FLAG)) {
457 memcpy(&cstate->current_stateid, &cstate->save_stateid, sizeof(stateid_t));
458 SET_STATE_ID(cstate, CURRENT_STATE_ID_FLAG);
459 }
455 return nfs_ok; 460 return nfs_ok;
456} 461}
457 462
@@ -463,6 +468,10 @@ nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
463 return nfserr_nofilehandle; 468 return nfserr_nofilehandle;
464 469
465 fh_dup2(&cstate->save_fh, &cstate->current_fh); 470 fh_dup2(&cstate->save_fh, &cstate->current_fh);
471 if (HAS_STATE_ID(cstate, CURRENT_STATE_ID_FLAG)) {
472 memcpy(&cstate->save_stateid, &cstate->current_stateid, sizeof(stateid_t));
473 SET_STATE_ID(cstate, SAVED_STATE_ID_FLAG);
474 }
466 return nfs_ok; 475 return nfs_ok;
467} 476}
468 477
@@ -481,14 +490,20 @@ nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
481 &access->ac_supported); 490 &access->ac_supported);
482} 491}
483 492
493static void gen_boot_verifier(nfs4_verifier *verifier)
494{
495 __be32 verf[2];
496
497 verf[0] = (__be32)nfssvc_boot.tv_sec;
498 verf[1] = (__be32)nfssvc_boot.tv_usec;
499 memcpy(verifier->data, verf, sizeof(verifier->data));
500}
501
484static __be32 502static __be32
485nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 503nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
486 struct nfsd4_commit *commit) 504 struct nfsd4_commit *commit)
487{ 505{
488 u32 *p = (u32 *)commit->co_verf.data; 506 gen_boot_verifier(&commit->co_verf);
489 *p++ = nfssvc_boot.tv_sec;
490 *p++ = nfssvc_boot.tv_usec;
491
492 return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset, 507 return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
493 commit->co_count); 508 commit->co_count);
494} 509}
@@ -865,7 +880,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
865{ 880{
866 stateid_t *stateid = &write->wr_stateid; 881 stateid_t *stateid = &write->wr_stateid;
867 struct file *filp = NULL; 882 struct file *filp = NULL;
868 u32 *p;
869 __be32 status = nfs_ok; 883 __be32 status = nfs_ok;
870 unsigned long cnt; 884 unsigned long cnt;
871 885
@@ -887,9 +901,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
887 901
888 cnt = write->wr_buflen; 902 cnt = write->wr_buflen;
889 write->wr_how_written = write->wr_stable_how; 903 write->wr_how_written = write->wr_stable_how;
890 p = (u32 *)write->wr_verifier.data; 904 gen_boot_verifier(&write->wr_verifier);
891 *p++ = nfssvc_boot.tv_sec;
892 *p++ = nfssvc_boot.tv_usec;
893 905
894 status = nfsd_write(rqstp, &cstate->current_fh, filp, 906 status = nfsd_write(rqstp, &cstate->current_fh, filp,
895 write->wr_offset, rqstp->rq_vec, write->wr_vlen, 907 write->wr_offset, rqstp->rq_vec, write->wr_vlen,
@@ -1000,6 +1012,8 @@ static inline void nfsd4_increment_op_stats(u32 opnum)
1000typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *, 1012typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
1001 void *); 1013 void *);
1002typedef u32(*nfsd4op_rsize)(struct svc_rqst *, struct nfsd4_op *op); 1014typedef u32(*nfsd4op_rsize)(struct svc_rqst *, struct nfsd4_op *op);
1015typedef void(*stateid_setter)(struct nfsd4_compound_state *, void *);
1016typedef void(*stateid_getter)(struct nfsd4_compound_state *, void *);
1003 1017
1004enum nfsd4_op_flags { 1018enum nfsd4_op_flags {
1005 ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */ 1019 ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */
@@ -1025,6 +1039,10 @@ enum nfsd4_op_flags {
1025 * the v4.0 case). 1039 * the v4.0 case).
1026 */ 1040 */
1027 OP_CACHEME = 1 << 6, 1041 OP_CACHEME = 1 << 6,
1042 /*
1043 * These are ops which clear current state id.
1044 */
1045 OP_CLEAR_STATEID = 1 << 7,
1028}; 1046};
1029 1047
1030struct nfsd4_operation { 1048struct nfsd4_operation {
@@ -1033,11 +1051,15 @@ struct nfsd4_operation {
1033 char *op_name; 1051 char *op_name;
1034 /* Try to get response size before operation */ 1052 /* Try to get response size before operation */
1035 nfsd4op_rsize op_rsize_bop; 1053 nfsd4op_rsize op_rsize_bop;
1054 stateid_setter op_get_currentstateid;
1055 stateid_getter op_set_currentstateid;
1036}; 1056};
1037 1057
1038static struct nfsd4_operation nfsd4_ops[]; 1058static struct nfsd4_operation nfsd4_ops[];
1039 1059
1060#ifdef NFSD_DEBUG
1040static const char *nfsd4_op_name(unsigned opnum); 1061static const char *nfsd4_op_name(unsigned opnum);
1062#endif
1041 1063
1042/* 1064/*
1043 * Enforce NFSv4.1 COMPOUND ordering rules: 1065 * Enforce NFSv4.1 COMPOUND ordering rules:
@@ -1215,13 +1237,23 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1215 if (op->status) 1237 if (op->status)
1216 goto encode_op; 1238 goto encode_op;
1217 1239
1218 if (opdesc->op_func) 1240 if (opdesc->op_func) {
1241 if (opdesc->op_get_currentstateid)
1242 opdesc->op_get_currentstateid(cstate, &op->u);
1219 op->status = opdesc->op_func(rqstp, cstate, &op->u); 1243 op->status = opdesc->op_func(rqstp, cstate, &op->u);
1220 else 1244 } else
1221 BUG_ON(op->status == nfs_ok); 1245 BUG_ON(op->status == nfs_ok);
1222 1246
1223 if (!op->status && need_wrongsec_check(rqstp)) 1247 if (!op->status) {
1224 op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp); 1248 if (opdesc->op_set_currentstateid)
1249 opdesc->op_set_currentstateid(cstate, &op->u);
1250
1251 if (opdesc->op_flags & OP_CLEAR_STATEID)
1252 clear_current_stateid(cstate);
1253
1254 if (need_wrongsec_check(rqstp))
1255 op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp);
1256 }
1225 1257
1226encode_op: 1258encode_op:
1227 /* Only from SEQUENCE */ 1259 /* Only from SEQUENCE */
@@ -1413,6 +1445,8 @@ static struct nfsd4_operation nfsd4_ops[] = {
1413 .op_flags = OP_MODIFIES_SOMETHING, 1445 .op_flags = OP_MODIFIES_SOMETHING,
1414 .op_name = "OP_CLOSE", 1446 .op_name = "OP_CLOSE",
1415 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize, 1447 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize,
1448 .op_get_currentstateid = (stateid_getter)nfsd4_get_closestateid,
1449 .op_set_currentstateid = (stateid_setter)nfsd4_set_closestateid,
1416 }, 1450 },
1417 [OP_COMMIT] = { 1451 [OP_COMMIT] = {
1418 .op_func = (nfsd4op_func)nfsd4_commit, 1452 .op_func = (nfsd4op_func)nfsd4_commit,
@@ -1422,7 +1456,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
1422 }, 1456 },
1423 [OP_CREATE] = { 1457 [OP_CREATE] = {
1424 .op_func = (nfsd4op_func)nfsd4_create, 1458 .op_func = (nfsd4op_func)nfsd4_create,
1425 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, 1459 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME | OP_CLEAR_STATEID,
1426 .op_name = "OP_CREATE", 1460 .op_name = "OP_CREATE",
1427 .op_rsize_bop = (nfsd4op_rsize)nfsd4_create_rsize, 1461 .op_rsize_bop = (nfsd4op_rsize)nfsd4_create_rsize,
1428 }, 1462 },
@@ -1431,6 +1465,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
1431 .op_flags = OP_MODIFIES_SOMETHING, 1465 .op_flags = OP_MODIFIES_SOMETHING,
1432 .op_name = "OP_DELEGRETURN", 1466 .op_name = "OP_DELEGRETURN",
1433 .op_rsize_bop = nfsd4_only_status_rsize, 1467 .op_rsize_bop = nfsd4_only_status_rsize,
1468 .op_get_currentstateid = (stateid_getter)nfsd4_get_delegreturnstateid,
1434 }, 1469 },
1435 [OP_GETATTR] = { 1470 [OP_GETATTR] = {
1436 .op_func = (nfsd4op_func)nfsd4_getattr, 1471 .op_func = (nfsd4op_func)nfsd4_getattr,
@@ -1453,6 +1488,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
1453 .op_flags = OP_MODIFIES_SOMETHING, 1488 .op_flags = OP_MODIFIES_SOMETHING,
1454 .op_name = "OP_LOCK", 1489 .op_name = "OP_LOCK",
1455 .op_rsize_bop = (nfsd4op_rsize)nfsd4_lock_rsize, 1490 .op_rsize_bop = (nfsd4op_rsize)nfsd4_lock_rsize,
1491 .op_set_currentstateid = (stateid_setter)nfsd4_set_lockstateid,
1456 }, 1492 },
1457 [OP_LOCKT] = { 1493 [OP_LOCKT] = {
1458 .op_func = (nfsd4op_func)nfsd4_lockt, 1494 .op_func = (nfsd4op_func)nfsd4_lockt,
@@ -1463,15 +1499,16 @@ static struct nfsd4_operation nfsd4_ops[] = {
1463 .op_flags = OP_MODIFIES_SOMETHING, 1499 .op_flags = OP_MODIFIES_SOMETHING,
1464 .op_name = "OP_LOCKU", 1500 .op_name = "OP_LOCKU",
1465 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize, 1501 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize,
1502 .op_get_currentstateid = (stateid_getter)nfsd4_get_lockustateid,
1466 }, 1503 },
1467 [OP_LOOKUP] = { 1504 [OP_LOOKUP] = {
1468 .op_func = (nfsd4op_func)nfsd4_lookup, 1505 .op_func = (nfsd4op_func)nfsd4_lookup,
1469 .op_flags = OP_HANDLES_WRONGSEC, 1506 .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID,
1470 .op_name = "OP_LOOKUP", 1507 .op_name = "OP_LOOKUP",
1471 }, 1508 },
1472 [OP_LOOKUPP] = { 1509 [OP_LOOKUPP] = {
1473 .op_func = (nfsd4op_func)nfsd4_lookupp, 1510 .op_func = (nfsd4op_func)nfsd4_lookupp,
1474 .op_flags = OP_HANDLES_WRONGSEC, 1511 .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID,
1475 .op_name = "OP_LOOKUPP", 1512 .op_name = "OP_LOOKUPP",
1476 }, 1513 },
1477 [OP_NVERIFY] = { 1514 [OP_NVERIFY] = {
@@ -1483,6 +1520,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
1483 .op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING, 1520 .op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING,
1484 .op_name = "OP_OPEN", 1521 .op_name = "OP_OPEN",
1485 .op_rsize_bop = (nfsd4op_rsize)nfsd4_open_rsize, 1522 .op_rsize_bop = (nfsd4op_rsize)nfsd4_open_rsize,
1523 .op_set_currentstateid = (stateid_setter)nfsd4_set_openstateid,
1486 }, 1524 },
1487 [OP_OPEN_CONFIRM] = { 1525 [OP_OPEN_CONFIRM] = {
1488 .op_func = (nfsd4op_func)nfsd4_open_confirm, 1526 .op_func = (nfsd4op_func)nfsd4_open_confirm,
@@ -1495,25 +1533,30 @@ static struct nfsd4_operation nfsd4_ops[] = {
1495 .op_flags = OP_MODIFIES_SOMETHING, 1533 .op_flags = OP_MODIFIES_SOMETHING,
1496 .op_name = "OP_OPEN_DOWNGRADE", 1534 .op_name = "OP_OPEN_DOWNGRADE",
1497 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize, 1535 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize,
1536 .op_get_currentstateid = (stateid_getter)nfsd4_get_opendowngradestateid,
1537 .op_set_currentstateid = (stateid_setter)nfsd4_set_opendowngradestateid,
1498 }, 1538 },
1499 [OP_PUTFH] = { 1539 [OP_PUTFH] = {
1500 .op_func = (nfsd4op_func)nfsd4_putfh, 1540 .op_func = (nfsd4op_func)nfsd4_putfh,
1501 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS 1541 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
1502 | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING, 1542 | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING
1543 | OP_CLEAR_STATEID,
1503 .op_name = "OP_PUTFH", 1544 .op_name = "OP_PUTFH",
1504 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1545 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1505 }, 1546 },
1506 [OP_PUTPUBFH] = { 1547 [OP_PUTPUBFH] = {
1507 .op_func = (nfsd4op_func)nfsd4_putrootfh, 1548 .op_func = (nfsd4op_func)nfsd4_putrootfh,
1508 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS 1549 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
1509 | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING, 1550 | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING
1551 | OP_CLEAR_STATEID,
1510 .op_name = "OP_PUTPUBFH", 1552 .op_name = "OP_PUTPUBFH",
1511 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1553 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1512 }, 1554 },
1513 [OP_PUTROOTFH] = { 1555 [OP_PUTROOTFH] = {
1514 .op_func = (nfsd4op_func)nfsd4_putrootfh, 1556 .op_func = (nfsd4op_func)nfsd4_putrootfh,
1515 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS 1557 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
1516 | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING, 1558 | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING
1559 | OP_CLEAR_STATEID,
1517 .op_name = "OP_PUTROOTFH", 1560 .op_name = "OP_PUTROOTFH",
1518 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1561 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1519 }, 1562 },
@@ -1522,6 +1565,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
1522 .op_flags = OP_MODIFIES_SOMETHING, 1565 .op_flags = OP_MODIFIES_SOMETHING,
1523 .op_name = "OP_READ", 1566 .op_name = "OP_READ",
1524 .op_rsize_bop = (nfsd4op_rsize)nfsd4_read_rsize, 1567 .op_rsize_bop = (nfsd4op_rsize)nfsd4_read_rsize,
1568 .op_get_currentstateid = (stateid_getter)nfsd4_get_readstateid,
1525 }, 1569 },
1526 [OP_READDIR] = { 1570 [OP_READDIR] = {
1527 .op_func = (nfsd4op_func)nfsd4_readdir, 1571 .op_func = (nfsd4op_func)nfsd4_readdir,
@@ -1576,6 +1620,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
1576 .op_name = "OP_SETATTR", 1620 .op_name = "OP_SETATTR",
1577 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, 1621 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
1578 .op_rsize_bop = (nfsd4op_rsize)nfsd4_setattr_rsize, 1622 .op_rsize_bop = (nfsd4op_rsize)nfsd4_setattr_rsize,
1623 .op_get_currentstateid = (stateid_getter)nfsd4_get_setattrstateid,
1579 }, 1624 },
1580 [OP_SETCLIENTID] = { 1625 [OP_SETCLIENTID] = {
1581 .op_func = (nfsd4op_func)nfsd4_setclientid, 1626 .op_func = (nfsd4op_func)nfsd4_setclientid,
@@ -1600,6 +1645,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
1600 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, 1645 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
1601 .op_name = "OP_WRITE", 1646 .op_name = "OP_WRITE",
1602 .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize, 1647 .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize,
1648 .op_get_currentstateid = (stateid_getter)nfsd4_get_writestateid,
1603 }, 1649 },
1604 [OP_RELEASE_LOCKOWNER] = { 1650 [OP_RELEASE_LOCKOWNER] = {
1605 .op_func = (nfsd4op_func)nfsd4_release_lockowner, 1651 .op_func = (nfsd4op_func)nfsd4_release_lockowner,
@@ -1674,12 +1720,14 @@ static struct nfsd4_operation nfsd4_ops[] = {
1674 }, 1720 },
1675}; 1721};
1676 1722
1723#ifdef NFSD_DEBUG
1677static const char *nfsd4_op_name(unsigned opnum) 1724static const char *nfsd4_op_name(unsigned opnum)
1678{ 1725{
1679 if (opnum < ARRAY_SIZE(nfsd4_ops)) 1726 if (opnum < ARRAY_SIZE(nfsd4_ops))
1680 return nfsd4_ops[opnum].op_name; 1727 return nfsd4_ops[opnum].op_name;
1681 return "unknown_operation"; 1728 return "unknown_operation";
1682} 1729}
1730#endif
1683 1731
1684#define nfsd4_voidres nfsd4_voidargs 1732#define nfsd4_voidres nfsd4_voidargs
1685struct nfsd4_voidargs { int dummy; }; 1733struct nfsd4_voidargs { int dummy; };
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 0b3e875d1abd..4767429264a2 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -1,5 +1,6 @@
1/* 1/*
2* Copyright (c) 2004 The Regents of the University of Michigan. 2* Copyright (c) 2004 The Regents of the University of Michigan.
3* Copyright (c) 2012 Jeff Layton <jlayton@redhat.com>
3* All rights reserved. 4* All rights reserved.
4* 5*
5* Andy Adamson <andros@citi.umich.edu> 6* Andy Adamson <andros@citi.umich.edu>
@@ -36,16 +37,34 @@
36#include <linux/namei.h> 37#include <linux/namei.h>
37#include <linux/crypto.h> 38#include <linux/crypto.h>
38#include <linux/sched.h> 39#include <linux/sched.h>
40#include <linux/fs.h>
41#include <linux/module.h>
42#include <net/net_namespace.h>
43#include <linux/sunrpc/rpc_pipe_fs.h>
44#include <linux/sunrpc/clnt.h>
45#include <linux/nfsd/cld.h>
39 46
40#include "nfsd.h" 47#include "nfsd.h"
41#include "state.h" 48#include "state.h"
42#include "vfs.h" 49#include "vfs.h"
50#include "netns.h"
43 51
44#define NFSDDBG_FACILITY NFSDDBG_PROC 52#define NFSDDBG_FACILITY NFSDDBG_PROC
45 53
54/* Declarations */
55struct nfsd4_client_tracking_ops {
56 int (*init)(struct net *);
57 void (*exit)(struct net *);
58 void (*create)(struct nfs4_client *);
59 void (*remove)(struct nfs4_client *);
60 int (*check)(struct nfs4_client *);
61 void (*grace_done)(struct net *, time_t);
62};
63
46/* Globals */ 64/* Globals */
47static struct file *rec_file; 65static struct file *rec_file;
48static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; 66static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
67static struct nfsd4_client_tracking_ops *client_tracking_ops;
49 68
50static int 69static int
51nfs4_save_creds(const struct cred **original_creds) 70nfs4_save_creds(const struct cred **original_creds)
@@ -117,7 +136,8 @@ out_no_tfm:
117 return status; 136 return status;
118} 137}
119 138
120void nfsd4_create_clid_dir(struct nfs4_client *clp) 139static void
140nfsd4_create_clid_dir(struct nfs4_client *clp)
121{ 141{
122 const struct cred *original_cred; 142 const struct cred *original_cred;
123 char *dname = clp->cl_recdir; 143 char *dname = clp->cl_recdir;
@@ -126,9 +146,8 @@ void nfsd4_create_clid_dir(struct nfs4_client *clp)
126 146
127 dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname); 147 dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
128 148
129 if (clp->cl_firststate) 149 if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
130 return; 150 return;
131 clp->cl_firststate = 1;
132 if (!rec_file) 151 if (!rec_file)
133 return; 152 return;
134 status = nfs4_save_creds(&original_cred); 153 status = nfs4_save_creds(&original_cred);
@@ -265,19 +284,19 @@ out_unlock:
265 return status; 284 return status;
266} 285}
267 286
268void 287static void
269nfsd4_remove_clid_dir(struct nfs4_client *clp) 288nfsd4_remove_clid_dir(struct nfs4_client *clp)
270{ 289{
271 const struct cred *original_cred; 290 const struct cred *original_cred;
272 int status; 291 int status;
273 292
274 if (!rec_file || !clp->cl_firststate) 293 if (!rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
275 return; 294 return;
276 295
277 status = mnt_want_write_file(rec_file); 296 status = mnt_want_write_file(rec_file);
278 if (status) 297 if (status)
279 goto out; 298 goto out;
280 clp->cl_firststate = 0; 299 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
281 300
282 status = nfs4_save_creds(&original_cred); 301 status = nfs4_save_creds(&original_cred);
283 if (status < 0) 302 if (status < 0)
@@ -292,7 +311,6 @@ out:
292 if (status) 311 if (status)
293 printk("NFSD: Failed to remove expired client state directory" 312 printk("NFSD: Failed to remove expired client state directory"
294 " %.*s\n", HEXDIR_LEN, clp->cl_recdir); 313 " %.*s\n", HEXDIR_LEN, clp->cl_recdir);
295 return;
296} 314}
297 315
298static int 316static int
@@ -311,8 +329,9 @@ purge_old(struct dentry *parent, struct dentry *child)
311 return 0; 329 return 0;
312} 330}
313 331
314void 332static void
315nfsd4_recdir_purge_old(void) { 333nfsd4_recdir_purge_old(struct net *net, time_t boot_time)
334{
316 int status; 335 int status;
317 336
318 if (!rec_file) 337 if (!rec_file)
@@ -343,7 +362,7 @@ load_recdir(struct dentry *parent, struct dentry *child)
343 return 0; 362 return 0;
344} 363}
345 364
346int 365static int
347nfsd4_recdir_load(void) { 366nfsd4_recdir_load(void) {
348 int status; 367 int status;
349 368
@@ -361,8 +380,8 @@ nfsd4_recdir_load(void) {
361 * Hold reference to the recovery directory. 380 * Hold reference to the recovery directory.
362 */ 381 */
363 382
364void 383static int
365nfsd4_init_recdir() 384nfsd4_init_recdir(void)
366{ 385{
367 const struct cred *original_cred; 386 const struct cred *original_cred;
368 int status; 387 int status;
@@ -377,20 +396,44 @@ nfsd4_init_recdir()
377 printk("NFSD: Unable to change credentials to find recovery" 396 printk("NFSD: Unable to change credentials to find recovery"
378 " directory: error %d\n", 397 " directory: error %d\n",
379 status); 398 status);
380 return; 399 return status;
381 } 400 }
382 401
383 rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0); 402 rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
384 if (IS_ERR(rec_file)) { 403 if (IS_ERR(rec_file)) {
385 printk("NFSD: unable to find recovery directory %s\n", 404 printk("NFSD: unable to find recovery directory %s\n",
386 user_recovery_dirname); 405 user_recovery_dirname);
406 status = PTR_ERR(rec_file);
387 rec_file = NULL; 407 rec_file = NULL;
388 } 408 }
389 409
390 nfs4_reset_creds(original_cred); 410 nfs4_reset_creds(original_cred);
411 return status;
391} 412}
392 413
393void 414static int
415nfsd4_load_reboot_recovery_data(struct net *net)
416{
417 int status;
418
419 /* XXX: The legacy code won't work in a container */
420 if (net != &init_net) {
421 WARN(1, KERN_ERR "NFSD: attempt to initialize legacy client "
422 "tracking in a container!\n");
423 return -EINVAL;
424 }
425
426 nfs4_lock_state();
427 status = nfsd4_init_recdir();
428 if (!status)
429 status = nfsd4_recdir_load();
430 nfs4_unlock_state();
431 if (status)
432 printk(KERN_ERR "NFSD: Failure reading reboot recovery data\n");
433 return status;
434}
435
436static void
394nfsd4_shutdown_recdir(void) 437nfsd4_shutdown_recdir(void)
395{ 438{
396 if (!rec_file) 439 if (!rec_file)
@@ -399,6 +442,13 @@ nfsd4_shutdown_recdir(void)
399 rec_file = NULL; 442 rec_file = NULL;
400} 443}
401 444
445static void
446nfsd4_legacy_tracking_exit(struct net *net)
447{
448 nfs4_release_reclaim();
449 nfsd4_shutdown_recdir();
450}
451
402/* 452/*
403 * Change the NFSv4 recovery directory to recdir. 453 * Change the NFSv4 recovery directory to recdir.
404 */ 454 */
@@ -425,3 +475,572 @@ nfs4_recoverydir(void)
425{ 475{
426 return user_recovery_dirname; 476 return user_recovery_dirname;
427} 477}
478
479static int
480nfsd4_check_legacy_client(struct nfs4_client *clp)
481{
482 /* did we already find that this client is stable? */
483 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
484 return 0;
485
486 /* look for it in the reclaim hashtable otherwise */
487 if (nfsd4_find_reclaim_client(clp)) {
488 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
489 return 0;
490 }
491
492 return -ENOENT;
493}
494
495static struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = {
496 .init = nfsd4_load_reboot_recovery_data,
497 .exit = nfsd4_legacy_tracking_exit,
498 .create = nfsd4_create_clid_dir,
499 .remove = nfsd4_remove_clid_dir,
500 .check = nfsd4_check_legacy_client,
501 .grace_done = nfsd4_recdir_purge_old,
502};
503
504/* Globals */
505#define NFSD_PIPE_DIR "nfsd"
506#define NFSD_CLD_PIPE "cld"
507
508/* per-net-ns structure for holding cld upcall info */
509struct cld_net {
510 struct rpc_pipe *cn_pipe;
511 spinlock_t cn_lock;
512 struct list_head cn_list;
513 unsigned int cn_xid;
514};
515
516struct cld_upcall {
517 struct list_head cu_list;
518 struct cld_net *cu_net;
519 struct task_struct *cu_task;
520 struct cld_msg cu_msg;
521};
522
523static int
524__cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg)
525{
526 int ret;
527 struct rpc_pipe_msg msg;
528
529 memset(&msg, 0, sizeof(msg));
530 msg.data = cmsg;
531 msg.len = sizeof(*cmsg);
532
533 /*
534 * Set task state before we queue the upcall. That prevents
535 * wake_up_process in the downcall from racing with schedule.
536 */
537 set_current_state(TASK_UNINTERRUPTIBLE);
538 ret = rpc_queue_upcall(pipe, &msg);
539 if (ret < 0) {
540 set_current_state(TASK_RUNNING);
541 goto out;
542 }
543
544 schedule();
545 set_current_state(TASK_RUNNING);
546
547 if (msg.errno < 0)
548 ret = msg.errno;
549out:
550 return ret;
551}
552
553static int
554cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg)
555{
556 int ret;
557
558 /*
559 * -EAGAIN occurs when pipe is closed and reopened while there are
560 * upcalls queued.
561 */
562 do {
563 ret = __cld_pipe_upcall(pipe, cmsg);
564 } while (ret == -EAGAIN);
565
566 return ret;
567}
568
569static ssize_t
570cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
571{
572 struct cld_upcall *tmp, *cup;
573 struct cld_msg *cmsg = (struct cld_msg *)src;
574 uint32_t xid;
575 struct nfsd_net *nn = net_generic(filp->f_dentry->d_sb->s_fs_info,
576 nfsd_net_id);
577 struct cld_net *cn = nn->cld_net;
578
579 if (mlen != sizeof(*cmsg)) {
580 dprintk("%s: got %lu bytes, expected %lu\n", __func__, mlen,
581 sizeof(*cmsg));
582 return -EINVAL;
583 }
584
585 /* copy just the xid so we can try to find that */
586 if (copy_from_user(&xid, &cmsg->cm_xid, sizeof(xid)) != 0) {
587 dprintk("%s: error when copying xid from userspace", __func__);
588 return -EFAULT;
589 }
590
591 /* walk the list and find corresponding xid */
592 cup = NULL;
593 spin_lock(&cn->cn_lock);
594 list_for_each_entry(tmp, &cn->cn_list, cu_list) {
595 if (get_unaligned(&tmp->cu_msg.cm_xid) == xid) {
596 cup = tmp;
597 list_del_init(&cup->cu_list);
598 break;
599 }
600 }
601 spin_unlock(&cn->cn_lock);
602
603 /* couldn't find upcall? */
604 if (!cup) {
605 dprintk("%s: couldn't find upcall -- xid=%u\n", __func__, xid);
606 return -EINVAL;
607 }
608
609 if (copy_from_user(&cup->cu_msg, src, mlen) != 0)
610 return -EFAULT;
611
612 wake_up_process(cup->cu_task);
613 return mlen;
614}
615
616static void
617cld_pipe_destroy_msg(struct rpc_pipe_msg *msg)
618{
619 struct cld_msg *cmsg = msg->data;
620 struct cld_upcall *cup = container_of(cmsg, struct cld_upcall,
621 cu_msg);
622
623 /* errno >= 0 means we got a downcall */
624 if (msg->errno >= 0)
625 return;
626
627 wake_up_process(cup->cu_task);
628}
629
630static const struct rpc_pipe_ops cld_upcall_ops = {
631 .upcall = rpc_pipe_generic_upcall,
632 .downcall = cld_pipe_downcall,
633 .destroy_msg = cld_pipe_destroy_msg,
634};
635
636static struct dentry *
637nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe)
638{
639 struct dentry *dir, *dentry;
640
641 dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR);
642 if (dir == NULL)
643 return ERR_PTR(-ENOENT);
644 dentry = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe);
645 dput(dir);
646 return dentry;
647}
648
649static void
650nfsd4_cld_unregister_sb(struct rpc_pipe *pipe)
651{
652 if (pipe->dentry)
653 rpc_unlink(pipe->dentry);
654}
655
656static struct dentry *
657nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe)
658{
659 struct super_block *sb;
660 struct dentry *dentry;
661
662 sb = rpc_get_sb_net(net);
663 if (!sb)
664 return NULL;
665 dentry = nfsd4_cld_register_sb(sb, pipe);
666 rpc_put_sb_net(net);
667 return dentry;
668}
669
670static void
671nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe)
672{
673 struct super_block *sb;
674
675 sb = rpc_get_sb_net(net);
676 if (sb) {
677 nfsd4_cld_unregister_sb(pipe);
678 rpc_put_sb_net(net);
679 }
680}
681
682/* Initialize rpc_pipefs pipe for communication with client tracking daemon */
683static int
684nfsd4_init_cld_pipe(struct net *net)
685{
686 int ret;
687 struct dentry *dentry;
688 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
689 struct cld_net *cn;
690
691 if (nn->cld_net)
692 return 0;
693
694 cn = kzalloc(sizeof(*cn), GFP_KERNEL);
695 if (!cn) {
696 ret = -ENOMEM;
697 goto err;
698 }
699
700 cn->cn_pipe = rpc_mkpipe_data(&cld_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
701 if (IS_ERR(cn->cn_pipe)) {
702 ret = PTR_ERR(cn->cn_pipe);
703 goto err;
704 }
705 spin_lock_init(&cn->cn_lock);
706 INIT_LIST_HEAD(&cn->cn_list);
707
708 dentry = nfsd4_cld_register_net(net, cn->cn_pipe);
709 if (IS_ERR(dentry)) {
710 ret = PTR_ERR(dentry);
711 goto err_destroy_data;
712 }
713
714 cn->cn_pipe->dentry = dentry;
715 nn->cld_net = cn;
716 return 0;
717
718err_destroy_data:
719 rpc_destroy_pipe_data(cn->cn_pipe);
720err:
721 kfree(cn);
722 printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n",
723 ret);
724 return ret;
725}
726
727static void
728nfsd4_remove_cld_pipe(struct net *net)
729{
730 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
731 struct cld_net *cn = nn->cld_net;
732
733 nfsd4_cld_unregister_net(net, cn->cn_pipe);
734 rpc_destroy_pipe_data(cn->cn_pipe);
735 kfree(nn->cld_net);
736 nn->cld_net = NULL;
737}
738
739static struct cld_upcall *
740alloc_cld_upcall(struct cld_net *cn)
741{
742 struct cld_upcall *new, *tmp;
743
744 new = kzalloc(sizeof(*new), GFP_KERNEL);
745 if (!new)
746 return new;
747
748 /* FIXME: hard cap on number in flight? */
749restart_search:
750 spin_lock(&cn->cn_lock);
751 list_for_each_entry(tmp, &cn->cn_list, cu_list) {
752 if (tmp->cu_msg.cm_xid == cn->cn_xid) {
753 cn->cn_xid++;
754 spin_unlock(&cn->cn_lock);
755 goto restart_search;
756 }
757 }
758 new->cu_task = current;
759 new->cu_msg.cm_vers = CLD_UPCALL_VERSION;
760 put_unaligned(cn->cn_xid++, &new->cu_msg.cm_xid);
761 new->cu_net = cn;
762 list_add(&new->cu_list, &cn->cn_list);
763 spin_unlock(&cn->cn_lock);
764
765 dprintk("%s: allocated xid %u\n", __func__, new->cu_msg.cm_xid);
766
767 return new;
768}
769
770static void
771free_cld_upcall(struct cld_upcall *victim)
772{
773 struct cld_net *cn = victim->cu_net;
774
775 spin_lock(&cn->cn_lock);
776 list_del(&victim->cu_list);
777 spin_unlock(&cn->cn_lock);
778 kfree(victim);
779}
780
781/* Ask daemon to create a new record */
782static void
783nfsd4_cld_create(struct nfs4_client *clp)
784{
785 int ret;
786 struct cld_upcall *cup;
787 /* FIXME: determine net from clp */
788 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
789 struct cld_net *cn = nn->cld_net;
790
791 /* Don't upcall if it's already stored */
792 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
793 return;
794
795 cup = alloc_cld_upcall(cn);
796 if (!cup) {
797 ret = -ENOMEM;
798 goto out_err;
799 }
800
801 cup->cu_msg.cm_cmd = Cld_Create;
802 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
803 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
804 clp->cl_name.len);
805
806 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
807 if (!ret) {
808 ret = cup->cu_msg.cm_status;
809 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
810 }
811
812 free_cld_upcall(cup);
813out_err:
814 if (ret)
815 printk(KERN_ERR "NFSD: Unable to create client "
816 "record on stable storage: %d\n", ret);
817}
818
819/* Ask daemon to create a new record */
820static void
821nfsd4_cld_remove(struct nfs4_client *clp)
822{
823 int ret;
824 struct cld_upcall *cup;
825 /* FIXME: determine net from clp */
826 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
827 struct cld_net *cn = nn->cld_net;
828
829 /* Don't upcall if it's already removed */
830 if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
831 return;
832
833 cup = alloc_cld_upcall(cn);
834 if (!cup) {
835 ret = -ENOMEM;
836 goto out_err;
837 }
838
839 cup->cu_msg.cm_cmd = Cld_Remove;
840 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
841 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
842 clp->cl_name.len);
843
844 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
845 if (!ret) {
846 ret = cup->cu_msg.cm_status;
847 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
848 }
849
850 free_cld_upcall(cup);
851out_err:
852 if (ret)
853 printk(KERN_ERR "NFSD: Unable to remove client "
854 "record from stable storage: %d\n", ret);
855}
856
857/* Check for presence of a record, and update its timestamp */
858static int
859nfsd4_cld_check(struct nfs4_client *clp)
860{
861 int ret;
862 struct cld_upcall *cup;
863 /* FIXME: determine net from clp */
864 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
865 struct cld_net *cn = nn->cld_net;
866
867 /* Don't upcall if one was already stored during this grace pd */
868 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
869 return 0;
870
871 cup = alloc_cld_upcall(cn);
872 if (!cup) {
873 printk(KERN_ERR "NFSD: Unable to check client record on "
874 "stable storage: %d\n", -ENOMEM);
875 return -ENOMEM;
876 }
877
878 cup->cu_msg.cm_cmd = Cld_Check;
879 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
880 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
881 clp->cl_name.len);
882
883 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
884 if (!ret) {
885 ret = cup->cu_msg.cm_status;
886 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
887 }
888
889 free_cld_upcall(cup);
890 return ret;
891}
892
893static void
894nfsd4_cld_grace_done(struct net *net, time_t boot_time)
895{
896 int ret;
897 struct cld_upcall *cup;
898 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
899 struct cld_net *cn = nn->cld_net;
900
901 cup = alloc_cld_upcall(cn);
902 if (!cup) {
903 ret = -ENOMEM;
904 goto out_err;
905 }
906
907 cup->cu_msg.cm_cmd = Cld_GraceDone;
908 cup->cu_msg.cm_u.cm_gracetime = (int64_t)boot_time;
909 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg);
910 if (!ret)
911 ret = cup->cu_msg.cm_status;
912
913 free_cld_upcall(cup);
914out_err:
915 if (ret)
916 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret);
917}
918
919static struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = {
920 .init = nfsd4_init_cld_pipe,
921 .exit = nfsd4_remove_cld_pipe,
922 .create = nfsd4_cld_create,
923 .remove = nfsd4_cld_remove,
924 .check = nfsd4_cld_check,
925 .grace_done = nfsd4_cld_grace_done,
926};
927
928int
929nfsd4_client_tracking_init(struct net *net)
930{
931 int status;
932 struct path path;
933
934 if (!client_tracking_ops) {
935 client_tracking_ops = &nfsd4_cld_tracking_ops;
936 status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path);
937 if (!status) {
938 if (S_ISDIR(path.dentry->d_inode->i_mode))
939 client_tracking_ops =
940 &nfsd4_legacy_tracking_ops;
941 path_put(&path);
942 }
943 }
944
945 status = client_tracking_ops->init(net);
946 if (status) {
947 printk(KERN_WARNING "NFSD: Unable to initialize client "
948 "recovery tracking! (%d)\n", status);
949 client_tracking_ops = NULL;
950 }
951 return status;
952}
953
954void
955nfsd4_client_tracking_exit(struct net *net)
956{
957 if (client_tracking_ops) {
958 client_tracking_ops->exit(net);
959 client_tracking_ops = NULL;
960 }
961}
962
963void
964nfsd4_client_record_create(struct nfs4_client *clp)
965{
966 if (client_tracking_ops)
967 client_tracking_ops->create(clp);
968}
969
970void
971nfsd4_client_record_remove(struct nfs4_client *clp)
972{
973 if (client_tracking_ops)
974 client_tracking_ops->remove(clp);
975}
976
977int
978nfsd4_client_record_check(struct nfs4_client *clp)
979{
980 if (client_tracking_ops)
981 return client_tracking_ops->check(clp);
982
983 return -EOPNOTSUPP;
984}
985
986void
987nfsd4_record_grace_done(struct net *net, time_t boot_time)
988{
989 if (client_tracking_ops)
990 client_tracking_ops->grace_done(net, boot_time);
991}
992
993static int
994rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr)
995{
996 struct super_block *sb = ptr;
997 struct net *net = sb->s_fs_info;
998 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
999 struct cld_net *cn = nn->cld_net;
1000 struct dentry *dentry;
1001 int ret = 0;
1002
1003 if (!try_module_get(THIS_MODULE))
1004 return 0;
1005
1006 if (!cn) {
1007 module_put(THIS_MODULE);
1008 return 0;
1009 }
1010
1011 switch (event) {
1012 case RPC_PIPEFS_MOUNT:
1013 dentry = nfsd4_cld_register_sb(sb, cn->cn_pipe);
1014 if (IS_ERR(dentry)) {
1015 ret = PTR_ERR(dentry);
1016 break;
1017 }
1018 cn->cn_pipe->dentry = dentry;
1019 break;
1020 case RPC_PIPEFS_UMOUNT:
1021 if (cn->cn_pipe->dentry)
1022 nfsd4_cld_unregister_sb(cn->cn_pipe);
1023 break;
1024 default:
1025 ret = -ENOTSUPP;
1026 break;
1027 }
1028 module_put(THIS_MODULE);
1029 return ret;
1030}
1031
1032struct notifier_block nfsd4_cld_block = {
1033 .notifier_call = rpc_pipefs_event,
1034};
1035
1036int
1037register_cld_notifier(void)
1038{
1039 return rpc_pipefs_notifier_register(&nfsd4_cld_block);
1040}
1041
1042void
1043unregister_cld_notifier(void)
1044{
1045 rpc_pipefs_notifier_unregister(&nfsd4_cld_block);
1046}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index c5cddd659429..1841f8bf845e 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -58,11 +58,15 @@ static const stateid_t one_stateid = {
58static const stateid_t zero_stateid = { 58static const stateid_t zero_stateid = {
59 /* all fields zero */ 59 /* all fields zero */
60}; 60};
61static const stateid_t currentstateid = {
62 .si_generation = 1,
63};
61 64
62static u64 current_sessionid = 1; 65static u64 current_sessionid = 1;
63 66
64#define ZERO_STATEID(stateid) (!memcmp((stateid), &zero_stateid, sizeof(stateid_t))) 67#define ZERO_STATEID(stateid) (!memcmp((stateid), &zero_stateid, sizeof(stateid_t)))
65#define ONE_STATEID(stateid) (!memcmp((stateid), &one_stateid, sizeof(stateid_t))) 68#define ONE_STATEID(stateid) (!memcmp((stateid), &one_stateid, sizeof(stateid_t)))
69#define CURRENT_STATEID(stateid) (!memcmp((stateid), &currentstateid, sizeof(stateid_t)))
66 70
67/* forward declarations */ 71/* forward declarations */
68static int check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner); 72static int check_for_locks(struct nfs4_file *filp, struct nfs4_lockowner *lowner);
@@ -91,6 +95,19 @@ nfs4_lock_state(void)
91 mutex_lock(&client_mutex); 95 mutex_lock(&client_mutex);
92} 96}
93 97
98static void free_session(struct kref *);
99
100/* Must be called under the client_lock */
101static void nfsd4_put_session_locked(struct nfsd4_session *ses)
102{
103 kref_put(&ses->se_ref, free_session);
104}
105
106static void nfsd4_get_session(struct nfsd4_session *ses)
107{
108 kref_get(&ses->se_ref);
109}
110
94void 111void
95nfs4_unlock_state(void) 112nfs4_unlock_state(void)
96{ 113{
@@ -605,12 +622,20 @@ hash_sessionid(struct nfs4_sessionid *sessionid)
605 return sid->sequence % SESSION_HASH_SIZE; 622 return sid->sequence % SESSION_HASH_SIZE;
606} 623}
607 624
625#ifdef NFSD_DEBUG
608static inline void 626static inline void
609dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid) 627dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid)
610{ 628{
611 u32 *ptr = (u32 *)(&sessionid->data[0]); 629 u32 *ptr = (u32 *)(&sessionid->data[0]);
612 dprintk("%s: %u:%u:%u:%u\n", fn, ptr[0], ptr[1], ptr[2], ptr[3]); 630 dprintk("%s: %u:%u:%u:%u\n", fn, ptr[0], ptr[1], ptr[2], ptr[3]);
613} 631}
632#else
633static inline void
634dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid)
635{
636}
637#endif
638
614 639
615static void 640static void
616gen_sessionid(struct nfsd4_session *ses) 641gen_sessionid(struct nfsd4_session *ses)
@@ -832,11 +857,12 @@ static void nfsd4_del_conns(struct nfsd4_session *s)
832 spin_unlock(&clp->cl_lock); 857 spin_unlock(&clp->cl_lock);
833} 858}
834 859
835void free_session(struct kref *kref) 860static void free_session(struct kref *kref)
836{ 861{
837 struct nfsd4_session *ses; 862 struct nfsd4_session *ses;
838 int mem; 863 int mem;
839 864
865 BUG_ON(!spin_is_locked(&client_lock));
840 ses = container_of(kref, struct nfsd4_session, se_ref); 866 ses = container_of(kref, struct nfsd4_session, se_ref);
841 nfsd4_del_conns(ses); 867 nfsd4_del_conns(ses);
842 spin_lock(&nfsd_drc_lock); 868 spin_lock(&nfsd_drc_lock);
@@ -847,6 +873,13 @@ void free_session(struct kref *kref)
847 kfree(ses); 873 kfree(ses);
848} 874}
849 875
876void nfsd4_put_session(struct nfsd4_session *ses)
877{
878 spin_lock(&client_lock);
879 nfsd4_put_session_locked(ses);
880 spin_unlock(&client_lock);
881}
882
850static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses) 883static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses)
851{ 884{
852 struct nfsd4_session *new; 885 struct nfsd4_session *new;
@@ -894,7 +927,9 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n
894 status = nfsd4_new_conn_from_crses(rqstp, new); 927 status = nfsd4_new_conn_from_crses(rqstp, new);
895 /* whoops: benny points out, status is ignored! (err, or bogus) */ 928 /* whoops: benny points out, status is ignored! (err, or bogus) */
896 if (status) { 929 if (status) {
930 spin_lock(&client_lock);
897 free_session(&new->se_ref); 931 free_session(&new->se_ref);
932 spin_unlock(&client_lock);
898 return NULL; 933 return NULL;
899 } 934 }
900 if (cses->flags & SESSION4_BACK_CHAN) { 935 if (cses->flags & SESSION4_BACK_CHAN) {
@@ -1006,12 +1041,13 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
1006static inline void 1041static inline void
1007free_client(struct nfs4_client *clp) 1042free_client(struct nfs4_client *clp)
1008{ 1043{
1044 BUG_ON(!spin_is_locked(&client_lock));
1009 while (!list_empty(&clp->cl_sessions)) { 1045 while (!list_empty(&clp->cl_sessions)) {
1010 struct nfsd4_session *ses; 1046 struct nfsd4_session *ses;
1011 ses = list_entry(clp->cl_sessions.next, struct nfsd4_session, 1047 ses = list_entry(clp->cl_sessions.next, struct nfsd4_session,
1012 se_perclnt); 1048 se_perclnt);
1013 list_del(&ses->se_perclnt); 1049 list_del(&ses->se_perclnt);
1014 nfsd4_put_session(ses); 1050 nfsd4_put_session_locked(ses);
1015 } 1051 }
1016 if (clp->cl_cred.cr_group_info) 1052 if (clp->cl_cred.cr_group_info)
1017 put_group_info(clp->cl_cred.cr_group_info); 1053 put_group_info(clp->cl_cred.cr_group_info);
@@ -1138,12 +1174,12 @@ static void gen_clid(struct nfs4_client *clp)
1138 1174
1139static void gen_confirm(struct nfs4_client *clp) 1175static void gen_confirm(struct nfs4_client *clp)
1140{ 1176{
1177 __be32 verf[2];
1141 static u32 i; 1178 static u32 i;
1142 u32 *p;
1143 1179
1144 p = (u32 *)clp->cl_confirm.data; 1180 verf[0] = (__be32)get_seconds();
1145 *p++ = get_seconds(); 1181 verf[1] = (__be32)i++;
1146 *p++ = i++; 1182 memcpy(clp->cl_confirm.data, verf, sizeof(clp->cl_confirm.data));
1147} 1183}
1148 1184
1149static struct nfs4_stid *find_stateid(struct nfs4_client *cl, stateid_t *t) 1185static struct nfs4_stid *find_stateid(struct nfs4_client *cl, stateid_t *t)
@@ -1180,7 +1216,9 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
1180 if (princ) { 1216 if (princ) {
1181 clp->cl_principal = kstrdup(princ, GFP_KERNEL); 1217 clp->cl_principal = kstrdup(princ, GFP_KERNEL);
1182 if (clp->cl_principal == NULL) { 1218 if (clp->cl_principal == NULL) {
1219 spin_lock(&client_lock);
1183 free_client(clp); 1220 free_client(clp);
1221 spin_unlock(&client_lock);
1184 return NULL; 1222 return NULL;
1185 } 1223 }
1186 } 1224 }
@@ -1347,6 +1385,7 @@ nfsd4_store_cache_entry(struct nfsd4_compoundres *resp)
1347 slot->sl_opcnt = resp->opcnt; 1385 slot->sl_opcnt = resp->opcnt;
1348 slot->sl_status = resp->cstate.status; 1386 slot->sl_status = resp->cstate.status;
1349 1387
1388 slot->sl_flags |= NFSD4_SLOT_INITIALIZED;
1350 if (nfsd4_not_cached(resp)) { 1389 if (nfsd4_not_cached(resp)) {
1351 slot->sl_datalen = 0; 1390 slot->sl_datalen = 0;
1352 return; 1391 return;
@@ -1374,15 +1413,12 @@ nfsd4_enc_sequence_replay(struct nfsd4_compoundargs *args,
1374 struct nfsd4_op *op; 1413 struct nfsd4_op *op;
1375 struct nfsd4_slot *slot = resp->cstate.slot; 1414 struct nfsd4_slot *slot = resp->cstate.slot;
1376 1415
1377 dprintk("--> %s resp->opcnt %d cachethis %u \n", __func__,
1378 resp->opcnt, resp->cstate.slot->sl_cachethis);
1379
1380 /* Encode the replayed sequence operation */ 1416 /* Encode the replayed sequence operation */
1381 op = &args->ops[resp->opcnt - 1]; 1417 op = &args->ops[resp->opcnt - 1];
1382 nfsd4_encode_operation(resp, op); 1418 nfsd4_encode_operation(resp, op);
1383 1419
1384 /* Return nfserr_retry_uncached_rep in next operation. */ 1420 /* Return nfserr_retry_uncached_rep in next operation. */
1385 if (args->opcnt > 1 && slot->sl_cachethis == 0) { 1421 if (args->opcnt > 1 && !(slot->sl_flags & NFSD4_SLOT_CACHETHIS)) {
1386 op = &args->ops[resp->opcnt++]; 1422 op = &args->ops[resp->opcnt++];
1387 op->status = nfserr_retry_uncached_rep; 1423 op->status = nfserr_retry_uncached_rep;
1388 nfsd4_encode_operation(resp, op); 1424 nfsd4_encode_operation(resp, op);
@@ -1575,16 +1611,11 @@ check_slot_seqid(u32 seqid, u32 slot_seqid, int slot_inuse)
1575 else 1611 else
1576 return nfserr_seq_misordered; 1612 return nfserr_seq_misordered;
1577 } 1613 }
1578 /* Normal */ 1614 /* Note unsigned 32-bit arithmetic handles wraparound: */
1579 if (likely(seqid == slot_seqid + 1)) 1615 if (likely(seqid == slot_seqid + 1))
1580 return nfs_ok; 1616 return nfs_ok;
1581 /* Replay */
1582 if (seqid == slot_seqid) 1617 if (seqid == slot_seqid)
1583 return nfserr_replay_cache; 1618 return nfserr_replay_cache;
1584 /* Wraparound */
1585 if (seqid == 1 && (slot_seqid + 1) == 0)
1586 return nfs_ok;
1587 /* Misordered replay or misordered new request */
1588 return nfserr_seq_misordered; 1619 return nfserr_seq_misordered;
1589} 1620}
1590 1621
@@ -1815,9 +1846,10 @@ nfsd4_destroy_session(struct svc_rqst *r,
1815 nfsd4_probe_callback_sync(ses->se_client); 1846 nfsd4_probe_callback_sync(ses->se_client);
1816 nfs4_unlock_state(); 1847 nfs4_unlock_state();
1817 1848
1849 spin_lock(&client_lock);
1818 nfsd4_del_conns(ses); 1850 nfsd4_del_conns(ses);
1819 1851 nfsd4_put_session_locked(ses);
1820 nfsd4_put_session(ses); 1852 spin_unlock(&client_lock);
1821 status = nfs_ok; 1853 status = nfs_ok;
1822out: 1854out:
1823 dprintk("%s returns %d\n", __func__, ntohl(status)); 1855 dprintk("%s returns %d\n", __func__, ntohl(status));
@@ -1921,8 +1953,12 @@ nfsd4_sequence(struct svc_rqst *rqstp,
1921 * sr_highest_slotid and the sr_target_slot id to maxslots */ 1953 * sr_highest_slotid and the sr_target_slot id to maxslots */
1922 seq->maxslots = session->se_fchannel.maxreqs; 1954 seq->maxslots = session->se_fchannel.maxreqs;
1923 1955
1924 status = check_slot_seqid(seq->seqid, slot->sl_seqid, slot->sl_inuse); 1956 status = check_slot_seqid(seq->seqid, slot->sl_seqid,
1957 slot->sl_flags & NFSD4_SLOT_INUSE);
1925 if (status == nfserr_replay_cache) { 1958 if (status == nfserr_replay_cache) {
1959 status = nfserr_seq_misordered;
1960 if (!(slot->sl_flags & NFSD4_SLOT_INITIALIZED))
1961 goto out;
1926 cstate->slot = slot; 1962 cstate->slot = slot;
1927 cstate->session = session; 1963 cstate->session = session;
1928 /* Return the cached reply status and set cstate->status 1964 /* Return the cached reply status and set cstate->status
@@ -1938,9 +1974,12 @@ nfsd4_sequence(struct svc_rqst *rqstp,
1938 conn = NULL; 1974 conn = NULL;
1939 1975
1940 /* Success! bump slot seqid */ 1976 /* Success! bump slot seqid */
1941 slot->sl_inuse = true;
1942 slot->sl_seqid = seq->seqid; 1977 slot->sl_seqid = seq->seqid;
1943 slot->sl_cachethis = seq->cachethis; 1978 slot->sl_flags |= NFSD4_SLOT_INUSE;
1979 if (seq->cachethis)
1980 slot->sl_flags |= NFSD4_SLOT_CACHETHIS;
1981 else
1982 slot->sl_flags &= ~NFSD4_SLOT_CACHETHIS;
1944 1983
1945 cstate->slot = slot; 1984 cstate->slot = slot;
1946 cstate->session = session; 1985 cstate->session = session;
@@ -2030,7 +2069,8 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
2030 2069
2031 nfs4_lock_state(); 2070 nfs4_lock_state();
2032 status = nfserr_complete_already; 2071 status = nfserr_complete_already;
2033 if (cstate->session->se_client->cl_firststate) 2072 if (test_and_set_bit(NFSD4_CLIENT_RECLAIM_COMPLETE,
2073 &cstate->session->se_client->cl_flags))
2034 goto out; 2074 goto out;
2035 2075
2036 status = nfserr_stale_clientid; 2076 status = nfserr_stale_clientid;
@@ -2045,7 +2085,7 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
2045 goto out; 2085 goto out;
2046 2086
2047 status = nfs_ok; 2087 status = nfs_ok;
2048 nfsd4_create_clid_dir(cstate->session->se_client); 2088 nfsd4_client_record_create(cstate->session->se_client);
2049out: 2089out:
2050 nfs4_unlock_state(); 2090 nfs4_unlock_state();
2051 return status; 2091 return status;
@@ -2240,7 +2280,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
2240 conf = find_confirmed_client_by_str(unconf->cl_recdir, 2280 conf = find_confirmed_client_by_str(unconf->cl_recdir,
2241 hash); 2281 hash);
2242 if (conf) { 2282 if (conf) {
2243 nfsd4_remove_clid_dir(conf); 2283 nfsd4_client_record_remove(conf);
2244 expire_client(conf); 2284 expire_client(conf);
2245 } 2285 }
2246 move_to_confirmed(unconf); 2286 move_to_confirmed(unconf);
@@ -2633,8 +2673,6 @@ nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
2633 2673
2634static int share_access_to_flags(u32 share_access) 2674static int share_access_to_flags(u32 share_access)
2635{ 2675{
2636 share_access &= ~NFS4_SHARE_WANT_MASK;
2637
2638 return share_access == NFS4_SHARE_ACCESS_READ ? RD_STATE : WR_STATE; 2676 return share_access == NFS4_SHARE_ACCESS_READ ? RD_STATE : WR_STATE;
2639} 2677}
2640 2678
@@ -2776,10 +2814,9 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *c
2776 2814
2777 2815
2778static void 2816static void
2779nfs4_set_claim_prev(struct nfsd4_open *open) 2817nfs4_set_claim_prev(struct nfsd4_open *open, bool has_session)
2780{ 2818{
2781 open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; 2819 open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
2782 open->op_openowner->oo_owner.so_client->cl_firststate = 1;
2783} 2820}
2784 2821
2785/* Should we give out recallable state?: */ 2822/* Should we give out recallable state?: */
@@ -2855,6 +2892,27 @@ static int nfs4_set_delegation(struct nfs4_delegation *dp, int flag)
2855 return 0; 2892 return 0;
2856} 2893}
2857 2894
2895static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
2896{
2897 open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
2898 if (status == -EAGAIN)
2899 open->op_why_no_deleg = WND4_CONTENTION;
2900 else {
2901 open->op_why_no_deleg = WND4_RESOURCE;
2902 switch (open->op_deleg_want) {
2903 case NFS4_SHARE_WANT_READ_DELEG:
2904 case NFS4_SHARE_WANT_WRITE_DELEG:
2905 case NFS4_SHARE_WANT_ANY_DELEG:
2906 break;
2907 case NFS4_SHARE_WANT_CANCEL:
2908 open->op_why_no_deleg = WND4_CANCELLED;
2909 break;
2910 case NFS4_SHARE_WANT_NO_DELEG:
2911 BUG(); /* not supposed to get here */
2912 }
2913 }
2914}
2915
2858/* 2916/*
2859 * Attempt to hand out a delegation. 2917 * Attempt to hand out a delegation.
2860 */ 2918 */
@@ -2864,7 +2922,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_
2864 struct nfs4_delegation *dp; 2922 struct nfs4_delegation *dp;
2865 struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner); 2923 struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner);
2866 int cb_up; 2924 int cb_up;
2867 int status, flag = 0; 2925 int status = 0, flag = 0;
2868 2926
2869 cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client); 2927 cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client);
2870 flag = NFS4_OPEN_DELEGATE_NONE; 2928 flag = NFS4_OPEN_DELEGATE_NONE;
@@ -2905,11 +2963,16 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_
2905 dprintk("NFSD: delegation stateid=" STATEID_FMT "\n", 2963 dprintk("NFSD: delegation stateid=" STATEID_FMT "\n",
2906 STATEID_VAL(&dp->dl_stid.sc_stateid)); 2964 STATEID_VAL(&dp->dl_stid.sc_stateid));
2907out: 2965out:
2908 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS
2909 && flag == NFS4_OPEN_DELEGATE_NONE
2910 && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
2911 dprintk("NFSD: WARNING: refusing delegation reclaim\n");
2912 open->op_delegate_type = flag; 2966 open->op_delegate_type = flag;
2967 if (flag == NFS4_OPEN_DELEGATE_NONE) {
2968 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&
2969 open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
2970 dprintk("NFSD: WARNING: refusing delegation reclaim\n");
2971
2972 /* 4.1 client asking for a delegation? */
2973 if (open->op_deleg_want)
2974 nfsd4_open_deleg_none_ext(open, status);
2975 }
2913 return; 2976 return;
2914out_free: 2977out_free:
2915 nfs4_put_delegation(dp); 2978 nfs4_put_delegation(dp);
@@ -2918,6 +2981,24 @@ out_no_deleg:
2918 goto out; 2981 goto out;
2919} 2982}
2920 2983
2984static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open,
2985 struct nfs4_delegation *dp)
2986{
2987 if (open->op_deleg_want == NFS4_SHARE_WANT_READ_DELEG &&
2988 dp->dl_type == NFS4_OPEN_DELEGATE_WRITE) {
2989 open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
2990 open->op_why_no_deleg = WND4_NOT_SUPP_DOWNGRADE;
2991 } else if (open->op_deleg_want == NFS4_SHARE_WANT_WRITE_DELEG &&
2992 dp->dl_type == NFS4_OPEN_DELEGATE_WRITE) {
2993 open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
2994 open->op_why_no_deleg = WND4_NOT_SUPP_UPGRADE;
2995 }
2996 /* Otherwise the client must be confused wanting a delegation
2997 * it already has, therefore we don't return
2998 * NFS4_OPEN_DELEGATE_NONE_EXT and reason.
2999 */
3000}
3001
2921/* 3002/*
2922 * called with nfs4_lock_state() held. 3003 * called with nfs4_lock_state() held.
2923 */ 3004 */
@@ -2979,24 +3060,36 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
2979 update_stateid(&stp->st_stid.sc_stateid); 3060 update_stateid(&stp->st_stid.sc_stateid);
2980 memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 3061 memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
2981 3062
2982 if (nfsd4_has_session(&resp->cstate)) 3063 if (nfsd4_has_session(&resp->cstate)) {
2983 open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; 3064 open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
2984 3065
3066 if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) {
3067 open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT;
3068 open->op_why_no_deleg = WND4_NOT_WANTED;
3069 goto nodeleg;
3070 }
3071 }
3072
2985 /* 3073 /*
2986 * Attempt to hand out a delegation. No error return, because the 3074 * Attempt to hand out a delegation. No error return, because the
2987 * OPEN succeeds even if we fail. 3075 * OPEN succeeds even if we fail.
2988 */ 3076 */
2989 nfs4_open_delegation(current_fh, open, stp); 3077 nfs4_open_delegation(current_fh, open, stp);
2990 3078nodeleg:
2991 status = nfs_ok; 3079 status = nfs_ok;
2992 3080
2993 dprintk("%s: stateid=" STATEID_FMT "\n", __func__, 3081 dprintk("%s: stateid=" STATEID_FMT "\n", __func__,
2994 STATEID_VAL(&stp->st_stid.sc_stateid)); 3082 STATEID_VAL(&stp->st_stid.sc_stateid));
2995out: 3083out:
3084 /* 4.1 client trying to upgrade/downgrade delegation? */
3085 if (open->op_delegate_type == NFS4_OPEN_DELEGATE_NONE && dp &&
3086 open->op_deleg_want)
3087 nfsd4_deleg_xgrade_none_ext(open, dp);
3088
2996 if (fp) 3089 if (fp)
2997 put_nfs4_file(fp); 3090 put_nfs4_file(fp);
2998 if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) 3091 if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
2999 nfs4_set_claim_prev(open); 3092 nfs4_set_claim_prev(open, nfsd4_has_session(&resp->cstate));
3000 /* 3093 /*
3001 * To finish the open response, we just need to set the rflags. 3094 * To finish the open response, we just need to set the rflags.
3002 */ 3095 */
@@ -3066,7 +3159,7 @@ static void
3066nfsd4_end_grace(void) 3159nfsd4_end_grace(void)
3067{ 3160{
3068 dprintk("NFSD: end of grace period\n"); 3161 dprintk("NFSD: end of grace period\n");
3069 nfsd4_recdir_purge_old(); 3162 nfsd4_record_grace_done(&init_net, boot_time);
3070 locks_end_grace(&nfsd4_manager); 3163 locks_end_grace(&nfsd4_manager);
3071 /* 3164 /*
3072 * Now that every NFSv4 client has had the chance to recover and 3165 * Now that every NFSv4 client has had the chance to recover and
@@ -3115,7 +3208,7 @@ nfs4_laundromat(void)
3115 clp = list_entry(pos, struct nfs4_client, cl_lru); 3208 clp = list_entry(pos, struct nfs4_client, cl_lru);
3116 dprintk("NFSD: purging unused client (clientid %08x)\n", 3209 dprintk("NFSD: purging unused client (clientid %08x)\n",
3117 clp->cl_clientid.cl_id); 3210 clp->cl_clientid.cl_id);
3118 nfsd4_remove_clid_dir(clp); 3211 nfsd4_client_record_remove(clp);
3119 expire_client(clp); 3212 expire_client(clp);
3120 } 3213 }
3121 spin_lock(&recall_lock); 3214 spin_lock(&recall_lock);
@@ -3400,7 +3493,14 @@ __be32
3400nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 3493nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3401 struct nfsd4_test_stateid *test_stateid) 3494 struct nfsd4_test_stateid *test_stateid)
3402{ 3495{
3403 /* real work is done during encoding */ 3496 struct nfsd4_test_stateid_id *stateid;
3497 struct nfs4_client *cl = cstate->session->se_client;
3498
3499 nfs4_lock_state();
3500 list_for_each_entry(stateid, &test_stateid->ts_stateid_list, ts_id_list)
3501 stateid->ts_id_status = nfs4_validate_stateid(cl, &stateid->ts_id_stateid);
3502 nfs4_unlock_state();
3503
3404 return nfs_ok; 3504 return nfs_ok;
3405} 3505}
3406 3506
@@ -3539,7 +3639,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3539 dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n", 3639 dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
3540 __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid)); 3640 __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid));
3541 3641
3542 nfsd4_create_clid_dir(oo->oo_owner.so_client); 3642 nfsd4_client_record_create(oo->oo_owner.so_client);
3543 status = nfs_ok; 3643 status = nfs_ok;
3544out: 3644out:
3545 if (!cstate->replay_owner) 3645 if (!cstate->replay_owner)
@@ -3596,7 +3696,9 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
3596 cstate->current_fh.fh_dentry->d_name.name); 3696 cstate->current_fh.fh_dentry->d_name.name);
3597 3697
3598 /* We don't yet support WANT bits: */ 3698 /* We don't yet support WANT bits: */
3599 od->od_share_access &= NFS4_SHARE_ACCESS_MASK; 3699 if (od->od_deleg_want)
3700 dprintk("NFSD: %s: od_deleg_want=0x%x ignored\n", __func__,
3701 od->od_deleg_want);
3600 3702
3601 nfs4_lock_state(); 3703 nfs4_lock_state();
3602 status = nfs4_preprocess_confirmed_seqid_op(cstate, od->od_seqid, 3704 status = nfs4_preprocess_confirmed_seqid_op(cstate, od->od_seqid,
@@ -4353,7 +4455,9 @@ nfs4_has_reclaimed_state(const char *name, bool use_exchange_id)
4353 struct nfs4_client *clp; 4455 struct nfs4_client *clp;
4354 4456
4355 clp = find_confirmed_client_by_str(name, strhashval); 4457 clp = find_confirmed_client_by_str(name, strhashval);
4356 return clp ? 1 : 0; 4458 if (!clp)
4459 return 0;
4460 return test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
4357} 4461}
4358 4462
4359/* 4463/*
@@ -4377,7 +4481,7 @@ nfs4_client_to_reclaim(const char *name)
4377 return 1; 4481 return 1;
4378} 4482}
4379 4483
4380static void 4484void
4381nfs4_release_reclaim(void) 4485nfs4_release_reclaim(void)
4382{ 4486{
4383 struct nfs4_client_reclaim *crp = NULL; 4487 struct nfs4_client_reclaim *crp = NULL;
@@ -4397,19 +4501,12 @@ nfs4_release_reclaim(void)
4397 4501
4398/* 4502/*
4399 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */ 4503 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
4400static struct nfs4_client_reclaim * 4504struct nfs4_client_reclaim *
4401nfs4_find_reclaim_client(clientid_t *clid) 4505nfsd4_find_reclaim_client(struct nfs4_client *clp)
4402{ 4506{
4403 unsigned int strhashval; 4507 unsigned int strhashval;
4404 struct nfs4_client *clp;
4405 struct nfs4_client_reclaim *crp = NULL; 4508 struct nfs4_client_reclaim *crp = NULL;
4406 4509
4407
4408 /* find clientid in conf_id_hashtbl */
4409 clp = find_confirmed_client(clid);
4410 if (clp == NULL)
4411 return NULL;
4412
4413 dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n", 4510 dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n",
4414 clp->cl_name.len, clp->cl_name.data, 4511 clp->cl_name.len, clp->cl_name.data,
4415 clp->cl_recdir); 4512 clp->cl_recdir);
@@ -4430,7 +4527,14 @@ nfs4_find_reclaim_client(clientid_t *clid)
4430__be32 4527__be32
4431nfs4_check_open_reclaim(clientid_t *clid) 4528nfs4_check_open_reclaim(clientid_t *clid)
4432{ 4529{
4433 return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad; 4530 struct nfs4_client *clp;
4531
4532 /* find clientid in conf_id_hashtbl */
4533 clp = find_confirmed_client(clid);
4534 if (clp == NULL)
4535 return nfserr_reclaim_bad;
4536
4537 return nfsd4_client_record_check(clp) ? nfserr_reclaim_bad : nfs_ok;
4434} 4538}
4435 4539
4436#ifdef CONFIG_NFSD_FAULT_INJECTION 4540#ifdef CONFIG_NFSD_FAULT_INJECTION
@@ -4442,7 +4546,7 @@ void nfsd_forget_clients(u64 num)
4442 4546
4443 nfs4_lock_state(); 4547 nfs4_lock_state();
4444 list_for_each_entry_safe(clp, next, &client_lru, cl_lru) { 4548 list_for_each_entry_safe(clp, next, &client_lru, cl_lru) {
4445 nfsd4_remove_clid_dir(clp); 4549 nfsd4_client_record_remove(clp);
4446 expire_client(clp); 4550 expire_client(clp);
4447 if (++count == num) 4551 if (++count == num)
4448 break; 4552 break;
@@ -4577,19 +4681,6 @@ nfs4_state_init(void)
4577 reclaim_str_hashtbl_size = 0; 4681 reclaim_str_hashtbl_size = 0;
4578} 4682}
4579 4683
4580static void
4581nfsd4_load_reboot_recovery_data(void)
4582{
4583 int status;
4584
4585 nfs4_lock_state();
4586 nfsd4_init_recdir();
4587 status = nfsd4_recdir_load();
4588 nfs4_unlock_state();
4589 if (status)
4590 printk("NFSD: Failure reading reboot recovery data\n");
4591}
4592
4593/* 4684/*
4594 * Since the lifetime of a delegation isn't limited to that of an open, a 4685 * Since the lifetime of a delegation isn't limited to that of an open, a
4595 * client may quite reasonably hang on to a delegation as long as it has 4686 * client may quite reasonably hang on to a delegation as long as it has
@@ -4613,21 +4704,34 @@ set_max_delegations(void)
4613 4704
4614/* initialization to perform when the nfsd service is started: */ 4705/* initialization to perform when the nfsd service is started: */
4615 4706
4616static int 4707int
4617__nfs4_state_start(void) 4708nfs4_state_start(void)
4618{ 4709{
4619 int ret; 4710 int ret;
4620 4711
4712 /*
4713 * FIXME: For now, we hang most of the pernet global stuff off of
4714 * init_net until nfsd is fully containerized. Eventually, we'll
4715 * need to pass a net pointer into this function, take a reference
4716 * to that instead and then do most of the rest of this on a per-net
4717 * basis.
4718 */
4719 get_net(&init_net);
4720 nfsd4_client_tracking_init(&init_net);
4621 boot_time = get_seconds(); 4721 boot_time = get_seconds();
4622 locks_start_grace(&nfsd4_manager); 4722 locks_start_grace(&nfsd4_manager);
4623 printk(KERN_INFO "NFSD: starting %ld-second grace period\n", 4723 printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
4624 nfsd4_grace); 4724 nfsd4_grace);
4625 ret = set_callback_cred(); 4725 ret = set_callback_cred();
4626 if (ret) 4726 if (ret) {
4627 return -ENOMEM; 4727 ret = -ENOMEM;
4728 goto out_recovery;
4729 }
4628 laundry_wq = create_singlethread_workqueue("nfsd4"); 4730 laundry_wq = create_singlethread_workqueue("nfsd4");
4629 if (laundry_wq == NULL) 4731 if (laundry_wq == NULL) {
4630 return -ENOMEM; 4732 ret = -ENOMEM;
4733 goto out_recovery;
4734 }
4631 ret = nfsd4_create_callback_queue(); 4735 ret = nfsd4_create_callback_queue();
4632 if (ret) 4736 if (ret)
4633 goto out_free_laundry; 4737 goto out_free_laundry;
@@ -4636,16 +4740,12 @@ __nfs4_state_start(void)
4636 return 0; 4740 return 0;
4637out_free_laundry: 4741out_free_laundry:
4638 destroy_workqueue(laundry_wq); 4742 destroy_workqueue(laundry_wq);
4743out_recovery:
4744 nfsd4_client_tracking_exit(&init_net);
4745 put_net(&init_net);
4639 return ret; 4746 return ret;
4640} 4747}
4641 4748
4642int
4643nfs4_state_start(void)
4644{
4645 nfsd4_load_reboot_recovery_data();
4646 return __nfs4_state_start();
4647}
4648
4649static void 4749static void
4650__nfs4_state_shutdown(void) 4750__nfs4_state_shutdown(void)
4651{ 4751{
@@ -4676,7 +4776,8 @@ __nfs4_state_shutdown(void)
4676 unhash_delegation(dp); 4776 unhash_delegation(dp);
4677 } 4777 }
4678 4778
4679 nfsd4_shutdown_recdir(); 4779 nfsd4_client_tracking_exit(&init_net);
4780 put_net(&init_net);
4680} 4781}
4681 4782
4682void 4783void
@@ -4686,8 +4787,108 @@ nfs4_state_shutdown(void)
4686 destroy_workqueue(laundry_wq); 4787 destroy_workqueue(laundry_wq);
4687 locks_end_grace(&nfsd4_manager); 4788 locks_end_grace(&nfsd4_manager);
4688 nfs4_lock_state(); 4789 nfs4_lock_state();
4689 nfs4_release_reclaim();
4690 __nfs4_state_shutdown(); 4790 __nfs4_state_shutdown();
4691 nfs4_unlock_state(); 4791 nfs4_unlock_state();
4692 nfsd4_destroy_callback_queue(); 4792 nfsd4_destroy_callback_queue();
4693} 4793}
4794
4795static void
4796get_stateid(struct nfsd4_compound_state *cstate, stateid_t *stateid)
4797{
4798 if (HAS_STATE_ID(cstate, CURRENT_STATE_ID_FLAG) && CURRENT_STATEID(stateid))
4799 memcpy(stateid, &cstate->current_stateid, sizeof(stateid_t));
4800}
4801
4802static void
4803put_stateid(struct nfsd4_compound_state *cstate, stateid_t *stateid)
4804{
4805 if (cstate->minorversion) {
4806 memcpy(&cstate->current_stateid, stateid, sizeof(stateid_t));
4807 SET_STATE_ID(cstate, CURRENT_STATE_ID_FLAG);
4808 }
4809}
4810
4811void
4812clear_current_stateid(struct nfsd4_compound_state *cstate)
4813{
4814 CLEAR_STATE_ID(cstate, CURRENT_STATE_ID_FLAG);
4815}
4816
4817/*
4818 * functions to set current state id
4819 */
4820void
4821nfsd4_set_opendowngradestateid(struct nfsd4_compound_state *cstate, struct nfsd4_open_downgrade *odp)
4822{
4823 put_stateid(cstate, &odp->od_stateid);
4824}
4825
4826void
4827nfsd4_set_openstateid(struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
4828{
4829 put_stateid(cstate, &open->op_stateid);
4830}
4831
4832void
4833nfsd4_set_closestateid(struct nfsd4_compound_state *cstate, struct nfsd4_close *close)
4834{
4835 put_stateid(cstate, &close->cl_stateid);
4836}
4837
4838void
4839nfsd4_set_lockstateid(struct nfsd4_compound_state *cstate, struct nfsd4_lock *lock)
4840{
4841 put_stateid(cstate, &lock->lk_resp_stateid);
4842}
4843
4844/*
4845 * functions to consume current state id
4846 */
4847
4848void
4849nfsd4_get_opendowngradestateid(struct nfsd4_compound_state *cstate, struct nfsd4_open_downgrade *odp)
4850{
4851 get_stateid(cstate, &odp->od_stateid);
4852}
4853
4854void
4855nfsd4_get_delegreturnstateid(struct nfsd4_compound_state *cstate, struct nfsd4_delegreturn *drp)
4856{
4857 get_stateid(cstate, &drp->dr_stateid);
4858}
4859
4860void
4861nfsd4_get_freestateid(struct nfsd4_compound_state *cstate, struct nfsd4_free_stateid *fsp)
4862{
4863 get_stateid(cstate, &fsp->fr_stateid);
4864}
4865
4866void
4867nfsd4_get_setattrstateid(struct nfsd4_compound_state *cstate, struct nfsd4_setattr *setattr)
4868{
4869 get_stateid(cstate, &setattr->sa_stateid);
4870}
4871
4872void
4873nfsd4_get_closestateid(struct nfsd4_compound_state *cstate, struct nfsd4_close *close)
4874{
4875 get_stateid(cstate, &close->cl_stateid);
4876}
4877
4878void
4879nfsd4_get_lockustateid(struct nfsd4_compound_state *cstate, struct nfsd4_locku *locku)
4880{
4881 get_stateid(cstate, &locku->lu_stateid);
4882}
4883
4884void
4885nfsd4_get_readstateid(struct nfsd4_compound_state *cstate, struct nfsd4_read *read)
4886{
4887 get_stateid(cstate, &read->rd_stateid);
4888}
4889
4890void
4891nfsd4_get_writestateid(struct nfsd4_compound_state *cstate, struct nfsd4_write *write)
4892{
4893 get_stateid(cstate, &write->wr_stateid);
4894}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 0ec5a1b9700e..bcd8904ab1e3 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -133,22 +133,6 @@ xdr_error: \
133 } \ 133 } \
134} while (0) 134} while (0)
135 135
136static void save_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep)
137{
138 savep->p = argp->p;
139 savep->end = argp->end;
140 savep->pagelen = argp->pagelen;
141 savep->pagelist = argp->pagelist;
142}
143
144static void restore_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep)
145{
146 argp->p = savep->p;
147 argp->end = savep->end;
148 argp->pagelen = savep->pagelen;
149 argp->pagelist = savep->pagelist;
150}
151
152static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) 136static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
153{ 137{
154 /* We want more bytes than seem to be available. 138 /* We want more bytes than seem to be available.
@@ -638,14 +622,18 @@ nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup
638 DECODE_TAIL; 622 DECODE_TAIL;
639} 623}
640 624
641static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *x) 625static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *share_access, u32 *deleg_want, u32 *deleg_when)
642{ 626{
643 __be32 *p; 627 __be32 *p;
644 u32 w; 628 u32 w;
645 629
646 READ_BUF(4); 630 READ_BUF(4);
647 READ32(w); 631 READ32(w);
648 *x = w; 632 *share_access = w & NFS4_SHARE_ACCESS_MASK;
633 *deleg_want = w & NFS4_SHARE_WANT_MASK;
634 if (deleg_when)
635 *deleg_when = w & NFS4_SHARE_WHEN_MASK;
636
649 switch (w & NFS4_SHARE_ACCESS_MASK) { 637 switch (w & NFS4_SHARE_ACCESS_MASK) {
650 case NFS4_SHARE_ACCESS_READ: 638 case NFS4_SHARE_ACCESS_READ:
651 case NFS4_SHARE_ACCESS_WRITE: 639 case NFS4_SHARE_ACCESS_WRITE:
@@ -673,6 +661,9 @@ static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *x)
673 w &= ~NFS4_SHARE_WANT_MASK; 661 w &= ~NFS4_SHARE_WANT_MASK;
674 if (!w) 662 if (!w)
675 return nfs_ok; 663 return nfs_ok;
664
665 if (!deleg_when) /* open_downgrade */
666 return nfserr_inval;
676 switch (w) { 667 switch (w) {
677 case NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL: 668 case NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL:
678 case NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED: 669 case NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED:
@@ -719,6 +710,7 @@ static __be32
719nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) 710nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
720{ 711{
721 DECODE_HEAD; 712 DECODE_HEAD;
713 u32 dummy;
722 714
723 memset(open->op_bmval, 0, sizeof(open->op_bmval)); 715 memset(open->op_bmval, 0, sizeof(open->op_bmval));
724 open->op_iattr.ia_valid = 0; 716 open->op_iattr.ia_valid = 0;
@@ -727,7 +719,9 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
727 /* seqid, share_access, share_deny, clientid, ownerlen */ 719 /* seqid, share_access, share_deny, clientid, ownerlen */
728 READ_BUF(4); 720 READ_BUF(4);
729 READ32(open->op_seqid); 721 READ32(open->op_seqid);
730 status = nfsd4_decode_share_access(argp, &open->op_share_access); 722 /* decode, yet ignore deleg_when until supported */
723 status = nfsd4_decode_share_access(argp, &open->op_share_access,
724 &open->op_deleg_want, &dummy);
731 if (status) 725 if (status)
732 goto xdr_error; 726 goto xdr_error;
733 status = nfsd4_decode_share_deny(argp, &open->op_share_deny); 727 status = nfsd4_decode_share_deny(argp, &open->op_share_deny);
@@ -755,14 +749,14 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
755 goto out; 749 goto out;
756 break; 750 break;
757 case NFS4_CREATE_EXCLUSIVE: 751 case NFS4_CREATE_EXCLUSIVE:
758 READ_BUF(8); 752 READ_BUF(NFS4_VERIFIER_SIZE);
759 COPYMEM(open->op_verf.data, 8); 753 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
760 break; 754 break;
761 case NFS4_CREATE_EXCLUSIVE4_1: 755 case NFS4_CREATE_EXCLUSIVE4_1:
762 if (argp->minorversion < 1) 756 if (argp->minorversion < 1)
763 goto xdr_error; 757 goto xdr_error;
764 READ_BUF(8); 758 READ_BUF(NFS4_VERIFIER_SIZE);
765 COPYMEM(open->op_verf.data, 8); 759 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
766 status = nfsd4_decode_fattr(argp, open->op_bmval, 760 status = nfsd4_decode_fattr(argp, open->op_bmval,
767 &open->op_iattr, &open->op_acl); 761 &open->op_iattr, &open->op_acl);
768 if (status) 762 if (status)
@@ -848,7 +842,8 @@ nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_d
848 return status; 842 return status;
849 READ_BUF(4); 843 READ_BUF(4);
850 READ32(open_down->od_seqid); 844 READ32(open_down->od_seqid);
851 status = nfsd4_decode_share_access(argp, &open_down->od_share_access); 845 status = nfsd4_decode_share_access(argp, &open_down->od_share_access,
846 &open_down->od_deleg_want, NULL);
852 if (status) 847 if (status)
853 return status; 848 return status;
854 status = nfsd4_decode_share_deny(argp, &open_down->od_share_deny); 849 status = nfsd4_decode_share_deny(argp, &open_down->od_share_deny);
@@ -994,8 +989,8 @@ nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclient
994{ 989{
995 DECODE_HEAD; 990 DECODE_HEAD;
996 991
997 READ_BUF(8); 992 READ_BUF(NFS4_VERIFIER_SIZE);
998 COPYMEM(setclientid->se_verf.data, 8); 993 COPYMEM(setclientid->se_verf.data, NFS4_VERIFIER_SIZE);
999 994
1000 status = nfsd4_decode_opaque(argp, &setclientid->se_name); 995 status = nfsd4_decode_opaque(argp, &setclientid->se_name);
1001 if (status) 996 if (status)
@@ -1020,9 +1015,9 @@ nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_s
1020{ 1015{
1021 DECODE_HEAD; 1016 DECODE_HEAD;
1022 1017
1023 READ_BUF(8 + sizeof(nfs4_verifier)); 1018 READ_BUF(8 + NFS4_VERIFIER_SIZE);
1024 COPYMEM(&scd_c->sc_clientid, 8); 1019 COPYMEM(&scd_c->sc_clientid, 8);
1025 COPYMEM(&scd_c->sc_confirm, sizeof(nfs4_verifier)); 1020 COPYMEM(&scd_c->sc_confirm, NFS4_VERIFIER_SIZE);
1026 1021
1027 DECODE_TAIL; 1022 DECODE_TAIL;
1028} 1023}
@@ -1385,26 +1380,29 @@ nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
1385static __be32 1380static __be32
1386nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid) 1381nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid)
1387{ 1382{
1388 unsigned int nbytes;
1389 stateid_t si;
1390 int i; 1383 int i;
1391 __be32 *p; 1384 __be32 *p, status;
1392 __be32 status; 1385 struct nfsd4_test_stateid_id *stateid;
1393 1386
1394 READ_BUF(4); 1387 READ_BUF(4);
1395 test_stateid->ts_num_ids = ntohl(*p++); 1388 test_stateid->ts_num_ids = ntohl(*p++);
1396 1389
1397 nbytes = test_stateid->ts_num_ids * sizeof(stateid_t); 1390 INIT_LIST_HEAD(&test_stateid->ts_stateid_list);
1398 if (nbytes > (u32)((char *)argp->end - (char *)argp->p))
1399 goto xdr_error;
1400
1401 test_stateid->ts_saved_args = argp;
1402 save_buf(argp, &test_stateid->ts_savedp);
1403 1391
1404 for (i = 0; i < test_stateid->ts_num_ids; i++) { 1392 for (i = 0; i < test_stateid->ts_num_ids; i++) {
1405 status = nfsd4_decode_stateid(argp, &si); 1393 stateid = kmalloc(sizeof(struct nfsd4_test_stateid_id), GFP_KERNEL);
1394 if (!stateid) {
1395 status = PTR_ERR(stateid);
1396 goto out;
1397 }
1398
1399 defer_free(argp, kfree, stateid);
1400 INIT_LIST_HEAD(&stateid->ts_id_list);
1401 list_add_tail(&stateid->ts_id_list, &test_stateid->ts_stateid_list);
1402
1403 status = nfsd4_decode_stateid(argp, &stateid->ts_id_stateid);
1406 if (status) 1404 if (status)
1407 return status; 1405 goto out;
1408 } 1406 }
1409 1407
1410 status = 0; 1408 status = 0;
@@ -2661,8 +2659,8 @@ nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
2661 __be32 *p; 2659 __be32 *p;
2662 2660
2663 if (!nfserr) { 2661 if (!nfserr) {
2664 RESERVE_SPACE(8); 2662 RESERVE_SPACE(NFS4_VERIFIER_SIZE);
2665 WRITEMEM(commit->co_verf.data, 8); 2663 WRITEMEM(commit->co_verf.data, NFS4_VERIFIER_SIZE);
2666 ADJUST_ARGS(); 2664 ADJUST_ARGS();
2667 } 2665 }
2668 return nfserr; 2666 return nfserr;
@@ -2851,6 +2849,20 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
2851 WRITE32(0); /* XXX: is NULL principal ok? */ 2849 WRITE32(0); /* XXX: is NULL principal ok? */
2852 ADJUST_ARGS(); 2850 ADJUST_ARGS();
2853 break; 2851 break;
2852 case NFS4_OPEN_DELEGATE_NONE_EXT: /* 4.1 */
2853 switch (open->op_why_no_deleg) {
2854 case WND4_CONTENTION:
2855 case WND4_RESOURCE:
2856 RESERVE_SPACE(8);
2857 WRITE32(open->op_why_no_deleg);
2858 WRITE32(0); /* deleg signaling not supported yet */
2859 break;
2860 default:
2861 RESERVE_SPACE(4);
2862 WRITE32(open->op_why_no_deleg);
2863 }
2864 ADJUST_ARGS();
2865 break;
2854 default: 2866 default:
2855 BUG(); 2867 BUG();
2856 } 2868 }
@@ -3008,7 +3020,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
3008 if (resp->xbuf->page_len) 3020 if (resp->xbuf->page_len)
3009 return nfserr_resource; 3021 return nfserr_resource;
3010 3022
3011 RESERVE_SPACE(8); /* verifier */ 3023 RESERVE_SPACE(NFS4_VERIFIER_SIZE);
3012 savep = p; 3024 savep = p;
3013 3025
3014 /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */ 3026 /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */
@@ -3209,9 +3221,9 @@ nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct n
3209 __be32 *p; 3221 __be32 *p;
3210 3222
3211 if (!nfserr) { 3223 if (!nfserr) {
3212 RESERVE_SPACE(8 + sizeof(nfs4_verifier)); 3224 RESERVE_SPACE(8 + NFS4_VERIFIER_SIZE);
3213 WRITEMEM(&scd->se_clientid, 8); 3225 WRITEMEM(&scd->se_clientid, 8);
3214 WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier)); 3226 WRITEMEM(&scd->se_confirm, NFS4_VERIFIER_SIZE);
3215 ADJUST_ARGS(); 3227 ADJUST_ARGS();
3216 } 3228 }
3217 else if (nfserr == nfserr_clid_inuse) { 3229 else if (nfserr == nfserr_clid_inuse) {
@@ -3232,7 +3244,7 @@ nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_w
3232 RESERVE_SPACE(16); 3244 RESERVE_SPACE(16);
3233 WRITE32(write->wr_bytes_written); 3245 WRITE32(write->wr_bytes_written);
3234 WRITE32(write->wr_how_written); 3246 WRITE32(write->wr_how_written);
3235 WRITEMEM(write->wr_verifier.data, 8); 3247 WRITEMEM(write->wr_verifier.data, NFS4_VERIFIER_SIZE);
3236 ADJUST_ARGS(); 3248 ADJUST_ARGS();
3237 } 3249 }
3238 return nfserr; 3250 return nfserr;
@@ -3391,30 +3403,17 @@ __be32
3391nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, int nfserr, 3403nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, int nfserr,
3392 struct nfsd4_test_stateid *test_stateid) 3404 struct nfsd4_test_stateid *test_stateid)
3393{ 3405{
3394 struct nfsd4_compoundargs *argp; 3406 struct nfsd4_test_stateid_id *stateid, *next;
3395 struct nfs4_client *cl = resp->cstate.session->se_client;
3396 stateid_t si;
3397 __be32 *p; 3407 __be32 *p;
3398 int i;
3399 int valid;
3400
3401 restore_buf(test_stateid->ts_saved_args, &test_stateid->ts_savedp);
3402 argp = test_stateid->ts_saved_args;
3403 3408
3404 RESERVE_SPACE(4); 3409 RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids));
3405 *p++ = htonl(test_stateid->ts_num_ids); 3410 *p++ = htonl(test_stateid->ts_num_ids);
3406 resp->p = p;
3407 3411
3408 nfs4_lock_state(); 3412 list_for_each_entry_safe(stateid, next, &test_stateid->ts_stateid_list, ts_id_list) {
3409 for (i = 0; i < test_stateid->ts_num_ids; i++) { 3413 *p++ = htonl(stateid->ts_id_status);
3410 nfsd4_decode_stateid(argp, &si);
3411 valid = nfs4_validate_stateid(cl, &si);
3412 RESERVE_SPACE(4);
3413 *p++ = htonl(valid);
3414 resp->p = p;
3415 } 3414 }
3416 nfs4_unlock_state();
3417 3415
3416 ADJUST_ARGS();
3418 return nfserr; 3417 return nfserr;
3419} 3418}
3420 3419
@@ -3532,7 +3531,7 @@ int nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 pad)
3532 if (length > session->se_fchannel.maxresp_sz) 3531 if (length > session->se_fchannel.maxresp_sz)
3533 return nfserr_rep_too_big; 3532 return nfserr_rep_too_big;
3534 3533
3535 if (slot->sl_cachethis == 1 && 3534 if ((slot->sl_flags & NFSD4_SLOT_CACHETHIS) &&
3536 length > session->se_fchannel.maxresp_cached) 3535 length > session->se_fchannel.maxresp_cached)
3537 return nfserr_rep_too_big_to_cache; 3536 return nfserr_rep_too_big_to_cache;
3538 3537
@@ -3656,8 +3655,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo
3656 if (nfsd4_has_session(cs)) { 3655 if (nfsd4_has_session(cs)) {
3657 if (cs->status != nfserr_replay_cache) { 3656 if (cs->status != nfserr_replay_cache) {
3658 nfsd4_store_cache_entry(resp); 3657 nfsd4_store_cache_entry(resp);
3659 dprintk("%s: SET SLOT STATE TO AVAILABLE\n", __func__); 3658 cs->slot->sl_flags &= ~NFSD4_SLOT_INUSE;
3660 cs->slot->sl_inuse = false;
3661 } 3659 }
3662 /* Renew the clientid on success and on replay */ 3660 /* Renew the clientid on success and on replay */
3663 release_session_client(cs->session); 3661 release_session_client(cs->session);
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 64c24af8d7ea..2c53be6d3579 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -13,12 +13,14 @@
13#include <linux/sunrpc/clnt.h> 13#include <linux/sunrpc/clnt.h>
14#include <linux/sunrpc/gss_api.h> 14#include <linux/sunrpc/gss_api.h>
15#include <linux/sunrpc/gss_krb5_enctypes.h> 15#include <linux/sunrpc/gss_krb5_enctypes.h>
16#include <linux/sunrpc/rpc_pipe_fs.h>
16#include <linux/module.h> 17#include <linux/module.h>
17 18
18#include "idmap.h" 19#include "idmap.h"
19#include "nfsd.h" 20#include "nfsd.h"
20#include "cache.h" 21#include "cache.h"
21#include "fault_inject.h" 22#include "fault_inject.h"
23#include "netns.h"
22 24
23/* 25/*
24 * We have a single directory with several nodes in it. 26 * We have a single directory with several nodes in it.
@@ -1124,14 +1126,26 @@ static int create_proc_exports_entry(void)
1124} 1126}
1125#endif 1127#endif
1126 1128
1129int nfsd_net_id;
1130static struct pernet_operations nfsd_net_ops = {
1131 .id = &nfsd_net_id,
1132 .size = sizeof(struct nfsd_net),
1133};
1134
1127static int __init init_nfsd(void) 1135static int __init init_nfsd(void)
1128{ 1136{
1129 int retval; 1137 int retval;
1130 printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n"); 1138 printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
1131 1139
1132 retval = nfsd4_init_slabs(); 1140 retval = register_cld_notifier();
1133 if (retval) 1141 if (retval)
1134 return retval; 1142 return retval;
1143 retval = register_pernet_subsys(&nfsd_net_ops);
1144 if (retval < 0)
1145 goto out_unregister_notifier;
1146 retval = nfsd4_init_slabs();
1147 if (retval)
1148 goto out_unregister_pernet;
1135 nfs4_state_init(); 1149 nfs4_state_init();
1136 retval = nfsd_fault_inject_init(); /* nfsd fault injection controls */ 1150 retval = nfsd_fault_inject_init(); /* nfsd fault injection controls */
1137 if (retval) 1151 if (retval)
@@ -1169,6 +1183,10 @@ out_free_stat:
1169 nfsd_fault_inject_cleanup(); 1183 nfsd_fault_inject_cleanup();
1170out_free_slabs: 1184out_free_slabs:
1171 nfsd4_free_slabs(); 1185 nfsd4_free_slabs();
1186out_unregister_pernet:
1187 unregister_pernet_subsys(&nfsd_net_ops);
1188out_unregister_notifier:
1189 unregister_cld_notifier();
1172 return retval; 1190 return retval;
1173} 1191}
1174 1192
@@ -1184,6 +1202,8 @@ static void __exit exit_nfsd(void)
1184 nfsd4_free_slabs(); 1202 nfsd4_free_slabs();
1185 nfsd_fault_inject_cleanup(); 1203 nfsd_fault_inject_cleanup();
1186 unregister_filesystem(&nfsd_fs_type); 1204 unregister_filesystem(&nfsd_fs_type);
1205 unregister_pernet_subsys(&nfsd_net_ops);
1206 unregister_cld_notifier();
1187} 1207}
1188 1208
1189MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>"); 1209MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 1d1e8589b4ce..1671429ffa66 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -364,12 +364,17 @@ static inline u32 nfsd_suppattrs2(u32 minorversion)
364 NFSD_WRITEABLE_ATTRS_WORD2 364 NFSD_WRITEABLE_ATTRS_WORD2
365 365
366extern int nfsd4_is_junction(struct dentry *dentry); 366extern int nfsd4_is_junction(struct dentry *dentry);
367#else 367extern int register_cld_notifier(void);
368extern void unregister_cld_notifier(void);
369#else /* CONFIG_NFSD_V4 */
368static inline int nfsd4_is_junction(struct dentry *dentry) 370static inline int nfsd4_is_junction(struct dentry *dentry)
369{ 371{
370 return 0; 372 return 0;
371} 373}
372 374
375#define register_cld_notifier() 0
376#define unregister_cld_notifier() do { } while(0)
377
373#endif /* CONFIG_NFSD_V4 */ 378#endif /* CONFIG_NFSD_V4 */
374 379
375#endif /* LINUX_NFSD_NFSD_H */ 380#endif /* LINUX_NFSD_NFSD_H */
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index fce472f5f39e..28dfad39f0c5 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -307,33 +307,37 @@ static void set_max_drc(void)
307 dprintk("%s nfsd_drc_max_mem %u \n", __func__, nfsd_drc_max_mem); 307 dprintk("%s nfsd_drc_max_mem %u \n", __func__, nfsd_drc_max_mem);
308} 308}
309 309
310int nfsd_create_serv(void) 310static int nfsd_get_default_max_blksize(void)
311{ 311{
312 int err = 0; 312 struct sysinfo i;
313 unsigned long long target;
314 unsigned long ret;
315
316 si_meminfo(&i);
317 target = (i.totalram - i.totalhigh) << PAGE_SHIFT;
318 /*
319 * Aim for 1/4096 of memory per thread This gives 1MB on 4Gig
320 * machines, but only uses 32K on 128M machines. Bottom out at
321 * 8K on 32M and smaller. Of course, this is only a default.
322 */
323 target >>= 12;
324
325 ret = NFSSVC_MAXBLKSIZE;
326 while (ret > target && ret >= 8*1024*2)
327 ret /= 2;
328 return ret;
329}
313 330
331int nfsd_create_serv(void)
332{
314 WARN_ON(!mutex_is_locked(&nfsd_mutex)); 333 WARN_ON(!mutex_is_locked(&nfsd_mutex));
315 if (nfsd_serv) { 334 if (nfsd_serv) {
316 svc_get(nfsd_serv); 335 svc_get(nfsd_serv);
317 return 0; 336 return 0;
318 } 337 }
319 if (nfsd_max_blksize == 0) { 338 if (nfsd_max_blksize == 0)
320 /* choose a suitable default */ 339 nfsd_max_blksize = nfsd_get_default_max_blksize();
321 struct sysinfo i;
322 si_meminfo(&i);
323 /* Aim for 1/4096 of memory per thread
324 * This gives 1MB on 4Gig machines
325 * But only uses 32K on 128M machines.
326 * Bottom out at 8K on 32M and smaller.
327 * Of course, this is only a default.
328 */
329 nfsd_max_blksize = NFSSVC_MAXBLKSIZE;
330 i.totalram <<= PAGE_SHIFT - 12;
331 while (nfsd_max_blksize > i.totalram &&
332 nfsd_max_blksize >= 8*1024*2)
333 nfsd_max_blksize /= 2;
334 }
335 nfsd_reset_versions(); 340 nfsd_reset_versions();
336
337 nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, 341 nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
338 nfsd_last_thread, nfsd, THIS_MODULE); 342 nfsd_last_thread, nfsd, THIS_MODULE);
339 if (nfsd_serv == NULL) 343 if (nfsd_serv == NULL)
@@ -341,7 +345,7 @@ int nfsd_create_serv(void)
341 345
342 set_max_drc(); 346 set_max_drc();
343 do_gettimeofday(&nfssvc_boot); /* record boot time */ 347 do_gettimeofday(&nfssvc_boot); /* record boot time */
344 return err; 348 return 0;
345} 349}
346 350
347int nfsd_nrpools(void) 351int nfsd_nrpools(void)
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index ffb5df1db94f..89ab137d379a 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -128,12 +128,14 @@ static inline struct nfs4_delegation *delegstateid(struct nfs4_stid *s)
128 (NFSD_CACHE_SIZE_SLOTS_PER_SESSION * NFSD_SLOT_CACHE_SIZE) 128 (NFSD_CACHE_SIZE_SLOTS_PER_SESSION * NFSD_SLOT_CACHE_SIZE)
129 129
130struct nfsd4_slot { 130struct nfsd4_slot {
131 bool sl_inuse;
132 bool sl_cachethis;
133 u16 sl_opcnt;
134 u32 sl_seqid; 131 u32 sl_seqid;
135 __be32 sl_status; 132 __be32 sl_status;
136 u32 sl_datalen; 133 u32 sl_datalen;
134 u16 sl_opcnt;
135#define NFSD4_SLOT_INUSE (1 << 0)
136#define NFSD4_SLOT_CACHETHIS (1 << 1)
137#define NFSD4_SLOT_INITIALIZED (1 << 2)
138 u8 sl_flags;
137 char sl_data[]; 139 char sl_data[];
138}; 140};
139 141
@@ -196,18 +198,7 @@ struct nfsd4_session {
196 struct nfsd4_slot *se_slots[]; /* forward channel slots */ 198 struct nfsd4_slot *se_slots[]; /* forward channel slots */
197}; 199};
198 200
199static inline void 201extern void nfsd4_put_session(struct nfsd4_session *ses);
200nfsd4_put_session(struct nfsd4_session *ses)
201{
202 extern void free_session(struct kref *kref);
203 kref_put(&ses->se_ref, free_session);
204}
205
206static inline void
207nfsd4_get_session(struct nfsd4_session *ses)
208{
209 kref_get(&ses->se_ref);
210}
211 202
212/* formatted contents of nfs4_sessionid */ 203/* formatted contents of nfs4_sessionid */
213struct nfsd4_sessionid { 204struct nfsd4_sessionid {
@@ -245,14 +236,17 @@ struct nfs4_client {
245 struct svc_cred cl_cred; /* setclientid principal */ 236 struct svc_cred cl_cred; /* setclientid principal */
246 clientid_t cl_clientid; /* generated by server */ 237 clientid_t cl_clientid; /* generated by server */
247 nfs4_verifier cl_confirm; /* generated by server */ 238 nfs4_verifier cl_confirm; /* generated by server */
248 u32 cl_firststate; /* recovery dir creation */
249 u32 cl_minorversion; 239 u32 cl_minorversion;
250 240
251 /* for v4.0 and v4.1 callbacks: */ 241 /* for v4.0 and v4.1 callbacks: */
252 struct nfs4_cb_conn cl_cb_conn; 242 struct nfs4_cb_conn cl_cb_conn;
253#define NFSD4_CLIENT_CB_UPDATE 1 243#define NFSD4_CLIENT_CB_UPDATE (0)
254#define NFSD4_CLIENT_KILL 2 244#define NFSD4_CLIENT_CB_KILL (1)
255 unsigned long cl_cb_flags; 245#define NFSD4_CLIENT_STABLE (2) /* client on stable storage */
246#define NFSD4_CLIENT_RECLAIM_COMPLETE (3) /* reclaim_complete done */
247#define NFSD4_CLIENT_CB_FLAG_MASK (1 << NFSD4_CLIENT_CB_UPDATE | \
248 1 << NFSD4_CLIENT_CB_KILL)
249 unsigned long cl_flags;
256 struct rpc_clnt *cl_cb_client; 250 struct rpc_clnt *cl_cb_client;
257 u32 cl_cb_ident; 251 u32 cl_cb_ident;
258#define NFSD4_CB_UP 0 252#define NFSD4_CB_UP 0
@@ -463,6 +457,8 @@ extern __be32 nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
463extern void nfs4_lock_state(void); 457extern void nfs4_lock_state(void);
464extern void nfs4_unlock_state(void); 458extern void nfs4_unlock_state(void);
465extern int nfs4_in_grace(void); 459extern int nfs4_in_grace(void);
460extern void nfs4_release_reclaim(void);
461extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp);
466extern __be32 nfs4_check_open_reclaim(clientid_t *clid); 462extern __be32 nfs4_check_open_reclaim(clientid_t *clid);
467extern void nfs4_free_openowner(struct nfs4_openowner *); 463extern void nfs4_free_openowner(struct nfs4_openowner *);
468extern void nfs4_free_lockowner(struct nfs4_lockowner *); 464extern void nfs4_free_lockowner(struct nfs4_lockowner *);
@@ -477,16 +473,17 @@ extern void nfsd4_destroy_callback_queue(void);
477extern void nfsd4_shutdown_callback(struct nfs4_client *); 473extern void nfsd4_shutdown_callback(struct nfs4_client *);
478extern void nfs4_put_delegation(struct nfs4_delegation *dp); 474extern void nfs4_put_delegation(struct nfs4_delegation *dp);
479extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname); 475extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
480extern void nfsd4_init_recdir(void);
481extern int nfsd4_recdir_load(void);
482extern void nfsd4_shutdown_recdir(void);
483extern int nfs4_client_to_reclaim(const char *name); 476extern int nfs4_client_to_reclaim(const char *name);
484extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id); 477extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id);
485extern void nfsd4_recdir_purge_old(void);
486extern void nfsd4_create_clid_dir(struct nfs4_client *clp);
487extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
488extern void release_session_client(struct nfsd4_session *); 478extern void release_session_client(struct nfsd4_session *);
489extern __be32 nfs4_validate_stateid(struct nfs4_client *, stateid_t *); 479extern __be32 nfs4_validate_stateid(struct nfs4_client *, stateid_t *);
490extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *); 480extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
491 481
482/* nfs4recover operations */
483extern int nfsd4_client_tracking_init(struct net *net);
484extern void nfsd4_client_tracking_exit(struct net *net);
485extern void nfsd4_client_record_create(struct nfs4_client *clp);
486extern void nfsd4_client_record_remove(struct nfs4_client *clp);
487extern int nfsd4_client_record_check(struct nfs4_client *clp);
488extern void nfsd4_record_grace_done(struct net *net, time_t boot_time);
492#endif /* NFSD4_STATE_H */ 489#endif /* NFSD4_STATE_H */
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index e59f71d0cf73..296d671654d6 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -737,12 +737,13 @@ static int nfsd_open_break_lease(struct inode *inode, int access)
737 737
738/* 738/*
739 * Open an existing file or directory. 739 * Open an existing file or directory.
740 * The access argument indicates the type of open (read/write/lock) 740 * The may_flags argument indicates the type of open (read/write/lock)
741 * and additional flags.
741 * N.B. After this call fhp needs an fh_put 742 * N.B. After this call fhp needs an fh_put
742 */ 743 */
743__be32 744__be32
744nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, 745nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
745 int access, struct file **filp) 746 int may_flags, struct file **filp)
746{ 747{
747 struct dentry *dentry; 748 struct dentry *dentry;
748 struct inode *inode; 749 struct inode *inode;
@@ -757,7 +758,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
757 * and (hopefully) checked permission - so allow OWNER_OVERRIDE 758 * and (hopefully) checked permission - so allow OWNER_OVERRIDE
758 * in case a chmod has now revoked permission. 759 * in case a chmod has now revoked permission.
759 */ 760 */
760 err = fh_verify(rqstp, fhp, type, access | NFSD_MAY_OWNER_OVERRIDE); 761 err = fh_verify(rqstp, fhp, type, may_flags | NFSD_MAY_OWNER_OVERRIDE);
761 if (err) 762 if (err)
762 goto out; 763 goto out;
763 764
@@ -768,7 +769,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
768 * or any access when mandatory locking enabled 769 * or any access when mandatory locking enabled
769 */ 770 */
770 err = nfserr_perm; 771 err = nfserr_perm;
771 if (IS_APPEND(inode) && (access & NFSD_MAY_WRITE)) 772 if (IS_APPEND(inode) && (may_flags & NFSD_MAY_WRITE))
772 goto out; 773 goto out;
773 /* 774 /*
774 * We must ignore files (but only files) which might have mandatory 775 * We must ignore files (but only files) which might have mandatory
@@ -781,12 +782,12 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
781 if (!inode->i_fop) 782 if (!inode->i_fop)
782 goto out; 783 goto out;
783 784
784 host_err = nfsd_open_break_lease(inode, access); 785 host_err = nfsd_open_break_lease(inode, may_flags);
785 if (host_err) /* NOMEM or WOULDBLOCK */ 786 if (host_err) /* NOMEM or WOULDBLOCK */
786 goto out_nfserr; 787 goto out_nfserr;
787 788
788 if (access & NFSD_MAY_WRITE) { 789 if (may_flags & NFSD_MAY_WRITE) {
789 if (access & NFSD_MAY_READ) 790 if (may_flags & NFSD_MAY_READ)
790 flags = O_RDWR|O_LARGEFILE; 791 flags = O_RDWR|O_LARGEFILE;
791 else 792 else
792 flags = O_WRONLY|O_LARGEFILE; 793 flags = O_WRONLY|O_LARGEFILE;
@@ -795,8 +796,15 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
795 flags, current_cred()); 796 flags, current_cred());
796 if (IS_ERR(*filp)) 797 if (IS_ERR(*filp))
797 host_err = PTR_ERR(*filp); 798 host_err = PTR_ERR(*filp);
798 else 799 else {
799 host_err = ima_file_check(*filp, access); 800 host_err = ima_file_check(*filp, may_flags);
801
802 if (may_flags & NFSD_MAY_64BIT_COOKIE)
803 (*filp)->f_mode |= FMODE_64BITHASH;
804 else
805 (*filp)->f_mode |= FMODE_32BITHASH;
806 }
807
800out_nfserr: 808out_nfserr:
801 err = nfserrno(host_err); 809 err = nfserrno(host_err);
802out: 810out:
@@ -2021,8 +2029,13 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
2021 __be32 err; 2029 __be32 err;
2022 struct file *file; 2030 struct file *file;
2023 loff_t offset = *offsetp; 2031 loff_t offset = *offsetp;
2032 int may_flags = NFSD_MAY_READ;
2033
2034 /* NFSv2 only supports 32 bit cookies */
2035 if (rqstp->rq_vers > 2)
2036 may_flags |= NFSD_MAY_64BIT_COOKIE;
2024 2037
2025 err = nfsd_open(rqstp, fhp, S_IFDIR, NFSD_MAY_READ, &file); 2038 err = nfsd_open(rqstp, fhp, S_IFDIR, may_flags, &file);
2026 if (err) 2039 if (err)
2027 goto out; 2040 goto out;
2028 2041
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index 1dcd238e11a0..ec0611b2b738 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -27,6 +27,8 @@
27#define NFSD_MAY_BYPASS_GSS 0x400 27#define NFSD_MAY_BYPASS_GSS 0x400
28#define NFSD_MAY_READ_IF_EXEC 0x800 28#define NFSD_MAY_READ_IF_EXEC 0x800
29 29
30#define NFSD_MAY_64BIT_COOKIE 0x1000 /* 64 bit readdir cookies for >= NFSv3 */
31
30#define NFSD_MAY_CREATE (NFSD_MAY_EXEC|NFSD_MAY_WRITE) 32#define NFSD_MAY_CREATE (NFSD_MAY_EXEC|NFSD_MAY_WRITE)
31#define NFSD_MAY_REMOVE (NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC) 33#define NFSD_MAY_REMOVE (NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC)
32 34
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 2364747ee97d..1b3501598ab5 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -43,6 +43,13 @@
43#define NFSD4_MAX_TAGLEN 128 43#define NFSD4_MAX_TAGLEN 128
44#define XDR_LEN(n) (((n) + 3) & ~3) 44#define XDR_LEN(n) (((n) + 3) & ~3)
45 45
46#define CURRENT_STATE_ID_FLAG (1<<0)
47#define SAVED_STATE_ID_FLAG (1<<1)
48
49#define SET_STATE_ID(c, f) ((c)->sid_flags |= (f))
50#define HAS_STATE_ID(c, f) ((c)->sid_flags & (f))
51#define CLEAR_STATE_ID(c, f) ((c)->sid_flags &= ~(f))
52
46struct nfsd4_compound_state { 53struct nfsd4_compound_state {
47 struct svc_fh current_fh; 54 struct svc_fh current_fh;
48 struct svc_fh save_fh; 55 struct svc_fh save_fh;
@@ -54,6 +61,10 @@ struct nfsd4_compound_state {
54 size_t iovlen; 61 size_t iovlen;
55 u32 minorversion; 62 u32 minorversion;
56 u32 status; 63 u32 status;
64 stateid_t current_stateid;
65 stateid_t save_stateid;
66 /* to indicate current and saved state id presents */
67 u32 sid_flags;
57}; 68};
58 69
59static inline bool nfsd4_has_session(struct nfsd4_compound_state *cs) 70static inline bool nfsd4_has_session(struct nfsd4_compound_state *cs)
@@ -212,16 +223,19 @@ struct nfsd4_open {
212 struct xdr_netobj op_fname; /* request - everything but CLAIM_PREV */ 223 struct xdr_netobj op_fname; /* request - everything but CLAIM_PREV */
213 u32 op_delegate_type; /* request - CLAIM_PREV only */ 224 u32 op_delegate_type; /* request - CLAIM_PREV only */
214 stateid_t op_delegate_stateid; /* request - response */ 225 stateid_t op_delegate_stateid; /* request - response */
226 u32 op_why_no_deleg; /* response - DELEG_NONE_EXT only */
215 u32 op_create; /* request */ 227 u32 op_create; /* request */
216 u32 op_createmode; /* request */ 228 u32 op_createmode; /* request */
217 u32 op_bmval[3]; /* request */ 229 u32 op_bmval[3]; /* request */
218 struct iattr iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */ 230 struct iattr iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */
219 nfs4_verifier verf; /* EXCLUSIVE4 */ 231 nfs4_verifier op_verf __attribute__((aligned(32)));
232 /* EXCLUSIVE4 */
220 clientid_t op_clientid; /* request */ 233 clientid_t op_clientid; /* request */
221 struct xdr_netobj op_owner; /* request */ 234 struct xdr_netobj op_owner; /* request */
222 u32 op_seqid; /* request */ 235 u32 op_seqid; /* request */
223 u32 op_share_access; /* request */ 236 u32 op_share_access; /* request */
224 u32 op_share_deny; /* request */ 237 u32 op_share_deny; /* request */
238 u32 op_deleg_want; /* request */
225 stateid_t op_stateid; /* response */ 239 stateid_t op_stateid; /* response */
226 u32 op_recall; /* recall */ 240 u32 op_recall; /* recall */
227 struct nfsd4_change_info op_cinfo; /* response */ 241 struct nfsd4_change_info op_cinfo; /* response */
@@ -234,7 +248,6 @@ struct nfsd4_open {
234 struct nfs4_acl *op_acl; 248 struct nfs4_acl *op_acl;
235}; 249};
236#define op_iattr iattr 250#define op_iattr iattr
237#define op_verf verf
238 251
239struct nfsd4_open_confirm { 252struct nfsd4_open_confirm {
240 stateid_t oc_req_stateid /* request */; 253 stateid_t oc_req_stateid /* request */;
@@ -245,8 +258,9 @@ struct nfsd4_open_confirm {
245struct nfsd4_open_downgrade { 258struct nfsd4_open_downgrade {
246 stateid_t od_stateid; 259 stateid_t od_stateid;
247 u32 od_seqid; 260 u32 od_seqid;
248 u32 od_share_access; 261 u32 od_share_access; /* request */
249 u32 od_share_deny; 262 u32 od_deleg_want; /* request */
263 u32 od_share_deny; /* request */
250}; 264};
251 265
252 266
@@ -343,10 +357,15 @@ struct nfsd4_saved_compoundargs {
343 struct page **pagelist; 357 struct page **pagelist;
344}; 358};
345 359
360struct nfsd4_test_stateid_id {
361 __be32 ts_id_status;
362 stateid_t ts_id_stateid;
363 struct list_head ts_id_list;
364};
365
346struct nfsd4_test_stateid { 366struct nfsd4_test_stateid {
347 __be32 ts_num_ids; 367 __be32 ts_num_ids;
348 struct nfsd4_compoundargs *ts_saved_args; 368 struct list_head ts_stateid_list;
349 struct nfsd4_saved_compoundargs ts_savedp;
350}; 369};
351 370
352struct nfsd4_free_stateid { 371struct nfsd4_free_stateid {
@@ -503,7 +522,8 @@ static inline bool nfsd4_is_solo_sequence(struct nfsd4_compoundres *resp)
503 522
504static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp) 523static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp)
505{ 524{
506 return !resp->cstate.slot->sl_cachethis || nfsd4_is_solo_sequence(resp); 525 return !(resp->cstate.slot->sl_flags & NFSD4_SLOT_CACHETHIS)
526 || nfsd4_is_solo_sequence(resp);
507} 527}
508 528
509#define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs) 529#define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs)