Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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
...

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