aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-29 17:53:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-29 17:53:25 -0400
commit71db34fc4330f7c784397acb9f1e6ee7f7b32eb2 (patch)
tree77dd08f6f778a799dcd0c48eb72d0742349df235
parent50483c3268918ee51a56d1baa39b9149d2d0d521 (diff)
parent797a9d797f8483bb67f265c761b76dcd5a077a23 (diff)
Merge branch 'for-3.4' of git://linux-nfs.org/~bfields/linux
Pull nfsd changes from Bruce Fields: Highlights: - Benny Halevy and Tigran Mkrtchyan implemented some more 4.1 features, moving us closer to a complete 4.1 implementation. - Bernd Schubert fixed a long-standing problem with readdir cookies on ext2/3/4. - Jeff Layton performed a long-overdue overhaul of the server reboot recovery code which will allow us to deprecate the current code (a rather unusual user of the vfs), and give us some needed flexibility for further improvements. - Like the client, we now support numeric uid's and gid's in the auth_sys case, allowing easier upgrades from NFSv2/v3 to v4.x. Plus miscellaneous bugfixes and cleanup. Thanks to everyone! There are also some delegation fixes waiting on vfs review that I suppose will have to wait for 3.5. With that done I think we'll finally turn off the "EXPERIMENTAL" dependency for v4 (though that's mostly symbolic as it's been on by default in distro's for a while). And the list of 4.1 todo's should be achievable for 3.5 as well: http://wiki.linux-nfs.org/wiki/index.php/Server_4.0_and_4.1_issues though we may still want a bit more experience with it before turning it on by default. * 'for-3.4' of git://linux-nfs.org/~bfields/linux: (55 commits) nfsd: only register cld pipe notifier when CONFIG_NFSD_V4 is enabled nfsd4: use auth_unix unconditionally on backchannel nfsd: fix NULL pointer dereference in cld_pipe_downcall nfsd4: memory corruption in numeric_name_to_id() sunrpc: skip portmap calls on sessions backchannel nfsd4: allow numeric idmapping nfsd: don't allow legacy client tracker init for anything but init_net nfsd: add notifier to handle mount/unmount of rpc_pipefs sb nfsd: add the infrastructure to handle the cld upcall nfsd: add a header describing upcall to nfsdcld nfsd: add a per-net-namespace struct for nfsd sunrpc: create nfsd dir in rpc_pipefs nfsd: add nfsd4_client_tracking_ops struct and a way to set it nfsd: convert nfs4_client->cl_cb_flags to a generic flags field NFSD: Fix nfs4_verifier memory alignment NFSD: Fix warnings when NFSD_DEBUG is not defined nfsd: vfs_llseek() with 32 or 64 bit offsets (hashes) nfsd: rename 'int access' to 'int may_flags' in nfsd_open() ext4: return 32/64-bit dir name hash according to usage type fs: add new FMODE flags: FMODE_32bithash and FMODE_64bithash ...
-rw-r--r--Documentation/kernel-parameters.txt6
-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
-rw-r--r--include/linux/fs.h4
-rw-r--r--include/linux/nfs4.h15
-rw-r--r--include/linux/nfsd/cld.h56
-rw-r--r--include/linux/sunrpc/svc_rdma.h4
-rw-r--r--net/sunrpc/cache.c2
-rw-r--r--net/sunrpc/rpc_pipe.c5
-rw-r--r--net/sunrpc/svcauth_unix.c2
-rw-r--r--net/sunrpc/svcsock.c2
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma.c1
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_marshal.c66
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c20
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_sendto.c26
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_transport.c10
-rw-r--r--net/sunrpc/xprtrdma/xprt_rdma.h7
-rw-r--r--net/sunrpc/xprtsock.c1
36 files changed, 1629 insertions, 411 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index e2f8c297a8a4..c1601e5a8b71 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1699,6 +1699,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
1699 The default is to send the implementation identification 1699 The default is to send the implementation identification
1700 information. 1700 information.
1701 1701
1702 nfsd.nfs4_disable_idmapping=
1703 [NFSv4] When set to the default of '1', the NFSv4
1704 server will return only numeric uids and gids to
1705 clients using auth_sys, and will accept numeric uids
1706 and gids from such clients. This is intended to ease
1707 migration from NFSv2/v3.
1702 1708
1703 objlayoutdriver.osd_login_prog= 1709 objlayoutdriver.osd_login_prog=
1704 [NFS] [OBJLAYOUT] sets the pathname to the program which 1710 [NFS] [OBJLAYOUT] sets the pathname to the program which
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)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index c437f914d537..135693e79f2b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -92,6 +92,10 @@ struct inodes_stat_t {
92/* File is opened using open(.., 3, ..) and is writeable only for ioctls 92/* File is opened using open(.., 3, ..) and is writeable only for ioctls
93 (specialy hack for floppy.c) */ 93 (specialy hack for floppy.c) */
94#define FMODE_WRITE_IOCTL ((__force fmode_t)0x100) 94#define FMODE_WRITE_IOCTL ((__force fmode_t)0x100)
95/* 32bit hashes as llseek() offset (for directories) */
96#define FMODE_32BITHASH ((__force fmode_t)0x200)
97/* 64bit hashes as llseek() offset (for directories) */
98#define FMODE_64BITHASH ((__force fmode_t)0x400)
95 99
96/* 100/*
97 * Don't update ctime and mtime. 101 * Don't update ctime and mtime.
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 834df8bf08b6..0987146b0637 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -438,7 +438,20 @@ enum limit_by4 {
438enum open_delegation_type4 { 438enum open_delegation_type4 {
439 NFS4_OPEN_DELEGATE_NONE = 0, 439 NFS4_OPEN_DELEGATE_NONE = 0,
440 NFS4_OPEN_DELEGATE_READ = 1, 440 NFS4_OPEN_DELEGATE_READ = 1,
441 NFS4_OPEN_DELEGATE_WRITE = 2 441 NFS4_OPEN_DELEGATE_WRITE = 2,
442 NFS4_OPEN_DELEGATE_NONE_EXT = 3, /* 4.1 */
443};
444
445enum why_no_delegation4 { /* new to v4.1 */
446 WND4_NOT_WANTED = 0,
447 WND4_CONTENTION = 1,
448 WND4_RESOURCE = 2,
449 WND4_NOT_SUPP_FTYPE = 3,
450 WND4_WRITE_DELEG_NOT_SUPP_FTYPE = 4,
451 WND4_NOT_SUPP_UPGRADE = 5,
452 WND4_NOT_SUPP_DOWNGRADE = 6,
453 WND4_CANCELLED = 7,
454 WND4_IS_DIR = 8,
442}; 455};
443 456
444enum lock_type4 { 457enum lock_type4 {
diff --git a/include/linux/nfsd/cld.h b/include/linux/nfsd/cld.h
new file mode 100644
index 000000000000..f14a9ab06f1f
--- /dev/null
+++ b/include/linux/nfsd/cld.h
@@ -0,0 +1,56 @@
1/*
2 * Upcall description for nfsdcld communication
3 *
4 * Copyright (c) 2012 Red Hat, Inc.
5 * Author(s): Jeff Layton <jlayton@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#ifndef _NFSD_CLD_H
23#define _NFSD_CLD_H
24
25/* latest upcall version available */
26#define CLD_UPCALL_VERSION 1
27
28/* defined by RFC3530 */
29#define NFS4_OPAQUE_LIMIT 1024
30
31enum cld_command {
32 Cld_Create, /* create a record for this cm_id */
33 Cld_Remove, /* remove record of this cm_id */
34 Cld_Check, /* is this cm_id allowed? */
35 Cld_GraceDone, /* grace period is complete */
36};
37
38/* representation of long-form NFSv4 client ID */
39struct cld_name {
40 uint16_t cn_len; /* length of cm_id */
41 unsigned char cn_id[NFS4_OPAQUE_LIMIT]; /* client-provided */
42} __attribute__((packed));
43
44/* message struct for communication with userspace */
45struct cld_msg {
46 uint8_t cm_vers; /* upcall version */
47 uint8_t cm_cmd; /* upcall command */
48 int16_t cm_status; /* return code */
49 uint32_t cm_xid; /* transaction id */
50 union {
51 int64_t cm_gracetime; /* grace period start time */
52 struct cld_name cm_name;
53 } __attribute__((packed)) cm_u;
54} __attribute__((packed));
55
56#endif /* !_NFSD_CLD_H */
diff --git a/include/linux/sunrpc/svc_rdma.h b/include/linux/sunrpc/svc_rdma.h
index c14fe86dac59..0b8e3e6bdacf 100644
--- a/include/linux/sunrpc/svc_rdma.h
+++ b/include/linux/sunrpc/svc_rdma.h
@@ -190,7 +190,7 @@ extern int svc_rdma_xdr_encode_error(struct svcxprt_rdma *,
190extern void svc_rdma_xdr_encode_write_list(struct rpcrdma_msg *, int); 190extern void svc_rdma_xdr_encode_write_list(struct rpcrdma_msg *, int);
191extern void svc_rdma_xdr_encode_reply_array(struct rpcrdma_write_array *, int); 191extern void svc_rdma_xdr_encode_reply_array(struct rpcrdma_write_array *, int);
192extern void svc_rdma_xdr_encode_array_chunk(struct rpcrdma_write_array *, int, 192extern void svc_rdma_xdr_encode_array_chunk(struct rpcrdma_write_array *, int,
193 u32, u64, u32); 193 __be32, __be64, u32);
194extern void svc_rdma_xdr_encode_reply_header(struct svcxprt_rdma *, 194extern void svc_rdma_xdr_encode_reply_header(struct svcxprt_rdma *,
195 struct rpcrdma_msg *, 195 struct rpcrdma_msg *,
196 struct rpcrdma_msg *, 196 struct rpcrdma_msg *,
@@ -292,7 +292,7 @@ svc_rdma_get_reply_array(struct rpcrdma_msg *rmsgp)
292 if (wr_ary) { 292 if (wr_ary) {
293 rp_ary = (struct rpcrdma_write_array *) 293 rp_ary = (struct rpcrdma_write_array *)
294 &wr_ary-> 294 &wr_ary->
295 wc_array[wr_ary->wc_nchunks].wc_target.rs_length; 295 wc_array[ntohl(wr_ary->wc_nchunks)].wc_target.rs_length;
296 296
297 goto found_it; 297 goto found_it;
298 } 298 }
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index f21ece088764..de0b0f39d9d8 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -830,6 +830,8 @@ static ssize_t cache_do_downcall(char *kaddr, const char __user *buf,
830{ 830{
831 ssize_t ret; 831 ssize_t ret;
832 832
833 if (count == 0)
834 return -EINVAL;
833 if (copy_from_user(kaddr, buf, count)) 835 if (copy_from_user(kaddr, buf, count))
834 return -EFAULT; 836 return -EFAULT;
835 kaddr[count] = '\0'; 837 kaddr[count] = '\0';
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index c84c0e0c41cb..0af37fc46818 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -1014,6 +1014,7 @@ enum {
1014 RPCAUTH_statd, 1014 RPCAUTH_statd,
1015 RPCAUTH_nfsd4_cb, 1015 RPCAUTH_nfsd4_cb,
1016 RPCAUTH_cache, 1016 RPCAUTH_cache,
1017 RPCAUTH_nfsd,
1017 RPCAUTH_RootEOF 1018 RPCAUTH_RootEOF
1018}; 1019};
1019 1020
@@ -1046,6 +1047,10 @@ static const struct rpc_filelist files[] = {
1046 .name = "cache", 1047 .name = "cache",
1047 .mode = S_IFDIR | S_IRUGO | S_IXUGO, 1048 .mode = S_IFDIR | S_IRUGO | S_IXUGO,
1048 }, 1049 },
1050 [RPCAUTH_nfsd] = {
1051 .name = "nfsd",
1052 .mode = S_IFDIR | S_IRUGO | S_IXUGO,
1053 },
1049}; 1054};
1050 1055
1051/* 1056/*
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index bcd574f2ac56..521d8f7dc833 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -507,7 +507,7 @@ static int unix_gid_parse(struct cache_detail *cd,
507 time_t expiry; 507 time_t expiry;
508 struct unix_gid ug, *ugp; 508 struct unix_gid ug, *ugp;
509 509
510 if (mlen <= 0 || mesg[mlen-1] != '\n') 510 if (mesg[mlen - 1] != '\n')
511 return -EINVAL; 511 return -EINVAL;
512 mesg[mlen-1] = 0; 512 mesg[mlen-1] = 0;
513 513
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 40ae884db865..824d32fb3121 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1381,8 +1381,6 @@ void svc_sock_update_bufs(struct svc_serv *serv)
1381 spin_lock_bh(&serv->sv_lock); 1381 spin_lock_bh(&serv->sv_lock);
1382 list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) 1382 list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list)
1383 set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); 1383 set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags);
1384 list_for_each_entry(svsk, &serv->sv_tempsocks, sk_xprt.xpt_list)
1385 set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags);
1386 spin_unlock_bh(&serv->sv_lock); 1384 spin_unlock_bh(&serv->sv_lock);
1387} 1385}
1388EXPORT_SYMBOL_GPL(svc_sock_update_bufs); 1386EXPORT_SYMBOL_GPL(svc_sock_update_bufs);
diff --git a/net/sunrpc/xprtrdma/svc_rdma.c b/net/sunrpc/xprtrdma/svc_rdma.c
index 09af4fab1a45..8343737e85f4 100644
--- a/net/sunrpc/xprtrdma/svc_rdma.c
+++ b/net/sunrpc/xprtrdma/svc_rdma.c
@@ -47,6 +47,7 @@
47#include <linux/sunrpc/clnt.h> 47#include <linux/sunrpc/clnt.h>
48#include <linux/sunrpc/sched.h> 48#include <linux/sunrpc/sched.h>
49#include <linux/sunrpc/svc_rdma.h> 49#include <linux/sunrpc/svc_rdma.h>
50#include "xprt_rdma.h"
50 51
51#define RPCDBG_FACILITY RPCDBG_SVCXPRT 52#define RPCDBG_FACILITY RPCDBG_SVCXPRT
52 53
diff --git a/net/sunrpc/xprtrdma/svc_rdma_marshal.c b/net/sunrpc/xprtrdma/svc_rdma_marshal.c
index 9530ef2d40dc..8d2edddf48cf 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_marshal.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_marshal.c
@@ -60,21 +60,11 @@ static u32 *decode_read_list(u32 *va, u32 *vaend)
60 struct rpcrdma_read_chunk *ch = (struct rpcrdma_read_chunk *)va; 60 struct rpcrdma_read_chunk *ch = (struct rpcrdma_read_chunk *)va;
61 61
62 while (ch->rc_discrim != xdr_zero) { 62 while (ch->rc_discrim != xdr_zero) {
63 u64 ch_offset;
64
65 if (((unsigned long)ch + sizeof(struct rpcrdma_read_chunk)) > 63 if (((unsigned long)ch + sizeof(struct rpcrdma_read_chunk)) >
66 (unsigned long)vaend) { 64 (unsigned long)vaend) {
67 dprintk("svcrdma: vaend=%p, ch=%p\n", vaend, ch); 65 dprintk("svcrdma: vaend=%p, ch=%p\n", vaend, ch);
68 return NULL; 66 return NULL;
69 } 67 }
70
71 ch->rc_discrim = ntohl(ch->rc_discrim);
72 ch->rc_position = ntohl(ch->rc_position);
73 ch->rc_target.rs_handle = ntohl(ch->rc_target.rs_handle);
74 ch->rc_target.rs_length = ntohl(ch->rc_target.rs_length);
75 va = (u32 *)&ch->rc_target.rs_offset;
76 xdr_decode_hyper(va, &ch_offset);
77 put_unaligned(ch_offset, (u64 *)va);
78 ch++; 68 ch++;
79 } 69 }
80 return (u32 *)&ch->rc_position; 70 return (u32 *)&ch->rc_position;
@@ -91,7 +81,7 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch,
91 *byte_count = 0; 81 *byte_count = 0;
92 *ch_count = 0; 82 *ch_count = 0;
93 for (; ch->rc_discrim != 0; ch++) { 83 for (; ch->rc_discrim != 0; ch++) {
94 *byte_count = *byte_count + ch->rc_target.rs_length; 84 *byte_count = *byte_count + ntohl(ch->rc_target.rs_length);
95 *ch_count = *ch_count + 1; 85 *ch_count = *ch_count + 1;
96 } 86 }
97} 87}
@@ -108,7 +98,8 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch,
108 */ 98 */
109static u32 *decode_write_list(u32 *va, u32 *vaend) 99static u32 *decode_write_list(u32 *va, u32 *vaend)
110{ 100{
111 int ch_no; 101 int nchunks;
102
112 struct rpcrdma_write_array *ary = 103 struct rpcrdma_write_array *ary =
113 (struct rpcrdma_write_array *)va; 104 (struct rpcrdma_write_array *)va;
114 105
@@ -121,37 +112,24 @@ static u32 *decode_write_list(u32 *va, u32 *vaend)
121 dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend); 112 dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend);
122 return NULL; 113 return NULL;
123 } 114 }
124 ary->wc_discrim = ntohl(ary->wc_discrim); 115 nchunks = ntohl(ary->wc_nchunks);
125 ary->wc_nchunks = ntohl(ary->wc_nchunks);
126 if (((unsigned long)&ary->wc_array[0] + 116 if (((unsigned long)&ary->wc_array[0] +
127 (sizeof(struct rpcrdma_write_chunk) * ary->wc_nchunks)) > 117 (sizeof(struct rpcrdma_write_chunk) * nchunks)) >
128 (unsigned long)vaend) { 118 (unsigned long)vaend) {
129 dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", 119 dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n",
130 ary, ary->wc_nchunks, vaend); 120 ary, nchunks, vaend);
131 return NULL; 121 return NULL;
132 } 122 }
133 for (ch_no = 0; ch_no < ary->wc_nchunks; ch_no++) {
134 u64 ch_offset;
135
136 ary->wc_array[ch_no].wc_target.rs_handle =
137 ntohl(ary->wc_array[ch_no].wc_target.rs_handle);
138 ary->wc_array[ch_no].wc_target.rs_length =
139 ntohl(ary->wc_array[ch_no].wc_target.rs_length);
140 va = (u32 *)&ary->wc_array[ch_no].wc_target.rs_offset;
141 xdr_decode_hyper(va, &ch_offset);
142 put_unaligned(ch_offset, (u64 *)va);
143 }
144
145 /* 123 /*
146 * rs_length is the 2nd 4B field in wc_target and taking its 124 * rs_length is the 2nd 4B field in wc_target and taking its
147 * address skips the list terminator 125 * address skips the list terminator
148 */ 126 */
149 return (u32 *)&ary->wc_array[ch_no].wc_target.rs_length; 127 return (u32 *)&ary->wc_array[nchunks].wc_target.rs_length;
150} 128}
151 129
152static u32 *decode_reply_array(u32 *va, u32 *vaend) 130static u32 *decode_reply_array(u32 *va, u32 *vaend)
153{ 131{
154 int ch_no; 132 int nchunks;
155 struct rpcrdma_write_array *ary = 133 struct rpcrdma_write_array *ary =
156 (struct rpcrdma_write_array *)va; 134 (struct rpcrdma_write_array *)va;
157 135
@@ -164,28 +142,15 @@ static u32 *decode_reply_array(u32 *va, u32 *vaend)
164 dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend); 142 dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend);
165 return NULL; 143 return NULL;
166 } 144 }
167 ary->wc_discrim = ntohl(ary->wc_discrim); 145 nchunks = ntohl(ary->wc_nchunks);
168 ary->wc_nchunks = ntohl(ary->wc_nchunks);
169 if (((unsigned long)&ary->wc_array[0] + 146 if (((unsigned long)&ary->wc_array[0] +
170 (sizeof(struct rpcrdma_write_chunk) * ary->wc_nchunks)) > 147 (sizeof(struct rpcrdma_write_chunk) * nchunks)) >
171 (unsigned long)vaend) { 148 (unsigned long)vaend) {
172 dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", 149 dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n",
173 ary, ary->wc_nchunks, vaend); 150 ary, nchunks, vaend);
174 return NULL; 151 return NULL;
175 } 152 }
176 for (ch_no = 0; ch_no < ary->wc_nchunks; ch_no++) { 153 return (u32 *)&ary->wc_array[nchunks];
177 u64 ch_offset;
178
179 ary->wc_array[ch_no].wc_target.rs_handle =
180 ntohl(ary->wc_array[ch_no].wc_target.rs_handle);
181 ary->wc_array[ch_no].wc_target.rs_length =
182 ntohl(ary->wc_array[ch_no].wc_target.rs_length);
183 va = (u32 *)&ary->wc_array[ch_no].wc_target.rs_offset;
184 xdr_decode_hyper(va, &ch_offset);
185 put_unaligned(ch_offset, (u64 *)va);
186 }
187
188 return (u32 *)&ary->wc_array[ch_no];
189} 154}
190 155
191int svc_rdma_xdr_decode_req(struct rpcrdma_msg **rdma_req, 156int svc_rdma_xdr_decode_req(struct rpcrdma_msg **rdma_req,
@@ -386,13 +351,14 @@ void svc_rdma_xdr_encode_reply_array(struct rpcrdma_write_array *ary,
386 351
387void svc_rdma_xdr_encode_array_chunk(struct rpcrdma_write_array *ary, 352void svc_rdma_xdr_encode_array_chunk(struct rpcrdma_write_array *ary,
388 int chunk_no, 353 int chunk_no,
389 u32 rs_handle, u64 rs_offset, 354 __be32 rs_handle,
355 __be64 rs_offset,
390 u32 write_len) 356 u32 write_len)
391{ 357{
392 struct rpcrdma_segment *seg = &ary->wc_array[chunk_no].wc_target; 358 struct rpcrdma_segment *seg = &ary->wc_array[chunk_no].wc_target;
393 seg->rs_handle = htonl(rs_handle); 359 seg->rs_handle = rs_handle;
360 seg->rs_offset = rs_offset;
394 seg->rs_length = htonl(write_len); 361 seg->rs_length = htonl(write_len);
395 xdr_encode_hyper((u32 *) &seg->rs_offset, rs_offset);
396} 362}
397 363
398void svc_rdma_xdr_encode_reply_header(struct svcxprt_rdma *xprt, 364void svc_rdma_xdr_encode_reply_header(struct svcxprt_rdma *xprt,
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index df67211c4baf..41cb63b623df 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -147,7 +147,7 @@ static int map_read_chunks(struct svcxprt_rdma *xprt,
147 page_off = 0; 147 page_off = 0;
148 ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; 148 ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0];
149 ch_no = 0; 149 ch_no = 0;
150 ch_bytes = ch->rc_target.rs_length; 150 ch_bytes = ntohl(ch->rc_target.rs_length);
151 head->arg.head[0] = rqstp->rq_arg.head[0]; 151 head->arg.head[0] = rqstp->rq_arg.head[0];
152 head->arg.tail[0] = rqstp->rq_arg.tail[0]; 152 head->arg.tail[0] = rqstp->rq_arg.tail[0];
153 head->arg.pages = &head->pages[head->count]; 153 head->arg.pages = &head->pages[head->count];
@@ -183,7 +183,7 @@ static int map_read_chunks(struct svcxprt_rdma *xprt,
183 ch_no++; 183 ch_no++;
184 ch++; 184 ch++;
185 chl_map->ch[ch_no].start = sge_no; 185 chl_map->ch[ch_no].start = sge_no;
186 ch_bytes = ch->rc_target.rs_length; 186 ch_bytes = ntohl(ch->rc_target.rs_length);
187 /* If bytes remaining account for next chunk */ 187 /* If bytes remaining account for next chunk */
188 if (byte_count) { 188 if (byte_count) {
189 head->arg.page_len += ch_bytes; 189 head->arg.page_len += ch_bytes;
@@ -281,11 +281,12 @@ static int fast_reg_read_chunks(struct svcxprt_rdma *xprt,
281 offset = 0; 281 offset = 0;
282 ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; 282 ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0];
283 for (ch_no = 0; ch_no < ch_count; ch_no++) { 283 for (ch_no = 0; ch_no < ch_count; ch_no++) {
284 int len = ntohl(ch->rc_target.rs_length);
284 rpl_map->sge[ch_no].iov_base = frmr->kva + offset; 285 rpl_map->sge[ch_no].iov_base = frmr->kva + offset;
285 rpl_map->sge[ch_no].iov_len = ch->rc_target.rs_length; 286 rpl_map->sge[ch_no].iov_len = len;
286 chl_map->ch[ch_no].count = 1; 287 chl_map->ch[ch_no].count = 1;
287 chl_map->ch[ch_no].start = ch_no; 288 chl_map->ch[ch_no].start = ch_no;
288 offset += ch->rc_target.rs_length; 289 offset += len;
289 ch++; 290 ch++;
290 } 291 }
291 292
@@ -316,7 +317,7 @@ static int rdma_set_ctxt_sge(struct svcxprt_rdma *xprt,
316 for (i = 0; i < count; i++) { 317 for (i = 0; i < count; i++) {
317 ctxt->sge[i].length = 0; /* in case map fails */ 318 ctxt->sge[i].length = 0; /* in case map fails */
318 if (!frmr) { 319 if (!frmr) {
319 BUG_ON(0 == virt_to_page(vec[i].iov_base)); 320 BUG_ON(!virt_to_page(vec[i].iov_base));
320 off = (unsigned long)vec[i].iov_base & ~PAGE_MASK; 321 off = (unsigned long)vec[i].iov_base & ~PAGE_MASK;
321 ctxt->sge[i].addr = 322 ctxt->sge[i].addr =
322 ib_dma_map_page(xprt->sc_cm_id->device, 323 ib_dma_map_page(xprt->sc_cm_id->device,
@@ -426,6 +427,7 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt,
426 427
427 for (ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; 428 for (ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0];
428 ch->rc_discrim != 0; ch++, ch_no++) { 429 ch->rc_discrim != 0; ch++, ch_no++) {
430 u64 rs_offset;
429next_sge: 431next_sge:
430 ctxt = svc_rdma_get_context(xprt); 432 ctxt = svc_rdma_get_context(xprt);
431 ctxt->direction = DMA_FROM_DEVICE; 433 ctxt->direction = DMA_FROM_DEVICE;
@@ -440,10 +442,10 @@ next_sge:
440 read_wr.opcode = IB_WR_RDMA_READ; 442 read_wr.opcode = IB_WR_RDMA_READ;
441 ctxt->wr_op = read_wr.opcode; 443 ctxt->wr_op = read_wr.opcode;
442 read_wr.send_flags = IB_SEND_SIGNALED; 444 read_wr.send_flags = IB_SEND_SIGNALED;
443 read_wr.wr.rdma.rkey = ch->rc_target.rs_handle; 445 read_wr.wr.rdma.rkey = ntohl(ch->rc_target.rs_handle);
444 read_wr.wr.rdma.remote_addr = 446 xdr_decode_hyper((__be32 *)&ch->rc_target.rs_offset,
445 get_unaligned(&(ch->rc_target.rs_offset)) + 447 &rs_offset);
446 sgl_offset; 448 read_wr.wr.rdma.remote_addr = rs_offset + sgl_offset;
447 read_wr.sg_list = ctxt->sge; 449 read_wr.sg_list = ctxt->sge;
448 read_wr.num_sge = 450 read_wr.num_sge =
449 rdma_read_max_sge(xprt, chl_map->ch[ch_no].count); 451 rdma_read_max_sge(xprt, chl_map->ch[ch_no].count);
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
index 249a835b703f..42eb7ba0b903 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
@@ -409,21 +409,21 @@ static int send_write_chunks(struct svcxprt_rdma *xprt,
409 u64 rs_offset; 409 u64 rs_offset;
410 410
411 arg_ch = &arg_ary->wc_array[chunk_no].wc_target; 411 arg_ch = &arg_ary->wc_array[chunk_no].wc_target;
412 write_len = min(xfer_len, arg_ch->rs_length); 412 write_len = min(xfer_len, ntohl(arg_ch->rs_length));
413 413
414 /* Prepare the response chunk given the length actually 414 /* Prepare the response chunk given the length actually
415 * written */ 415 * written */
416 rs_offset = get_unaligned(&(arg_ch->rs_offset)); 416 xdr_decode_hyper((__be32 *)&arg_ch->rs_offset, &rs_offset);
417 svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no, 417 svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no,
418 arg_ch->rs_handle, 418 arg_ch->rs_handle,
419 rs_offset, 419 arg_ch->rs_offset,
420 write_len); 420 write_len);
421 chunk_off = 0; 421 chunk_off = 0;
422 while (write_len) { 422 while (write_len) {
423 int this_write; 423 int this_write;
424 this_write = min(write_len, max_write); 424 this_write = min(write_len, max_write);
425 ret = send_write(xprt, rqstp, 425 ret = send_write(xprt, rqstp,
426 arg_ch->rs_handle, 426 ntohl(arg_ch->rs_handle),
427 rs_offset + chunk_off, 427 rs_offset + chunk_off,
428 xdr_off, 428 xdr_off,
429 this_write, 429 this_write,
@@ -457,6 +457,7 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt,
457 u32 xdr_off; 457 u32 xdr_off;
458 int chunk_no; 458 int chunk_no;
459 int chunk_off; 459 int chunk_off;
460 int nchunks;
460 struct rpcrdma_segment *ch; 461 struct rpcrdma_segment *ch;
461 struct rpcrdma_write_array *arg_ary; 462 struct rpcrdma_write_array *arg_ary;
462 struct rpcrdma_write_array *res_ary; 463 struct rpcrdma_write_array *res_ary;
@@ -476,26 +477,27 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt,
476 max_write = xprt->sc_max_sge * PAGE_SIZE; 477 max_write = xprt->sc_max_sge * PAGE_SIZE;
477 478
478 /* xdr offset starts at RPC message */ 479 /* xdr offset starts at RPC message */
480 nchunks = ntohl(arg_ary->wc_nchunks);
479 for (xdr_off = 0, chunk_no = 0; 481 for (xdr_off = 0, chunk_no = 0;
480 xfer_len && chunk_no < arg_ary->wc_nchunks; 482 xfer_len && chunk_no < nchunks;
481 chunk_no++) { 483 chunk_no++) {
482 u64 rs_offset; 484 u64 rs_offset;
483 ch = &arg_ary->wc_array[chunk_no].wc_target; 485 ch = &arg_ary->wc_array[chunk_no].wc_target;
484 write_len = min(xfer_len, ch->rs_length); 486 write_len = min(xfer_len, htonl(ch->rs_length));
485 487
486 /* Prepare the reply chunk given the length actually 488 /* Prepare the reply chunk given the length actually
487 * written */ 489 * written */
488 rs_offset = get_unaligned(&(ch->rs_offset)); 490 xdr_decode_hyper((__be32 *)&ch->rs_offset, &rs_offset);
489 svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no, 491 svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no,
490 ch->rs_handle, rs_offset, 492 ch->rs_handle, ch->rs_offset,
491 write_len); 493 write_len);
492 chunk_off = 0; 494 chunk_off = 0;
493 while (write_len) { 495 while (write_len) {
494 int this_write; 496 int this_write;
495 497
496 this_write = min(write_len, max_write); 498 this_write = min(write_len, max_write);
497 ret = send_write(xprt, rqstp, 499 ret = send_write(xprt, rqstp,
498 ch->rs_handle, 500 ntohl(ch->rs_handle),
499 rs_offset + chunk_off, 501 rs_offset + chunk_off,
500 xdr_off, 502 xdr_off,
501 this_write, 503 this_write,
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
index 894cb42db91d..73b428bef598 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
@@ -51,6 +51,7 @@
51#include <rdma/rdma_cm.h> 51#include <rdma/rdma_cm.h>
52#include <linux/sunrpc/svc_rdma.h> 52#include <linux/sunrpc/svc_rdma.h>
53#include <linux/export.h> 53#include <linux/export.h>
54#include "xprt_rdma.h"
54 55
55#define RPCDBG_FACILITY RPCDBG_SVCXPRT 56#define RPCDBG_FACILITY RPCDBG_SVCXPRT
56 57
@@ -90,12 +91,6 @@ struct svc_xprt_class svc_rdma_class = {
90 .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, 91 .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP,
91}; 92};
92 93
93/* WR context cache. Created in svc_rdma.c */
94extern struct kmem_cache *svc_rdma_ctxt_cachep;
95
96/* Workqueue created in svc_rdma.c */
97extern struct workqueue_struct *svc_rdma_wq;
98
99struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) 94struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt)
100{ 95{
101 struct svc_rdma_op_ctxt *ctxt; 96 struct svc_rdma_op_ctxt *ctxt;
@@ -150,9 +145,6 @@ void svc_rdma_put_context(struct svc_rdma_op_ctxt *ctxt, int free_pages)
150 atomic_dec(&xprt->sc_ctxt_used); 145 atomic_dec(&xprt->sc_ctxt_used);
151} 146}
152 147
153/* Temporary NFS request map cache. Created in svc_rdma.c */
154extern struct kmem_cache *svc_rdma_map_cachep;
155
156/* 148/*
157 * Temporary NFS req mappings are shared across all transport 149 * Temporary NFS req mappings are shared across all transport
158 * instances. These are short lived and should be bounded by the number 150 * instances. These are short lived and should be bounded by the number
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h
index 08c5d5a128fc..9a66c95b5837 100644
--- a/net/sunrpc/xprtrdma/xprt_rdma.h
+++ b/net/sunrpc/xprtrdma/xprt_rdma.h
@@ -343,4 +343,11 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *);
343 */ 343 */
344int rpcrdma_marshal_req(struct rpc_rqst *); 344int rpcrdma_marshal_req(struct rpc_rqst *);
345 345
346/* Temporary NFS request map cache. Created in svc_rdma.c */
347extern struct kmem_cache *svc_rdma_map_cachep;
348/* WR context cache. Created in svc_rdma.c */
349extern struct kmem_cache *svc_rdma_ctxt_cachep;
350/* Workqueue created in svc_rdma.c */
351extern struct workqueue_struct *svc_rdma_wq;
352
346#endif /* _LINUX_SUNRPC_XPRT_RDMA_H */ 353#endif /* _LINUX_SUNRPC_XPRT_RDMA_H */
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 92bc5181dbeb..890b03f8d877 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -2475,6 +2475,7 @@ static struct rpc_xprt_ops xs_tcp_ops = {
2475static struct rpc_xprt_ops bc_tcp_ops = { 2475static struct rpc_xprt_ops bc_tcp_ops = {
2476 .reserve_xprt = xprt_reserve_xprt, 2476 .reserve_xprt = xprt_reserve_xprt,
2477 .release_xprt = xprt_release_xprt, 2477 .release_xprt = xprt_release_xprt,
2478 .rpcbind = xs_local_rpcbind,
2478 .buf_alloc = bc_malloc, 2479 .buf_alloc = bc_malloc,
2479 .buf_free = bc_free, 2480 .buf_free = bc_free,
2480 .send_request = bc_send_request, 2481 .send_request = bc_send_request,