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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'nfsd-6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux

Pull nfsd updates from Chuck Lever:
"Jeff Layton contributed an implementation of NFSv4.2+ attribute
delegation, as described here:

https://www.ietf.org/archive/id/draft-ietf-nfsv4-delstid-08.html

This interoperates with similar functionality introduced into the
Linux NFS client in v6.11. An attribute delegation permits an NFS
client to manage a file's mtime, rather than flushing dirty data to
the NFS server so that the file's mtime reflects the last write, which
is considerably slower.

Neil Brown contributed dynamic NFSv4.1 session slot table resizing.
This facility enables NFSD to increase or decrease the number of slots
per NFS session depending on server memory availability. More session
slots means greater parallelism.

Chuck Lever fixed a long-standing latent bug where NFSv4 COMPOUND
encoding screws up when crossing a page boundary in the encoding
buffer. This is a zero-day bug, but hitting it is rare and depends on
the NFS client implementation. The Linux NFS client does not happen to
trigger this issue.

A variety of bug fixes and other incremental improvements fill out the
list of commits in this release. Great thanks to all contributors,
reviewers, testers, and bug reporters who participated during this
development cycle"

* tag 'nfsd-6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: (42 commits)
sunrpc: Remove gss_{de,en}crypt_xdr_buf deadcode
sunrpc: Remove gss_generic_token deadcode
sunrpc: Remove unused xprt_iter_get_xprt
Revert "SUNRPC: Reduce thread wake-up rate when receiving large RPC messages"
nfsd: implement OPEN_ARGS_SHARE_ACCESS_WANT_OPEN_XOR_DELEGATION
nfsd: handle delegated timestamps in SETATTR
nfsd: add support for delegated timestamps
nfsd: rework NFS4_SHARE_WANT_* flag handling
nfsd: add support for FATTR4_OPEN_ARGUMENTS
nfsd: prepare delegation code for handing out *_ATTRS_DELEG delegations
nfsd: rename NFS4_SHARE_WANT_* constants to OPEN4_SHARE_ACCESS_WANT_*
nfsd: switch to autogenerated definitions for open_delegation_type4
nfs_common: make include/linux/nfs4.h include generated nfs4_1.h
nfsd: fix handling of delegated change attr in CB_GETATTR
SUNRPC: Document validity guarantees of the pointer returned by reserve_space
NFSD: Insulate nfsd4_encode_fattr4() from page boundaries in the encode buffer
NFSD: Insulate nfsd4_encode_secinfo() from page boundaries in the encode buffer
NFSD: Refactor nfsd4_do_encode_secinfo() again
NFSD: Insulate nfsd4_encode_readlink() from page boundaries in the encode buffer
NFSD: Insulate nfsd4_encode_read_plus_data() from page boundaries in the encode buffer
...

+1462 -885
+186
Documentation/sunrpc/xdr/nfs4_1.x
··· 1 + /* 2 + * Copyright (c) 2010 IETF Trust and the persons identified 3 + * as the document authors. All rights reserved. 4 + * 5 + * The document authors are identified in RFC 3530 and 6 + * RFC 5661. 7 + * 8 + * Redistribution and use in source and binary forms, with 9 + * or without modification, are permitted provided that the 10 + * following conditions are met: 11 + * 12 + * - Redistributions of source code must retain the above 13 + * copyright notice, this list of conditions and the 14 + * following disclaimer. 15 + * 16 + * - Redistributions in binary form must reproduce the above 17 + * copyright notice, this list of conditions and the 18 + * following disclaimer in the documentation and/or other 19 + * materials provided with the distribution. 20 + * 21 + * - Neither the name of Internet Society, IETF or IETF 22 + * Trust, nor the names of specific contributors, may be 23 + * used to endorse or promote products derived from this 24 + * software without specific prior written permission. 25 + * 26 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 27 + * AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 28 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 30 + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 31 + * EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 32 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 33 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 34 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 35 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 36 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 37 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 38 + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 39 + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 40 + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 + */ 42 + 43 + pragma header nfs4; 44 + 45 + /* 46 + * Basic typedefs for RFC 1832 data type definitions 47 + */ 48 + typedef hyper int64_t; 49 + typedef unsigned int uint32_t; 50 + 51 + /* 52 + * Basic data types 53 + */ 54 + typedef uint32_t bitmap4<>; 55 + 56 + /* 57 + * Timeval 58 + */ 59 + struct nfstime4 { 60 + int64_t seconds; 61 + uint32_t nseconds; 62 + }; 63 + 64 + 65 + /* 66 + * The following content was extracted from draft-ietf-nfsv4-delstid 67 + */ 68 + 69 + typedef bool fattr4_offline; 70 + 71 + 72 + const FATTR4_OFFLINE = 83; 73 + 74 + 75 + struct open_arguments4 { 76 + bitmap4 oa_share_access; 77 + bitmap4 oa_share_deny; 78 + bitmap4 oa_share_access_want; 79 + bitmap4 oa_open_claim; 80 + bitmap4 oa_create_mode; 81 + }; 82 + 83 + 84 + enum open_args_share_access4 { 85 + OPEN_ARGS_SHARE_ACCESS_READ = 1, 86 + OPEN_ARGS_SHARE_ACCESS_WRITE = 2, 87 + OPEN_ARGS_SHARE_ACCESS_BOTH = 3 88 + }; 89 + 90 + 91 + enum open_args_share_deny4 { 92 + OPEN_ARGS_SHARE_DENY_NONE = 0, 93 + OPEN_ARGS_SHARE_DENY_READ = 1, 94 + OPEN_ARGS_SHARE_DENY_WRITE = 2, 95 + OPEN_ARGS_SHARE_DENY_BOTH = 3 96 + }; 97 + 98 + 99 + enum open_args_share_access_want4 { 100 + OPEN_ARGS_SHARE_ACCESS_WANT_ANY_DELEG = 3, 101 + OPEN_ARGS_SHARE_ACCESS_WANT_NO_DELEG = 4, 102 + OPEN_ARGS_SHARE_ACCESS_WANT_CANCEL = 5, 103 + OPEN_ARGS_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL 104 + = 17, 105 + OPEN_ARGS_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED 106 + = 18, 107 + OPEN_ARGS_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS = 20, 108 + OPEN_ARGS_SHARE_ACCESS_WANT_OPEN_XOR_DELEGATION = 21 109 + }; 110 + 111 + 112 + enum open_args_open_claim4 { 113 + OPEN_ARGS_OPEN_CLAIM_NULL = 0, 114 + OPEN_ARGS_OPEN_CLAIM_PREVIOUS = 1, 115 + OPEN_ARGS_OPEN_CLAIM_DELEGATE_CUR = 2, 116 + OPEN_ARGS_OPEN_CLAIM_DELEGATE_PREV = 3, 117 + OPEN_ARGS_OPEN_CLAIM_FH = 4, 118 + OPEN_ARGS_OPEN_CLAIM_DELEG_CUR_FH = 5, 119 + OPEN_ARGS_OPEN_CLAIM_DELEG_PREV_FH = 6 120 + }; 121 + 122 + 123 + enum open_args_createmode4 { 124 + OPEN_ARGS_CREATEMODE_UNCHECKED4 = 0, 125 + OPEN_ARGS_CREATE_MODE_GUARDED = 1, 126 + OPEN_ARGS_CREATEMODE_EXCLUSIVE4 = 2, 127 + OPEN_ARGS_CREATE_MODE_EXCLUSIVE4_1 = 3 128 + }; 129 + 130 + 131 + typedef open_arguments4 fattr4_open_arguments; 132 + pragma public fattr4_open_arguments; 133 + 134 + 135 + %/* 136 + % * Determine what OPEN supports. 137 + % */ 138 + const FATTR4_OPEN_ARGUMENTS = 86; 139 + 140 + 141 + 142 + 143 + const OPEN4_RESULT_NO_OPEN_STATEID = 0x00000010; 144 + 145 + 146 + /* 147 + * attributes for the delegation times being 148 + * cached and served by the "client" 149 + */ 150 + typedef nfstime4 fattr4_time_deleg_access; 151 + typedef nfstime4 fattr4_time_deleg_modify; 152 + pragma public fattr4_time_deleg_access; 153 + pragma public fattr4_time_deleg_modify; 154 + 155 + 156 + %/* 157 + % * New RECOMMENDED Attribute for 158 + % * delegation caching of times 159 + % */ 160 + const FATTR4_TIME_DELEG_ACCESS = 84; 161 + const FATTR4_TIME_DELEG_MODIFY = 85; 162 + 163 + 164 + 165 + /* new flags for share_access field of OPEN4args */ 166 + const OPEN4_SHARE_ACCESS_WANT_DELEG_MASK = 0xFF00; 167 + const OPEN4_SHARE_ACCESS_WANT_NO_PREFERENCE = 0x0000; 168 + const OPEN4_SHARE_ACCESS_WANT_READ_DELEG = 0x0100; 169 + const OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG = 0x0200; 170 + const OPEN4_SHARE_ACCESS_WANT_ANY_DELEG = 0x0300; 171 + const OPEN4_SHARE_ACCESS_WANT_NO_DELEG = 0x0400; 172 + const OPEN4_SHARE_ACCESS_WANT_CANCEL = 0x0500; 173 + 174 + const OPEN4_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL = 0x10000; 175 + const OPEN4_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED = 0x20000; 176 + const OPEN4_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS = 0x100000; 177 + const OPEN4_SHARE_ACCESS_WANT_OPEN_XOR_DELEGATION = 0x200000; 178 + 179 + enum open_delegation_type4 { 180 + OPEN_DELEGATE_NONE = 0, 181 + OPEN_DELEGATE_READ = 1, 182 + OPEN_DELEGATE_WRITE = 2, 183 + OPEN_DELEGATE_NONE_EXT = 3, /* new to v4.1 */ 184 + OPEN_DELEGATE_READ_ATTRS_DELEG = 4, 185 + OPEN_DELEGATE_WRITE_ATTRS_DELEG = 5 186 + };
-8
fs/lockd/svc.c
··· 70 70 unsigned long nlm_timeout = LOCKD_DFLT_TIMEO; 71 71 static int nlm_udpport, nlm_tcpport; 72 72 73 - /* RLIM_NOFILE defaults to 1024. That seems like a reasonable default here. */ 74 - static unsigned int nlm_max_connections = 1024; 75 - 76 73 /* 77 74 * Constants needed for the sysctl interface. 78 75 */ ··· 133 136 * NFS mount or NFS daemon has gone away. 134 137 */ 135 138 while (!svc_thread_should_stop(rqstp)) { 136 - /* update sv_maxconn if it has changed */ 137 - rqstp->rq_server->sv_maxconn = nlm_max_connections; 138 - 139 139 nlmsvc_retry_blocked(rqstp); 140 140 svc_recv(rqstp); 141 141 } ··· 334 340 return -ENOMEM; 335 341 } 336 342 337 - serv->sv_maxconn = nlm_max_connections; 338 343 error = svc_set_num_threads(serv, NULL, 1); 339 344 if (error < 0) { 340 345 svc_destroy(&serv); ··· 535 542 module_param_call(nlm_tcpport, param_set_port, param_get_int, 536 543 &nlm_tcpport, 0644); 537 544 module_param(nsm_use_hostnames, bool, 0644); 538 - module_param(nlm_max_connections, uint, 0644); 539 545 540 546 static int lockd_init_net(struct net *net) 541 547 {
-4
fs/nfs/callback.c
··· 211 211 return ERR_PTR(-ENOMEM); 212 212 } 213 213 cb_info->serv = serv; 214 - /* As there is only one thread we need to over-ride the 215 - * default maximum of 80 connections 216 - */ 217 - serv->sv_maxconn = 1024; 218 214 dprintk("nfs_callback_create_svc: service created\n"); 219 215 return serv; 220 216 }
+1
fs/nfs/callback_xdr.c
··· 984 984 nfs_put_client(cps.clp); 985 985 goto out_invalidcred; 986 986 } 987 + svc_xprt_set_valid(rqstp->rq_xprt); 987 988 } 988 989 989 990 cps.minorversion = hdr_arg.minorversion;
+15 -1
fs/nfsd/Makefile
··· 18 18 nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o 19 19 nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o 20 20 nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \ 21 - nfs4acl.o nfs4callback.o nfs4recover.o 21 + nfs4acl.o nfs4callback.o nfs4recover.o nfs4xdr_gen.o 22 22 nfsd-$(CONFIG_NFSD_PNFS) += nfs4layouts.o 23 23 nfsd-$(CONFIG_NFSD_BLOCKLAYOUT) += blocklayout.o blocklayoutxdr.o 24 24 nfsd-$(CONFIG_NFSD_SCSILAYOUT) += blocklayout.o blocklayoutxdr.o 25 25 nfsd-$(CONFIG_NFSD_FLEXFILELAYOUT) += flexfilelayout.o flexfilelayoutxdr.o 26 26 nfsd-$(CONFIG_NFS_LOCALIO) += localio.o 27 + 28 + 29 + .PHONY: xdrgen 30 + 31 + xdrgen: ../../include/linux/sunrpc/xdrgen/nfs4_1.h nfs4xdr_gen.h nfs4xdr_gen.c 32 + 33 + ../../include/linux/sunrpc/xdrgen/nfs4_1.h: ../../Documentation/sunrpc/xdr/nfs4_1.x 34 + ../../tools/net/sunrpc/xdrgen/xdrgen definitions $< > $@ 35 + 36 + nfs4xdr_gen.h: ../../Documentation/sunrpc/xdr/nfs4_1.x 37 + ../../tools/net/sunrpc/xdrgen/xdrgen declarations $< > $@ 38 + 39 + nfs4xdr_gen.c: ../../Documentation/sunrpc/xdr/nfs4_1.x 40 + ../../tools/net/sunrpc/xdrgen/xdrgen source $< > $@
+15 -10
fs/nfsd/export.c
··· 355 355 EXP_STATS_COUNTERS_NUM); 356 356 } 357 357 358 - static void svc_export_put(struct kref *ref) 358 + static void svc_export_release(struct rcu_head *rcu_head) 359 359 { 360 - struct svc_export *exp = container_of(ref, struct svc_export, h.ref); 361 - path_put(&exp->ex_path); 362 - auth_domain_put(exp->ex_client); 360 + struct svc_export *exp = container_of(rcu_head, struct svc_export, 361 + ex_rcu); 362 + 363 363 nfsd4_fslocs_free(&exp->ex_fslocs); 364 364 export_stats_destroy(exp->ex_stats); 365 365 kfree(exp->ex_stats); 366 366 kfree(exp->ex_uuid); 367 - kfree_rcu(exp, ex_rcu); 367 + kfree(exp); 368 + } 369 + 370 + static void svc_export_put(struct kref *ref) 371 + { 372 + struct svc_export *exp = container_of(ref, struct svc_export, h.ref); 373 + 374 + path_put(&exp->ex_path); 375 + auth_domain_put(exp->ex_client); 376 + call_rcu(&exp->ex_rcu, svc_export_release); 368 377 } 369 378 370 379 static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h) ··· 1434 1425 return 0; 1435 1426 } 1436 1427 1437 - if (!cache_get_rcu(&exp->h)) 1428 + if (cache_check_rcu(cd, &exp->h, NULL)) 1438 1429 return 0; 1439 1430 1440 - if (cache_check(cd, &exp->h, NULL)) 1441 - return 0; 1442 - 1443 - exp_put(exp); 1444 1431 return svc_export_show(m, cd, cp); 1445 1432 } 1446 1433
-6
fs/nfsd/netns.h
··· 128 128 seqlock_t writeverf_lock; 129 129 unsigned char writeverf[8]; 130 130 131 - /* 132 - * Max number of connections this nfsd container will allow. Defaults 133 - * to '0' which is means that it bases this on the number of threads. 134 - */ 135 - unsigned int max_connections; 136 - 137 131 u32 clientid_base; 138 132 u32 clientid_counter; 139 133 u32 clverifier_counter;
+48 -12
fs/nfsd/nfs4callback.c
··· 42 42 #include "trace.h" 43 43 #include "xdr4cb.h" 44 44 #include "xdr4.h" 45 + #include "nfs4xdr_gen.h" 45 46 46 47 #define NFSDDBG_FACILITY NFSDDBG_PROC 47 48 ··· 94 93 { 95 94 fattr->ncf_cb_change = 0; 96 95 fattr->ncf_cb_fsize = 0; 96 + fattr->ncf_cb_atime.tv_sec = 0; 97 + fattr->ncf_cb_atime.tv_nsec = 0; 98 + fattr->ncf_cb_mtime.tv_sec = 0; 99 + fattr->ncf_cb_mtime.tv_nsec = 0; 100 + 97 101 if (bitmap[0] & FATTR4_WORD0_CHANGE) 98 102 if (xdr_stream_decode_u64(xdr, &fattr->ncf_cb_change) < 0) 99 103 return -NFSERR_BAD_XDR; 100 104 if (bitmap[0] & FATTR4_WORD0_SIZE) 101 105 if (xdr_stream_decode_u64(xdr, &fattr->ncf_cb_fsize) < 0) 102 106 return -NFSERR_BAD_XDR; 107 + if (bitmap[2] & FATTR4_WORD2_TIME_DELEG_ACCESS) { 108 + fattr4_time_deleg_access access; 109 + 110 + if (!xdrgen_decode_fattr4_time_deleg_access(xdr, &access)) 111 + return -NFSERR_BAD_XDR; 112 + fattr->ncf_cb_atime.tv_sec = access.seconds; 113 + fattr->ncf_cb_atime.tv_nsec = access.nseconds; 114 + 115 + } 116 + if (bitmap[2] & FATTR4_WORD2_TIME_DELEG_MODIFY) { 117 + fattr4_time_deleg_modify modify; 118 + 119 + if (!xdrgen_decode_fattr4_time_deleg_modify(xdr, &modify)) 120 + return -NFSERR_BAD_XDR; 121 + fattr->ncf_cb_mtime.tv_sec = modify.seconds; 122 + fattr->ncf_cb_mtime.tv_nsec = modify.nseconds; 123 + 124 + } 103 125 return 0; 104 126 } 105 127 ··· 385 361 encode_cb_getattr4args(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr, 386 362 struct nfs4_cb_fattr *fattr) 387 363 { 388 - struct nfs4_delegation *dp = 389 - container_of(fattr, struct nfs4_delegation, dl_cb_fattr); 364 + struct nfs4_delegation *dp = container_of(fattr, struct nfs4_delegation, dl_cb_fattr); 390 365 struct knfsd_fh *fh = &dp->dl_stid.sc_file->fi_fhandle; 391 - u32 bmap[1]; 366 + struct nfs4_cb_fattr *ncf = &dp->dl_cb_fattr; 367 + u32 bmap_size = 1; 368 + u32 bmap[3]; 392 369 393 - bmap[0] = FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE; 370 + bmap[0] = FATTR4_WORD0_SIZE; 371 + if (!ncf->ncf_file_modified) 372 + bmap[0] |= FATTR4_WORD0_CHANGE; 394 373 374 + if (deleg_attrs_deleg(dp->dl_type)) { 375 + bmap[1] = 0; 376 + bmap[2] = FATTR4_WORD2_TIME_DELEG_ACCESS | FATTR4_WORD2_TIME_DELEG_MODIFY; 377 + bmap_size = 3; 378 + } 395 379 encode_nfs_cb_opnum4(xdr, OP_CB_GETATTR); 396 380 encode_nfs_fh4(xdr, fh); 397 - encode_bitmap4(xdr, bmap, ARRAY_SIZE(bmap)); 381 + encode_bitmap4(xdr, bmap, bmap_size); 398 382 hdr->nops++; 399 383 } 400 384 ··· 666 634 struct nfs4_cb_compound_hdr hdr; 667 635 int status; 668 636 u32 bitmap[3] = {0}; 669 - u32 attrlen; 637 + u32 attrlen, maxlen; 670 638 struct nfs4_cb_fattr *ncf = 671 639 container_of(cb, struct nfs4_cb_fattr, ncf_getattr); 672 640 ··· 679 647 return status; 680 648 681 649 status = decode_cb_op_status(xdr, OP_CB_GETATTR, &cb->cb_status); 682 - if (status) 650 + if (unlikely(status || cb->cb_seq_status)) 683 651 return status; 684 652 if (xdr_stream_decode_uint32_array(xdr, bitmap, 3) < 0) 685 653 return -NFSERR_BAD_XDR; 686 654 if (xdr_stream_decode_u32(xdr, &attrlen) < 0) 687 655 return -NFSERR_BAD_XDR; 688 - if (attrlen > (sizeof(ncf->ncf_cb_change) + sizeof(ncf->ncf_cb_fsize))) 656 + maxlen = sizeof(ncf->ncf_cb_change) + sizeof(ncf->ncf_cb_fsize); 657 + if (bitmap[2] != 0) 658 + maxlen += (sizeof(ncf->ncf_cb_mtime.tv_sec) + 659 + sizeof(ncf->ncf_cb_mtime.tv_nsec)) * 2; 660 + if (attrlen > maxlen) 689 661 return -NFSERR_BAD_XDR; 690 662 status = decode_cb_fattr4(xdr, bitmap, ncf); 691 663 return status; ··· 1072 1036 static void nfsd41_cb_inflight_end(struct nfs4_client *clp) 1073 1037 { 1074 1038 1075 - if (atomic_dec_and_test(&clp->cl_cb_inflight)) 1076 - wake_up_var(&clp->cl_cb_inflight); 1039 + atomic_dec_and_wake_up(&clp->cl_cb_inflight); 1077 1040 } 1078 1041 1079 1042 static void nfsd41_cb_inflight_wait_complete(struct nfs4_client *clp) ··· 1432 1397 return; 1433 1398 1434 1399 if (cb->cb_status) { 1435 - WARN_ONCE(task->tk_status, "cb_status=%d tk_status=%d", 1436 - cb->cb_status, task->tk_status); 1400 + WARN_ONCE(task->tk_status, 1401 + "cb_status=%d tk_status=%d cb_opcode=%d", 1402 + cb->cb_status, task->tk_status, cb->cb_ops->opcode); 1437 1403 task->tk_status = cb->cb_status; 1438 1404 } 1439 1405
+28 -3
fs/nfsd/nfs4proc.c
··· 1135 1135 .na_iattr = &setattr->sa_iattr, 1136 1136 .na_seclabel = &setattr->sa_label, 1137 1137 }; 1138 + bool save_no_wcc, deleg_attrs; 1139 + struct nfs4_stid *st = NULL; 1138 1140 struct inode *inode; 1139 1141 __be32 status = nfs_ok; 1140 - bool save_no_wcc; 1141 1142 int err; 1142 1143 1143 - if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { 1144 + deleg_attrs = setattr->sa_bmval[2] & (FATTR4_WORD2_TIME_DELEG_ACCESS | 1145 + FATTR4_WORD2_TIME_DELEG_MODIFY); 1146 + 1147 + if (deleg_attrs || (setattr->sa_iattr.ia_valid & ATTR_SIZE)) { 1148 + int flags = WR_STATE; 1149 + 1150 + if (setattr->sa_bmval[2] & FATTR4_WORD2_TIME_DELEG_ACCESS) 1151 + flags |= RD_STATE; 1152 + 1144 1153 status = nfs4_preprocess_stateid_op(rqstp, cstate, 1145 1154 &cstate->current_fh, &setattr->sa_stateid, 1146 - WR_STATE, NULL, NULL); 1155 + flags, NULL, &st); 1147 1156 if (status) 1148 1157 return status; 1149 1158 } 1159 + 1160 + if (deleg_attrs) { 1161 + status = nfserr_bad_stateid; 1162 + if (st->sc_type & SC_TYPE_DELEG) { 1163 + struct nfs4_delegation *dp = delegstateid(st); 1164 + 1165 + /* Only for *_ATTRS_DELEG flavors */ 1166 + if (deleg_attrs_deleg(dp->dl_type)) 1167 + status = nfs_ok; 1168 + } 1169 + } 1170 + if (st) 1171 + nfs4_put_stid(st); 1172 + if (status) 1173 + return status; 1174 + 1150 1175 err = fh_want_write(&cstate->current_fh); 1151 1176 if (err) 1152 1177 return nfserrno(err);
-1
fs/nfsd/nfs4recover.c
··· 2051 2051 path_put(&path); 2052 2052 if (status) 2053 2053 return -ENOTDIR; 2054 - status = nn->client_tracking_ops->init(net); 2055 2054 } 2056 2055 return status; 2057 2056 }
+374 -152
fs/nfsd/nfs4state.c
··· 1909 1909 */ 1910 1910 #define NFSD_MIN_HDR_SEQ_SZ (24 + 12 + 44) 1911 1911 1912 + static struct shrinker *nfsd_slot_shrinker; 1913 + static DEFINE_SPINLOCK(nfsd_session_list_lock); 1914 + static LIST_HEAD(nfsd_session_list); 1915 + /* The sum of "target_slots-1" on every session. The shrinker can push this 1916 + * down, though it can take a little while for the memory to actually 1917 + * be freed. The "-1" is because we can never free slot 0 while the 1918 + * session is active. 1919 + */ 1920 + static atomic_t nfsd_total_target_slots = ATOMIC_INIT(0); 1921 + 1912 1922 static void 1913 - free_session_slots(struct nfsd4_session *ses) 1923 + free_session_slots(struct nfsd4_session *ses, int from) 1914 1924 { 1915 1925 int i; 1916 1926 1917 - for (i = 0; i < ses->se_fchannel.maxreqs; i++) { 1918 - free_svc_cred(&ses->se_slots[i]->sl_cred); 1919 - kfree(ses->se_slots[i]); 1927 + if (from >= ses->se_fchannel.maxreqs) 1928 + return; 1929 + 1930 + for (i = from; i < ses->se_fchannel.maxreqs; i++) { 1931 + struct nfsd4_slot *slot = xa_load(&ses->se_slots, i); 1932 + 1933 + /* 1934 + * Save the seqid in case we reactivate this slot. 1935 + * This will never require a memory allocation so GFP 1936 + * flag is irrelevant 1937 + */ 1938 + xa_store(&ses->se_slots, i, xa_mk_value(slot->sl_seqid), 0); 1939 + free_svc_cred(&slot->sl_cred); 1940 + kfree(slot); 1920 1941 } 1942 + ses->se_fchannel.maxreqs = from; 1943 + if (ses->se_target_maxslots > from) { 1944 + int new_target = from ?: 1; 1945 + atomic_sub(ses->se_target_maxslots - new_target, &nfsd_total_target_slots); 1946 + ses->se_target_maxslots = new_target; 1947 + } 1948 + } 1949 + 1950 + /** 1951 + * reduce_session_slots - reduce the target max-slots of a session if possible 1952 + * @ses: The session to affect 1953 + * @dec: how much to decrease the target by 1954 + * 1955 + * This interface can be used by a shrinker to reduce the target max-slots 1956 + * for a session so that some slots can eventually be freed. 1957 + * It uses spin_trylock() as it may be called in a context where another 1958 + * spinlock is held that has a dependency on client_lock. As shrinkers are 1959 + * best-effort, skiping a session is client_lock is already held has no 1960 + * great coast 1961 + * 1962 + * Return value: 1963 + * The number of slots that the target was reduced by. 1964 + */ 1965 + static int 1966 + reduce_session_slots(struct nfsd4_session *ses, int dec) 1967 + { 1968 + struct nfsd_net *nn = net_generic(ses->se_client->net, 1969 + nfsd_net_id); 1970 + int ret = 0; 1971 + 1972 + if (ses->se_target_maxslots <= 1) 1973 + return ret; 1974 + if (!spin_trylock(&nn->client_lock)) 1975 + return ret; 1976 + ret = min(dec, ses->se_target_maxslots-1); 1977 + ses->se_target_maxslots -= ret; 1978 + atomic_sub(ret, &nfsd_total_target_slots); 1979 + ses->se_slot_gen += 1; 1980 + if (ses->se_slot_gen == 0) { 1981 + int i; 1982 + ses->se_slot_gen = 1; 1983 + for (i = 0; i < ses->se_fchannel.maxreqs; i++) { 1984 + struct nfsd4_slot *slot = xa_load(&ses->se_slots, i); 1985 + slot->sl_generation = 0; 1986 + } 1987 + } 1988 + spin_unlock(&nn->client_lock); 1989 + return ret; 1921 1990 } 1922 1991 1923 1992 /* ··· 2004 1935 return size + sizeof(struct nfsd4_slot); 2005 1936 } 2006 1937 2007 - /* 2008 - * XXX: If we run out of reserved DRC memory we could (up to a point) 2009 - * re-negotiate active sessions and reduce their slot usage to make 2010 - * room for new connections. For now we just fail the create session. 2011 - */ 2012 - static u32 nfsd4_get_drc_mem(struct nfsd4_channel_attrs *ca, struct nfsd_net *nn) 2013 - { 2014 - u32 slotsize = slot_bytes(ca); 2015 - u32 num = ca->maxreqs; 2016 - unsigned long avail, total_avail; 2017 - unsigned int scale_factor; 2018 - 2019 - spin_lock(&nfsd_drc_lock); 2020 - if (nfsd_drc_max_mem > nfsd_drc_mem_used) 2021 - total_avail = nfsd_drc_max_mem - nfsd_drc_mem_used; 2022 - else 2023 - /* We have handed out more space than we chose in 2024 - * set_max_drc() to allow. That isn't really a 2025 - * problem as long as that doesn't make us think we 2026 - * have lots more due to integer overflow. 2027 - */ 2028 - total_avail = 0; 2029 - avail = min((unsigned long)NFSD_MAX_MEM_PER_SESSION, total_avail); 2030 - /* 2031 - * Never use more than a fraction of the remaining memory, 2032 - * unless it's the only way to give this client a slot. 2033 - * The chosen fraction is either 1/8 or 1/number of threads, 2034 - * whichever is smaller. This ensures there are adequate 2035 - * slots to support multiple clients per thread. 2036 - * Give the client one slot even if that would require 2037 - * over-allocation--it is better than failure. 2038 - */ 2039 - scale_factor = max_t(unsigned int, 8, nn->nfsd_serv->sv_nrthreads); 2040 - 2041 - avail = clamp_t(unsigned long, avail, slotsize, 2042 - total_avail/scale_factor); 2043 - num = min_t(int, num, avail / slotsize); 2044 - num = max_t(int, num, 1); 2045 - nfsd_drc_mem_used += num * slotsize; 2046 - spin_unlock(&nfsd_drc_lock); 2047 - 2048 - return num; 2049 - } 2050 - 2051 - static void nfsd4_put_drc_mem(struct nfsd4_channel_attrs *ca) 2052 - { 2053 - int slotsize = slot_bytes(ca); 2054 - 2055 - spin_lock(&nfsd_drc_lock); 2056 - nfsd_drc_mem_used -= slotsize * ca->maxreqs; 2057 - spin_unlock(&nfsd_drc_lock); 2058 - } 2059 - 2060 1938 static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs, 2061 1939 struct nfsd4_channel_attrs *battrs) 2062 1940 { 2063 1941 int numslots = fattrs->maxreqs; 2064 1942 int slotsize = slot_bytes(fattrs); 2065 1943 struct nfsd4_session *new; 1944 + struct nfsd4_slot *slot; 2066 1945 int i; 2067 1946 2068 - BUILD_BUG_ON(struct_size(new, se_slots, NFSD_MAX_SLOTS_PER_SESSION) 2069 - > PAGE_SIZE); 2070 - 2071 - new = kzalloc(struct_size(new, se_slots, numslots), GFP_KERNEL); 1947 + new = kzalloc(sizeof(*new), GFP_KERNEL); 2072 1948 if (!new) 2073 1949 return NULL; 1950 + xa_init(&new->se_slots); 2074 1951 /* allocate each struct nfsd4_slot and data cache in one piece */ 2075 - for (i = 0; i < numslots; i++) { 2076 - new->se_slots[i] = kzalloc(slotsize, GFP_KERNEL); 2077 - if (!new->se_slots[i]) 2078 - goto out_free; 2079 - } 1952 + slot = kzalloc(slotsize, GFP_KERNEL); 1953 + if (!slot || xa_is_err(xa_store(&new->se_slots, 0, slot, GFP_KERNEL))) 1954 + goto out_free; 2080 1955 1956 + for (i = 1; i < numslots; i++) { 1957 + const gfp_t gfp = GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN; 1958 + slot = kzalloc(slotsize, gfp); 1959 + if (!slot) 1960 + break; 1961 + if (xa_is_err(xa_store(&new->se_slots, i, slot, gfp))) { 1962 + kfree(slot); 1963 + break; 1964 + } 1965 + } 1966 + fattrs->maxreqs = i; 2081 1967 memcpy(&new->se_fchannel, fattrs, sizeof(struct nfsd4_channel_attrs)); 1968 + new->se_target_maxslots = i; 1969 + atomic_add(i - 1, &nfsd_total_target_slots); 2082 1970 new->se_cb_slot_avail = ~0U; 2083 1971 new->se_cb_highest_slot = min(battrs->maxreqs - 1, 2084 1972 NFSD_BC_SLOT_TABLE_SIZE - 1); 2085 1973 spin_lock_init(&new->se_lock); 2086 1974 return new; 2087 1975 out_free: 2088 - while (i--) 2089 - kfree(new->se_slots[i]); 1976 + kfree(slot); 1977 + xa_destroy(&new->se_slots); 2090 1978 kfree(new); 2091 1979 return NULL; 2092 1980 } ··· 2149 2123 2150 2124 static void __free_session(struct nfsd4_session *ses) 2151 2125 { 2152 - free_session_slots(ses); 2126 + free_session_slots(ses, 0); 2127 + xa_destroy(&ses->se_slots); 2153 2128 kfree(ses); 2154 2129 } 2155 2130 2156 2131 static void free_session(struct nfsd4_session *ses) 2157 2132 { 2158 2133 nfsd4_del_conns(ses); 2159 - nfsd4_put_drc_mem(&ses->se_fchannel); 2160 2134 __free_session(ses); 2135 + } 2136 + 2137 + static unsigned long 2138 + nfsd_slot_count(struct shrinker *s, struct shrink_control *sc) 2139 + { 2140 + unsigned long cnt = atomic_read(&nfsd_total_target_slots); 2141 + 2142 + return cnt ? cnt : SHRINK_EMPTY; 2143 + } 2144 + 2145 + static unsigned long 2146 + nfsd_slot_scan(struct shrinker *s, struct shrink_control *sc) 2147 + { 2148 + struct nfsd4_session *ses; 2149 + unsigned long scanned = 0; 2150 + unsigned long freed = 0; 2151 + 2152 + spin_lock(&nfsd_session_list_lock); 2153 + list_for_each_entry(ses, &nfsd_session_list, se_all_sessions) { 2154 + freed += reduce_session_slots(ses, 1); 2155 + scanned += 1; 2156 + if (scanned >= sc->nr_to_scan) { 2157 + /* Move starting point for next scan */ 2158 + list_move(&nfsd_session_list, &ses->se_all_sessions); 2159 + break; 2160 + } 2161 + } 2162 + spin_unlock(&nfsd_session_list_lock); 2163 + sc->nr_scanned = scanned; 2164 + return freed; 2161 2165 } 2162 2166 2163 2167 static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses) ··· 2213 2157 spin_lock(&clp->cl_lock); 2214 2158 list_add(&new->se_perclnt, &clp->cl_sessions); 2215 2159 spin_unlock(&clp->cl_lock); 2160 + 2161 + spin_lock(&nfsd_session_list_lock); 2162 + list_add_tail(&new->se_all_sessions, &nfsd_session_list); 2163 + spin_unlock(&nfsd_session_list_lock); 2216 2164 2217 2165 { 2218 2166 struct sockaddr *sa = svc_addr(rqstp); ··· 2287 2227 spin_lock(&ses->se_client->cl_lock); 2288 2228 list_del(&ses->se_perclnt); 2289 2229 spin_unlock(&ses->se_client->cl_lock); 2230 + spin_lock(&nfsd_session_list_lock); 2231 + list_del(&ses->se_all_sessions); 2232 + spin_unlock(&nfsd_session_list_lock); 2290 2233 } 2291 2234 2292 2235 /* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */ ··· 2425 2362 } 2426 2363 list_del_init(&clp->cl_lru); 2427 2364 spin_lock(&clp->cl_lock); 2428 - list_for_each_entry(ses, &clp->cl_sessions, se_perclnt) 2365 + spin_lock(&nfsd_session_list_lock); 2366 + list_for_each_entry(ses, &clp->cl_sessions, se_perclnt) { 2429 2367 list_del_init(&ses->se_hash); 2368 + list_del_init(&ses->se_all_sessions); 2369 + } 2370 + spin_unlock(&nfsd_session_list_lock); 2430 2371 spin_unlock(&clp->cl_lock); 2431 2372 } 2432 2373 ··· 2752 2685 static int client_info_show(struct seq_file *m, void *v) 2753 2686 { 2754 2687 struct inode *inode = file_inode(m->file); 2688 + struct nfsd4_session *ses; 2755 2689 struct nfs4_client *clp; 2756 2690 u64 clid; 2757 2691 ··· 2789 2721 seq_printf(m, "callback address: \"%pISpc\"\n", &clp->cl_cb_conn.cb_addr); 2790 2722 seq_printf(m, "admin-revoked states: %d\n", 2791 2723 atomic_read(&clp->cl_admin_revoked)); 2724 + spin_lock(&clp->cl_lock); 2725 + seq_printf(m, "session slots:"); 2726 + list_for_each_entry(ses, &clp->cl_sessions, se_perclnt) 2727 + seq_printf(m, " %u", ses->se_fchannel.maxreqs); 2728 + seq_printf(m, "\nsession target slots:"); 2729 + list_for_each_entry(ses, &clp->cl_sessions, se_perclnt) 2730 + seq_printf(m, " %u", ses->se_target_maxslots); 2731 + spin_unlock(&clp->cl_lock); 2732 + seq_puts(m, "\n"); 2733 + 2792 2734 drop_client(clp); 2793 2735 2794 2736 return 0; ··· 2951 2873 return 0; 2952 2874 } 2953 2875 2876 + static char *nfs4_show_deleg_type(u32 dl_type) 2877 + { 2878 + switch (dl_type) { 2879 + case OPEN_DELEGATE_READ: 2880 + return "r"; 2881 + case OPEN_DELEGATE_WRITE: 2882 + return "w"; 2883 + case OPEN_DELEGATE_READ_ATTRS_DELEG: 2884 + return "ra"; 2885 + case OPEN_DELEGATE_WRITE_ATTRS_DELEG: 2886 + return "wa"; 2887 + } 2888 + return "?"; 2889 + } 2890 + 2954 2891 static int nfs4_show_deleg(struct seq_file *s, struct nfs4_stid *st) 2955 2892 { 2956 2893 struct nfs4_delegation *ds; ··· 2979 2886 nfs4_show_stateid(s, &st->sc_stateid); 2980 2887 seq_puts(s, ": { type: deleg, "); 2981 2888 2982 - seq_printf(s, "access: %s", 2983 - ds->dl_type == NFS4_OPEN_DELEGATE_READ ? "r" : "w"); 2889 + seq_printf(s, "access: %s", nfs4_show_deleg_type(ds->dl_type)); 2984 2890 2985 2891 /* XXX: lease time, whether it's being recalled. */ 2986 2892 ··· 3800 3708 kfree(exid->server_impl_name); 3801 3709 } 3802 3710 3803 - static __be32 check_slot_seqid(u32 seqid, u32 slot_seqid, bool slot_inuse) 3711 + static __be32 check_slot_seqid(u32 seqid, u32 slot_seqid, u8 flags) 3804 3712 { 3805 3713 /* The slot is in use, and no response has been sent. */ 3806 - if (slot_inuse) { 3714 + if (flags & NFSD4_SLOT_INUSE) { 3807 3715 if (seqid == slot_seqid) 3808 3716 return nfserr_jukebox; 3809 3717 else ··· 3811 3719 } 3812 3720 /* Note unsigned 32-bit arithmetic handles wraparound: */ 3813 3721 if (likely(seqid == slot_seqid + 1)) 3722 + return nfs_ok; 3723 + if ((flags & NFSD4_SLOT_REUSED) && seqid == 1) 3814 3724 return nfs_ok; 3815 3725 if (seqid == slot_seqid) 3816 3726 return nfserr_replay_cache; ··· 3872 3778 ca->maxresp_cached = min_t(u32, ca->maxresp_cached, 3873 3779 NFSD_SLOT_CACHE_SIZE + NFSD_MIN_HDR_SEQ_SZ); 3874 3780 ca->maxreqs = min_t(u32, ca->maxreqs, NFSD_MAX_SLOTS_PER_SESSION); 3875 - /* 3876 - * Note decreasing slot size below client's request may make it 3877 - * difficult for client to function correctly, whereas 3878 - * decreasing the number of slots will (just?) affect 3879 - * performance. When short on memory we therefore prefer to 3880 - * decrease number of slots instead of their size. Clients that 3881 - * request larger slots than they need will get poor results: 3882 - * Note that we always allow at least one slot, because our 3883 - * accounting is soft and provides no guarantees either way. 3884 - */ 3885 - ca->maxreqs = nfsd4_get_drc_mem(ca, nn); 3886 3781 3887 3782 return nfs_ok; 3888 3783 } ··· 3949 3866 return status; 3950 3867 status = check_backchannel_attrs(&cr_ses->back_channel); 3951 3868 if (status) 3952 - goto out_release_drc_mem; 3869 + goto out_err; 3953 3870 status = nfserr_jukebox; 3954 3871 new = alloc_session(&cr_ses->fore_channel, &cr_ses->back_channel); 3955 3872 if (!new) 3956 - goto out_release_drc_mem; 3873 + goto out_err; 3957 3874 conn = alloc_conn_from_crses(rqstp, cr_ses); 3958 3875 if (!conn) 3959 3876 goto out_free_session; ··· 4062 3979 free_conn(conn); 4063 3980 out_free_session: 4064 3981 __free_session(new); 4065 - out_release_drc_mem: 4066 - nfsd4_put_drc_mem(&cr_ses->fore_channel); 3982 + out_err: 4067 3983 return status; 4068 3984 } 4069 3985 ··· 4360 4278 if (seq->slotid >= session->se_fchannel.maxreqs) 4361 4279 goto out_put_session; 4362 4280 4363 - slot = session->se_slots[seq->slotid]; 4281 + slot = xa_load(&session->se_slots, seq->slotid); 4364 4282 dprintk("%s: slotid %d\n", __func__, seq->slotid); 4365 4283 4366 - /* We do not negotiate the number of slots yet, so set the 4367 - * maxslots to the session maxreqs which is used to encode 4368 - * sr_highest_slotid and the sr_target_slot id to maxslots */ 4369 - seq->maxslots = session->se_fchannel.maxreqs; 4370 - 4371 4284 trace_nfsd_slot_seqid_sequence(clp, seq, slot); 4372 - status = check_slot_seqid(seq->seqid, slot->sl_seqid, 4373 - slot->sl_flags & NFSD4_SLOT_INUSE); 4285 + status = check_slot_seqid(seq->seqid, slot->sl_seqid, slot->sl_flags); 4374 4286 if (status == nfserr_replay_cache) { 4375 4287 status = nfserr_seq_misordered; 4376 4288 if (!(slot->sl_flags & NFSD4_SLOT_INITIALIZED)) ··· 4389 4313 if (status) 4390 4314 goto out_put_session; 4391 4315 4316 + if (session->se_target_maxslots < session->se_fchannel.maxreqs && 4317 + slot->sl_generation == session->se_slot_gen && 4318 + seq->maxslots <= session->se_target_maxslots) 4319 + /* Client acknowledged our reduce maxreqs */ 4320 + free_session_slots(session, session->se_target_maxslots); 4321 + 4392 4322 buflen = (seq->cachethis) ? 4393 4323 session->se_fchannel.maxresp_cached : 4394 4324 session->se_fchannel.maxresp_sz; ··· 4405 4323 svc_reserve(rqstp, buflen); 4406 4324 4407 4325 status = nfs_ok; 4408 - /* Success! bump slot seqid */ 4326 + /* Success! accept new slot seqid */ 4409 4327 slot->sl_seqid = seq->seqid; 4328 + slot->sl_flags &= ~NFSD4_SLOT_REUSED; 4410 4329 slot->sl_flags |= NFSD4_SLOT_INUSE; 4330 + slot->sl_generation = session->se_slot_gen; 4411 4331 if (seq->cachethis) 4412 4332 slot->sl_flags |= NFSD4_SLOT_CACHETHIS; 4413 4333 else ··· 4418 4334 cstate->slot = slot; 4419 4335 cstate->session = session; 4420 4336 cstate->clp = clp; 4337 + 4338 + /* 4339 + * If the client ever uses the highest available slot, 4340 + * gently try to allocate another 20%. This allows 4341 + * fairly quick growth without grossly over-shooting what 4342 + * the client might use. 4343 + */ 4344 + if (seq->slotid == session->se_fchannel.maxreqs - 1 && 4345 + session->se_target_maxslots >= session->se_fchannel.maxreqs && 4346 + session->se_fchannel.maxreqs < NFSD_MAX_SLOTS_PER_SESSION) { 4347 + int s = session->se_fchannel.maxreqs; 4348 + int cnt = DIV_ROUND_UP(s, 5); 4349 + void *prev_slot; 4350 + 4351 + do { 4352 + /* 4353 + * GFP_NOWAIT both allows allocation under a 4354 + * spinlock, and only succeeds if there is 4355 + * plenty of memory. 4356 + */ 4357 + slot = kzalloc(slot_bytes(&session->se_fchannel), 4358 + GFP_NOWAIT); 4359 + prev_slot = xa_load(&session->se_slots, s); 4360 + if (xa_is_value(prev_slot) && slot) { 4361 + slot->sl_seqid = xa_to_value(prev_slot); 4362 + slot->sl_flags |= NFSD4_SLOT_REUSED; 4363 + } 4364 + if (slot && 4365 + !xa_is_err(xa_store(&session->se_slots, s, slot, 4366 + GFP_NOWAIT))) { 4367 + s += 1; 4368 + session->se_fchannel.maxreqs = s; 4369 + atomic_add(s - session->se_target_maxslots, 4370 + &nfsd_total_target_slots); 4371 + session->se_target_maxslots = s; 4372 + } else { 4373 + kfree(slot); 4374 + slot = NULL; 4375 + } 4376 + } while (slot && --cnt > 0); 4377 + } 4378 + seq->maxslots = max(session->se_target_maxslots, seq->maxslots); 4379 + seq->target_maxslots = session->se_target_maxslots; 4421 4380 4422 4381 out: 4423 4382 switch (clp->cl_cb_state) { ··· 4866 4739 rp->rp_status = nfserr_serverfault; 4867 4740 rp->rp_buflen = 0; 4868 4741 rp->rp_buf = rp->rp_ibuf; 4869 - atomic_set(&rp->rp_locked, RP_UNLOCKED); 4742 + rp->rp_locked = RP_UNLOCKED; 4870 4743 } 4871 4744 4872 4745 static int nfsd4_cstate_assign_replay(struct nfsd4_compound_state *cstate, ··· 4874 4747 { 4875 4748 if (!nfsd4_has_session(cstate)) { 4876 4749 wait_var_event(&so->so_replay.rp_locked, 4877 - atomic_cmpxchg(&so->so_replay.rp_locked, 4878 - RP_UNLOCKED, RP_LOCKED) != RP_LOCKED); 4879 - if (atomic_read(&so->so_replay.rp_locked) == RP_UNHASHED) 4750 + cmpxchg(&so->so_replay.rp_locked, 4751 + RP_UNLOCKED, RP_LOCKED) != RP_LOCKED); 4752 + if (so->so_replay.rp_locked == RP_UNHASHED) 4880 4753 return -EAGAIN; 4881 4754 cstate->replay_owner = nfs4_get_stateowner(so); 4882 4755 } ··· 4889 4762 4890 4763 if (so != NULL) { 4891 4764 cstate->replay_owner = NULL; 4892 - atomic_set(&so->so_replay.rp_locked, RP_UNLOCKED); 4893 - smp_mb__after_atomic(); 4894 - wake_up_var(&so->so_replay.rp_locked); 4765 + store_release_wake_up(&so->so_replay.rp_locked, RP_UNLOCKED); 4895 4766 nfs4_put_stateowner(so); 4896 4767 } 4897 4768 } ··· 5194 5069 * Some threads with a reference might be waiting for rp_locked, 5195 5070 * so tell them to stop waiting. 5196 5071 */ 5197 - atomic_set(&oo->oo_owner.so_replay.rp_locked, RP_UNHASHED); 5198 - smp_mb__after_atomic(); 5199 - wake_up_var(&oo->oo_owner.so_replay.rp_locked); 5072 + store_release_wake_up(&oo->oo_owner.so_replay.rp_locked, RP_UNHASHED); 5200 5073 wait_event(close_wq, refcount_read(&s->st_stid.sc_count) == 2); 5201 5074 5202 5075 release_all_access(s); ··· 5595 5472 static inline __be32 5596 5473 nfs4_check_delegmode(struct nfs4_delegation *dp, int flags) 5597 5474 { 5598 - if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ)) 5475 + if (!(flags & RD_STATE) && deleg_is_read(dp->dl_type)) 5599 5476 return nfserr_openmode; 5600 5477 else 5601 5478 return nfs_ok; ··· 5827 5704 return clp->cl_minorversion && clp->cl_cb_state == NFSD4_CB_UNKNOWN; 5828 5705 } 5829 5706 5830 - static struct file_lease *nfs4_alloc_init_lease(struct nfs4_delegation *dp, 5831 - int flag) 5707 + static struct file_lease *nfs4_alloc_init_lease(struct nfs4_delegation *dp) 5832 5708 { 5833 5709 struct file_lease *fl; 5834 5710 ··· 5836 5714 return NULL; 5837 5715 fl->fl_lmops = &nfsd_lease_mng_ops; 5838 5716 fl->c.flc_flags = FL_DELEG; 5839 - fl->c.flc_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK; 5717 + fl->c.flc_type = deleg_is_read(dp->dl_type) ? F_RDLCK : F_WRLCK; 5840 5718 fl->c.flc_owner = (fl_owner_t)dp; 5841 5719 fl->c.flc_pid = current->tgid; 5842 5720 fl->c.flc_file = dp->dl_stid.sc_file->fi_deleg_file->nf_file; ··· 5951 5829 nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp, 5952 5830 struct svc_fh *parent) 5953 5831 { 5954 - int status = 0; 5832 + bool deleg_ts = open->op_deleg_want & OPEN4_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS; 5955 5833 struct nfs4_client *clp = stp->st_stid.sc_client; 5956 5834 struct nfs4_file *fp = stp->st_stid.sc_file; 5957 5835 struct nfs4_clnt_odstate *odstate = stp->st_clnt_odstate; 5958 5836 struct nfs4_delegation *dp; 5959 5837 struct nfsd_file *nf = NULL; 5960 5838 struct file_lease *fl; 5839 + int status = 0; 5961 5840 u32 dl_type; 5962 5841 5963 5842 /* ··· 5983 5860 */ 5984 5861 if ((open->op_share_access & NFS4_SHARE_ACCESS_BOTH) == NFS4_SHARE_ACCESS_BOTH) { 5985 5862 nf = find_rw_file(fp); 5986 - dl_type = NFS4_OPEN_DELEGATE_WRITE; 5863 + dl_type = deleg_ts ? OPEN_DELEGATE_WRITE_ATTRS_DELEG : OPEN_DELEGATE_WRITE; 5987 5864 } 5988 5865 5989 5866 /* ··· 5992 5869 */ 5993 5870 if (!nf && (open->op_share_access & NFS4_SHARE_ACCESS_READ)) { 5994 5871 nf = find_readable_file(fp); 5995 - dl_type = NFS4_OPEN_DELEGATE_READ; 5872 + dl_type = deleg_ts ? OPEN_DELEGATE_READ_ATTRS_DELEG : OPEN_DELEGATE_READ; 5996 5873 } 5997 5874 5998 5875 if (!nf) ··· 6024 5901 if (!dp) 6025 5902 goto out_delegees; 6026 5903 6027 - fl = nfs4_alloc_init_lease(dp, dl_type); 5904 + fl = nfs4_alloc_init_lease(dp); 6028 5905 if (!fl) 6029 5906 goto out_clnt_odstate; 6030 5907 ··· 6081 5958 6082 5959 static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status) 6083 5960 { 6084 - open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT; 5961 + open->op_delegate_type = OPEN_DELEGATE_NONE_EXT; 6085 5962 if (status == -EAGAIN) 6086 5963 open->op_why_no_deleg = WND4_CONTENTION; 6087 5964 else { 6088 5965 open->op_why_no_deleg = WND4_RESOURCE; 6089 5966 switch (open->op_deleg_want) { 6090 - case NFS4_SHARE_WANT_READ_DELEG: 6091 - case NFS4_SHARE_WANT_WRITE_DELEG: 6092 - case NFS4_SHARE_WANT_ANY_DELEG: 5967 + case OPEN4_SHARE_ACCESS_WANT_READ_DELEG: 5968 + case OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG: 5969 + case OPEN4_SHARE_ACCESS_WANT_ANY_DELEG: 6093 5970 break; 6094 - case NFS4_SHARE_WANT_CANCEL: 5971 + case OPEN4_SHARE_ACCESS_WANT_CANCEL: 6095 5972 open->op_why_no_deleg = WND4_CANCELLED; 6096 5973 break; 6097 - case NFS4_SHARE_WANT_NO_DELEG: 5974 + case OPEN4_SHARE_ACCESS_WANT_NO_DELEG: 6098 5975 WARN_ON_ONCE(1); 6099 5976 } 6100 5977 } ··· 6150 6027 nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp, 6151 6028 struct svc_fh *currentfh) 6152 6029 { 6153 - struct nfs4_delegation *dp; 6030 + bool deleg_ts = open->op_deleg_want & OPEN4_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS; 6154 6031 struct nfs4_openowner *oo = openowner(stp->st_stateowner); 6155 6032 struct nfs4_client *clp = stp->st_stid.sc_client; 6156 6033 struct svc_fh *parent = NULL; 6157 - int cb_up; 6158 - int status = 0; 6034 + struct nfs4_delegation *dp; 6159 6035 struct kstat stat; 6036 + int status = 0; 6037 + int cb_up; 6160 6038 6161 6039 cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client); 6162 6040 open->op_recall = false; ··· 6198 6074 destroy_delegation(dp); 6199 6075 goto out_no_deleg; 6200 6076 } 6201 - open->op_delegate_type = NFS4_OPEN_DELEGATE_WRITE; 6077 + open->op_delegate_type = deleg_ts ? OPEN_DELEGATE_WRITE_ATTRS_DELEG : 6078 + OPEN_DELEGATE_WRITE; 6202 6079 dp->dl_cb_fattr.ncf_cur_fsize = stat.size; 6203 6080 dp->dl_cb_fattr.ncf_initial_cinfo = nfsd4_change_attribute(&stat); 6204 6081 trace_nfsd_deleg_write(&dp->dl_stid.sc_stateid); 6205 6082 } else { 6206 - open->op_delegate_type = NFS4_OPEN_DELEGATE_READ; 6083 + open->op_delegate_type = deleg_ts ? OPEN_DELEGATE_READ_ATTRS_DELEG : 6084 + OPEN_DELEGATE_READ; 6207 6085 trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid); 6208 6086 } 6209 6087 nfs4_put_stid(&dp->dl_stid); 6210 6088 return; 6211 6089 out_no_deleg: 6212 - open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE; 6090 + open->op_delegate_type = OPEN_DELEGATE_NONE; 6213 6091 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS && 6214 - open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) { 6092 + open->op_delegate_type != OPEN_DELEGATE_NONE) { 6215 6093 dprintk("NFSD: WARNING: refusing delegation reclaim\n"); 6216 6094 open->op_recall = true; 6217 6095 } ··· 6227 6101 static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open, 6228 6102 struct nfs4_delegation *dp) 6229 6103 { 6230 - if (open->op_deleg_want == NFS4_SHARE_WANT_READ_DELEG && 6231 - dp->dl_type == NFS4_OPEN_DELEGATE_WRITE) { 6232 - open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT; 6233 - open->op_why_no_deleg = WND4_NOT_SUPP_DOWNGRADE; 6234 - } else if (open->op_deleg_want == NFS4_SHARE_WANT_WRITE_DELEG && 6235 - dp->dl_type == NFS4_OPEN_DELEGATE_WRITE) { 6236 - open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT; 6237 - open->op_why_no_deleg = WND4_NOT_SUPP_UPGRADE; 6104 + if (deleg_is_write(dp->dl_type)) { 6105 + if (open->op_deleg_want & OPEN4_SHARE_ACCESS_WANT_READ_DELEG) { 6106 + open->op_delegate_type = OPEN_DELEGATE_NONE_EXT; 6107 + open->op_why_no_deleg = WND4_NOT_SUPP_DOWNGRADE; 6108 + } else if (open->op_deleg_want & OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG) { 6109 + open->op_delegate_type = OPEN_DELEGATE_NONE_EXT; 6110 + open->op_why_no_deleg = WND4_NOT_SUPP_UPGRADE; 6111 + } 6238 6112 } 6239 6113 /* Otherwise the client must be confused wanting a delegation 6240 6114 * it already has, therefore we don't return 6241 - * NFS4_OPEN_DELEGATE_NONE_EXT and reason. 6115 + * OPEN_DELEGATE_NONE_EXT and reason. 6242 6116 */ 6117 + } 6118 + 6119 + /* Are we returning only a delegation stateid? */ 6120 + static bool open_xor_delegation(struct nfsd4_open *open) 6121 + { 6122 + if (!(open->op_deleg_want & OPEN4_SHARE_ACCESS_WANT_OPEN_XOR_DELEGATION)) 6123 + return false; 6124 + /* Did we actually get a delegation? */ 6125 + if (!deleg_is_read(open->op_delegate_type) && !deleg_is_write(open->op_delegate_type)) 6126 + return false; 6127 + return true; 6243 6128 } 6244 6129 6245 6130 /** ··· 6338 6201 mutex_unlock(&stp->st_mutex); 6339 6202 6340 6203 if (nfsd4_has_session(&resp->cstate)) { 6341 - if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) { 6342 - open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE_EXT; 6204 + if (open->op_deleg_want & OPEN4_SHARE_ACCESS_WANT_NO_DELEG) { 6205 + open->op_delegate_type = OPEN_DELEGATE_NONE_EXT; 6343 6206 open->op_why_no_deleg = WND4_NOT_WANTED; 6344 6207 goto nodeleg; 6345 6208 } ··· 6350 6213 * OPEN succeeds even if we fail. 6351 6214 */ 6352 6215 nfs4_open_delegation(open, stp, &resp->cstate.current_fh); 6216 + 6217 + /* 6218 + * If there is an existing open stateid, it must be updated and 6219 + * returned. Only respect WANT_OPEN_XOR_DELEGATION when a new 6220 + * open stateid would have to be created. 6221 + */ 6222 + if (new_stp && open_xor_delegation(open)) { 6223 + memcpy(&open->op_stateid, &zero_stateid, sizeof(open->op_stateid)); 6224 + open->op_rflags |= OPEN4_RESULT_NO_OPEN_STATEID; 6225 + release_open_stateid(stp); 6226 + } 6353 6227 nodeleg: 6354 6228 status = nfs_ok; 6355 6229 trace_nfsd_open(&stp->st_stid.sc_stateid); 6356 6230 out: 6357 6231 /* 4.1 client trying to upgrade/downgrade delegation? */ 6358 - if (open->op_delegate_type == NFS4_OPEN_DELEGATE_NONE && dp && 6232 + if (open->op_delegate_type == OPEN_DELEGATE_NONE && dp && 6359 6233 open->op_deleg_want) 6360 6234 nfsd4_deleg_xgrade_none_ext(open, dp); 6361 6235 ··· 6377 6229 /* 6378 6230 * To finish the open response, we just need to set the rflags. 6379 6231 */ 6380 - open->op_rflags = NFS4_OPEN_RESULT_LOCKTYPE_POSIX; 6232 + open->op_rflags |= NFS4_OPEN_RESULT_LOCKTYPE_POSIX; 6381 6233 if (nfsd4_has_session(&resp->cstate)) 6382 6234 open->op_rflags |= NFS4_OPEN_RESULT_MAY_NOTIFY_LOCK; 6383 6235 else if (!(open->op_openowner->oo_flags & NFS4_OO_CONFIRMED)) ··· 8114 7966 struct nfsd4_blocked_lock *nbl = NULL; 8115 7967 struct file_lock *file_lock = NULL; 8116 7968 struct file_lock *conflock = NULL; 8117 - struct super_block *sb; 8118 7969 __be32 status = 0; 8119 7970 int lkflg; 8120 7971 int err; ··· 8133 7986 status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0); 8134 7987 if (status != nfs_ok) 8135 7988 return status; 8136 - sb = cstate->current_fh.fh_dentry->d_sb; 8137 7989 8138 7990 if (lock->lk_is_new) { 8139 7991 if (nfsd4_has_session(cstate)) ··· 8867 8721 } 8868 8722 8869 8723 /* initialization to perform when the nfsd service is started: */ 8870 - 8871 8724 int 8872 8725 nfs4_state_start(void) 8873 8726 { ··· 8875 8730 ret = rhltable_init(&nfs4_file_rhltable, &nfs4_file_rhash_params); 8876 8731 if (ret) 8877 8732 return ret; 8733 + 8734 + nfsd_slot_shrinker = shrinker_alloc(0, "nfsd-DRC-slot"); 8735 + if (!nfsd_slot_shrinker) { 8736 + rhltable_destroy(&nfs4_file_rhltable); 8737 + return -ENOMEM; 8738 + } 8739 + nfsd_slot_shrinker->count_objects = nfsd_slot_count; 8740 + nfsd_slot_shrinker->scan_objects = nfsd_slot_scan; 8741 + shrinker_register(nfsd_slot_shrinker); 8878 8742 8879 8743 set_max_delegations(); 8880 8744 return 0; ··· 8926 8772 nfs4_state_shutdown(void) 8927 8773 { 8928 8774 rhltable_destroy(&nfs4_file_rhltable); 8775 + shrinker_free(nfsd_slot_shrinker); 8929 8776 } 8930 8777 8931 8778 static void ··· 9044 8889 } 9045 8890 9046 8891 /** 8892 + * set_cb_time - vet and set the timespec for a cb_getattr update 8893 + * @cb: timestamp from the CB_GETATTR response 8894 + * @orig: original timestamp in the inode 8895 + * @now: current time 8896 + * 8897 + * Given a timestamp in a CB_GETATTR response, check it against the 8898 + * current timestamp in the inode and the current time. Returns true 8899 + * if the inode's timestamp needs to be updated, and false otherwise. 8900 + * @cb may also be changed if the timestamp needs to be clamped. 8901 + */ 8902 + static bool set_cb_time(struct timespec64 *cb, const struct timespec64 *orig, 8903 + const struct timespec64 *now) 8904 + { 8905 + 8906 + /* 8907 + * "When the time presented is before the original time, then the 8908 + * update is ignored." Also no need to update if there is no change. 8909 + */ 8910 + if (timespec64_compare(cb, orig) <= 0) 8911 + return false; 8912 + 8913 + /* 8914 + * "When the time presented is in the future, the server can either 8915 + * clamp the new time to the current time, or it may 8916 + * return NFS4ERR_DELAY to the client, allowing it to retry." 8917 + */ 8918 + if (timespec64_compare(cb, now) > 0) { 8919 + /* clamp it */ 8920 + *cb = *now; 8921 + } 8922 + 8923 + return true; 8924 + } 8925 + 8926 + static int cb_getattr_update_times(struct dentry *dentry, struct nfs4_delegation *dp) 8927 + { 8928 + struct inode *inode = d_inode(dentry); 8929 + struct timespec64 now = current_time(inode); 8930 + struct nfs4_cb_fattr *ncf = &dp->dl_cb_fattr; 8931 + struct iattr attrs = { }; 8932 + int ret; 8933 + 8934 + if (deleg_attrs_deleg(dp->dl_type)) { 8935 + struct timespec64 atime = inode_get_atime(inode); 8936 + struct timespec64 mtime = inode_get_mtime(inode); 8937 + 8938 + attrs.ia_atime = ncf->ncf_cb_atime; 8939 + attrs.ia_mtime = ncf->ncf_cb_mtime; 8940 + 8941 + if (set_cb_time(&attrs.ia_atime, &atime, &now)) 8942 + attrs.ia_valid |= ATTR_ATIME | ATTR_ATIME_SET; 8943 + 8944 + if (set_cb_time(&attrs.ia_mtime, &mtime, &now)) { 8945 + attrs.ia_valid |= ATTR_CTIME | ATTR_MTIME | ATTR_MTIME_SET; 8946 + attrs.ia_ctime = attrs.ia_mtime; 8947 + } 8948 + } else { 8949 + attrs.ia_valid |= ATTR_MTIME | ATTR_CTIME; 8950 + attrs.ia_mtime = attrs.ia_ctime = now; 8951 + } 8952 + 8953 + if (!attrs.ia_valid) 8954 + return 0; 8955 + 8956 + attrs.ia_valid |= ATTR_DELEG; 8957 + inode_lock(inode); 8958 + ret = notify_change(&nop_mnt_idmap, dentry, &attrs, NULL); 8959 + inode_unlock(inode); 8960 + return ret; 8961 + } 8962 + 8963 + /** 9047 8964 * nfsd4_deleg_getattr_conflict - Recall if GETATTR causes conflict 9048 8965 * @rqstp: RPC transaction context 9049 8966 * @dentry: dentry of inode to be checked for a conflict ··· 9141 8914 struct file_lock_context *ctx; 9142 8915 struct nfs4_delegation *dp = NULL; 9143 8916 struct file_lease *fl; 9144 - struct iattr attrs; 9145 8917 struct nfs4_cb_fattr *ncf; 9146 8918 struct inode *inode = d_inode(dentry); 9147 8919 ··· 9202 8976 * not update the file's metadata with the client's 9203 8977 * modified size 9204 8978 */ 9205 - attrs.ia_mtime = attrs.ia_ctime = current_time(inode); 9206 - attrs.ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_DELEG; 9207 - inode_lock(inode); 9208 - err = notify_change(&nop_mnt_idmap, dentry, &attrs, NULL); 9209 - inode_unlock(inode); 8979 + err = cb_getattr_update_times(dentry, dp); 9210 8980 if (err) { 9211 8981 status = nfserrno(err); 9212 8982 goto out_status;
+222 -116
fs/nfsd/nfs4xdr.c
··· 55 55 #include "netns.h" 56 56 #include "pnfs.h" 57 57 #include "filecache.h" 58 + #include "nfs4xdr_gen.h" 58 59 59 60 #include "trace.h" 60 61 ··· 520 519 return nfserr_bad_xdr; 521 520 *umask = mask & S_IRWXUGO; 522 521 iattr->ia_valid |= ATTR_MODE; 522 + } 523 + if (bmval[2] & FATTR4_WORD2_TIME_DELEG_ACCESS) { 524 + fattr4_time_deleg_access access; 525 + 526 + if (!xdrgen_decode_fattr4_time_deleg_access(argp->xdr, &access)) 527 + return nfserr_bad_xdr; 528 + iattr->ia_atime.tv_sec = access.seconds; 529 + iattr->ia_atime.tv_nsec = access.nseconds; 530 + iattr->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET | ATTR_DELEG; 531 + } 532 + if (bmval[2] & FATTR4_WORD2_TIME_DELEG_MODIFY) { 533 + fattr4_time_deleg_modify modify; 534 + 535 + if (!xdrgen_decode_fattr4_time_deleg_modify(argp->xdr, &modify)) 536 + return nfserr_bad_xdr; 537 + iattr->ia_mtime.tv_sec = modify.seconds; 538 + iattr->ia_mtime.tv_nsec = modify.nseconds; 539 + iattr->ia_ctime.tv_sec = modify.seconds; 540 + iattr->ia_ctime.tv_nsec = modify.seconds; 541 + iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME | ATTR_MTIME_SET | ATTR_DELEG; 523 542 } 524 543 525 544 /* request sanity: did attrlist4 contain the expected number of words? */ ··· 1087 1066 return nfs_ok; 1088 1067 if (!argp->minorversion) 1089 1068 return nfserr_bad_xdr; 1090 - switch (w & NFS4_SHARE_WANT_MASK) { 1091 - case NFS4_SHARE_WANT_NO_PREFERENCE: 1092 - case NFS4_SHARE_WANT_READ_DELEG: 1093 - case NFS4_SHARE_WANT_WRITE_DELEG: 1094 - case NFS4_SHARE_WANT_ANY_DELEG: 1095 - case NFS4_SHARE_WANT_NO_DELEG: 1096 - case NFS4_SHARE_WANT_CANCEL: 1069 + switch (w & NFS4_SHARE_WANT_TYPE_MASK) { 1070 + case OPEN4_SHARE_ACCESS_WANT_NO_PREFERENCE: 1071 + case OPEN4_SHARE_ACCESS_WANT_READ_DELEG: 1072 + case OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG: 1073 + case OPEN4_SHARE_ACCESS_WANT_ANY_DELEG: 1074 + case OPEN4_SHARE_ACCESS_WANT_NO_DELEG: 1075 + case OPEN4_SHARE_ACCESS_WANT_CANCEL: 1097 1076 break; 1098 1077 default: 1099 1078 return nfserr_bad_xdr; ··· 1905 1884 return nfserr_bad_xdr; 1906 1885 seq->seqid = be32_to_cpup(p++); 1907 1886 seq->slotid = be32_to_cpup(p++); 1908 - seq->maxslots = be32_to_cpup(p++); 1887 + /* sa_highest_slotid counts from 0 but maxslots counts from 1 ... */ 1888 + seq->maxslots = be32_to_cpup(p++) + 1; 1909 1889 seq->cachethis = be32_to_cpup(p); 1910 1890 1911 1891 seq->status_flags = 0; ··· 2941 2919 struct kstat stat; 2942 2920 struct kstatfs statfs; 2943 2921 struct nfs4_acl *acl; 2922 + u64 change_attr; 2944 2923 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL 2945 2924 struct lsm_context context; 2946 2925 #endif ··· 3040 3017 const struct nfsd4_fattr_args *args) 3041 3018 { 3042 3019 const struct svc_export *exp = args->exp; 3043 - u64 c; 3044 3020 3045 3021 if (unlikely(exp->ex_flags & NFSEXP_V4ROOT)) { 3046 3022 u32 flush_time = convert_to_wallclock(exp->cd->flush_time); ··· 3050 3028 return nfserr_resource; 3051 3029 return nfs_ok; 3052 3030 } 3053 - 3054 - c = nfsd4_change_attribute(&args->stat); 3055 - return nfsd4_encode_changeid4(xdr, c); 3031 + return nfsd4_encode_changeid4(xdr, args->change_attr); 3056 3032 } 3057 3033 3058 3034 static __be32 nfsd4_encode_fattr4_size(struct xdr_stream *xdr, ··· 3407 3387 return nfsd4_encode_bool(xdr, err == 0); 3408 3388 } 3409 3389 3390 + #define NFSD_OA_SHARE_ACCESS (BIT(OPEN_ARGS_SHARE_ACCESS_READ) | \ 3391 + BIT(OPEN_ARGS_SHARE_ACCESS_WRITE) | \ 3392 + BIT(OPEN_ARGS_SHARE_ACCESS_BOTH)) 3393 + 3394 + #define NFSD_OA_SHARE_DENY (BIT(OPEN_ARGS_SHARE_DENY_NONE) | \ 3395 + BIT(OPEN_ARGS_SHARE_DENY_READ) | \ 3396 + BIT(OPEN_ARGS_SHARE_DENY_WRITE) | \ 3397 + BIT(OPEN_ARGS_SHARE_DENY_BOTH)) 3398 + 3399 + #define NFSD_OA_SHARE_ACCESS_WANT (BIT(OPEN_ARGS_SHARE_ACCESS_WANT_ANY_DELEG) | \ 3400 + BIT(OPEN_ARGS_SHARE_ACCESS_WANT_NO_DELEG) | \ 3401 + BIT(OPEN_ARGS_SHARE_ACCESS_WANT_CANCEL) | \ 3402 + BIT(OPEN_ARGS_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS) | \ 3403 + BIT(OPEN_ARGS_SHARE_ACCESS_WANT_OPEN_XOR_DELEGATION)) 3404 + 3405 + #define NFSD_OA_OPEN_CLAIM (BIT(OPEN_ARGS_OPEN_CLAIM_NULL) | \ 3406 + BIT(OPEN_ARGS_OPEN_CLAIM_PREVIOUS) | \ 3407 + BIT(OPEN_ARGS_OPEN_CLAIM_DELEGATE_CUR) | \ 3408 + BIT(OPEN_ARGS_OPEN_CLAIM_DELEGATE_PREV)| \ 3409 + BIT(OPEN_ARGS_OPEN_CLAIM_FH) | \ 3410 + BIT(OPEN_ARGS_OPEN_CLAIM_DELEG_CUR_FH) | \ 3411 + BIT(OPEN_ARGS_OPEN_CLAIM_DELEG_PREV_FH)) 3412 + 3413 + #define NFSD_OA_CREATE_MODE (BIT(OPEN_ARGS_CREATEMODE_UNCHECKED4) | \ 3414 + BIT(OPEN_ARGS_CREATE_MODE_GUARDED) | \ 3415 + BIT(OPEN_ARGS_CREATEMODE_EXCLUSIVE4) | \ 3416 + BIT(OPEN_ARGS_CREATE_MODE_EXCLUSIVE4_1)) 3417 + 3418 + static uint32_t oa_share_access = NFSD_OA_SHARE_ACCESS; 3419 + static uint32_t oa_share_deny = NFSD_OA_SHARE_DENY; 3420 + static uint32_t oa_share_access_want = NFSD_OA_SHARE_ACCESS_WANT; 3421 + static uint32_t oa_open_claim = NFSD_OA_OPEN_CLAIM; 3422 + static uint32_t oa_create_mode = NFSD_OA_CREATE_MODE; 3423 + 3424 + static const struct open_arguments4 nfsd_open_arguments = { 3425 + .oa_share_access = { .count = 1, .element = &oa_share_access }, 3426 + .oa_share_deny = { .count = 1, .element = &oa_share_deny }, 3427 + .oa_share_access_want = { .count = 1, .element = &oa_share_access_want }, 3428 + .oa_open_claim = { .count = 1, .element = &oa_open_claim }, 3429 + .oa_create_mode = { .count = 1, .element = &oa_create_mode }, 3430 + }; 3431 + 3432 + static __be32 nfsd4_encode_fattr4_open_arguments(struct xdr_stream *xdr, 3433 + const struct nfsd4_fattr_args *args) 3434 + { 3435 + if (!xdrgen_encode_fattr4_open_arguments(xdr, &nfsd_open_arguments)) 3436 + return nfserr_resource; 3437 + return nfs_ok; 3438 + } 3439 + 3410 3440 static const nfsd4_enc_attr nfsd4_enc_fattr4_encode_ops[] = { 3411 3441 [FATTR4_SUPPORTED_ATTRS] = nfsd4_encode_fattr4_supported_attrs, 3412 3442 [FATTR4_TYPE] = nfsd4_encode_fattr4_type, ··· 3557 3487 3558 3488 [FATTR4_MODE_UMASK] = nfsd4_encode_fattr4__noop, 3559 3489 [FATTR4_XATTR_SUPPORT] = nfsd4_encode_fattr4_xattr_support, 3490 + [FATTR4_OPEN_ARGUMENTS] = nfsd4_encode_fattr4_open_arguments, 3560 3491 }; 3561 3492 3562 3493 /* ··· 3575 3504 struct nfsd4_fattr_args args; 3576 3505 struct svc_fh *tempfh = NULL; 3577 3506 int starting_len = xdr->buf->len; 3578 - __be32 *attrlen_p, status; 3579 - int attrlen_offset; 3507 + unsigned int attrlen_offset; 3508 + __be32 attrlen, status; 3580 3509 u32 attrmask[3]; 3581 3510 int err; 3582 3511 struct nfsd4_compoundres *resp = rqstp->rq_resp; ··· 3613 3542 if (status) 3614 3543 goto out; 3615 3544 } 3616 - if (attrmask[0] & (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE)) { 3545 + if ((attrmask[0] & (FATTR4_WORD0_CHANGE | 3546 + FATTR4_WORD0_SIZE)) || 3547 + (attrmask[1] & (FATTR4_WORD1_TIME_ACCESS | 3548 + FATTR4_WORD1_TIME_MODIFY | 3549 + FATTR4_WORD1_TIME_METADATA))) { 3617 3550 status = nfsd4_deleg_getattr_conflict(rqstp, dentry, &dp); 3618 3551 if (status) 3619 3552 goto out; ··· 3629 3554 if (dp) { 3630 3555 struct nfs4_cb_fattr *ncf = &dp->dl_cb_fattr; 3631 3556 3632 - if (ncf->ncf_file_modified) 3557 + if (ncf->ncf_file_modified) { 3558 + ++ncf->ncf_initial_cinfo; 3633 3559 args.stat.size = ncf->ncf_cur_fsize; 3560 + if (!timespec64_is_epoch(&ncf->ncf_cb_mtime)) 3561 + args.stat.mtime = ncf->ncf_cb_mtime; 3562 + } 3563 + args.change_attr = ncf->ncf_initial_cinfo; 3564 + 3565 + if (!timespec64_is_epoch(&ncf->ncf_cb_atime)) 3566 + args.stat.atime = ncf->ncf_cb_atime; 3634 3567 3635 3568 nfs4_put_stid(&dp->dl_stid); 3569 + } else { 3570 + args.change_attr = nfsd4_change_attribute(&args.stat); 3636 3571 } 3572 + 3637 3573 if (err) 3638 3574 goto out_nfserr; 3639 3575 ··· 3712 3626 3713 3627 /* attr_vals */ 3714 3628 attrlen_offset = xdr->buf->len; 3715 - attrlen_p = xdr_reserve_space(xdr, XDR_UNIT); 3716 - if (!attrlen_p) 3629 + if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT))) 3717 3630 goto out_resource; 3718 3631 bitmap_from_arr32(attr_bitmap, attrmask, 3719 3632 ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops)); ··· 3722 3637 if (status != nfs_ok) 3723 3638 goto out; 3724 3639 } 3725 - *attrlen_p = cpu_to_be32(xdr->buf->len - attrlen_offset - XDR_UNIT); 3640 + attrlen = cpu_to_be32(xdr->buf->len - attrlen_offset - XDR_UNIT); 3641 + write_bytes_to_xdr_buf(xdr->buf, attrlen_offset, &attrlen, XDR_UNIT); 3726 3642 status = nfs_ok; 3727 3643 3728 3644 out: ··· 4313 4227 if (xdr_stream_encode_u32(xdr, open->op_delegate_type) != XDR_UNIT) 4314 4228 return nfserr_resource; 4315 4229 switch (open->op_delegate_type) { 4316 - case NFS4_OPEN_DELEGATE_NONE: 4230 + case OPEN_DELEGATE_NONE: 4317 4231 status = nfs_ok; 4318 4232 break; 4319 - case NFS4_OPEN_DELEGATE_READ: 4233 + case OPEN_DELEGATE_READ: 4234 + case OPEN_DELEGATE_READ_ATTRS_DELEG: 4320 4235 /* read */ 4321 4236 status = nfsd4_encode_open_read_delegation4(xdr, open); 4322 4237 break; 4323 - case NFS4_OPEN_DELEGATE_WRITE: 4238 + case OPEN_DELEGATE_WRITE: 4239 + case OPEN_DELEGATE_WRITE_ATTRS_DELEG: 4324 4240 /* write */ 4325 4241 status = nfsd4_encode_open_write_delegation4(xdr, open); 4326 4242 break; 4327 - case NFS4_OPEN_DELEGATE_NONE_EXT: 4243 + case OPEN_DELEGATE_NONE_EXT: 4328 4244 /* od_whynone */ 4329 4245 status = nfsd4_encode_open_none_delegation4(xdr, open); 4330 4246 break; ··· 4401 4313 struct xdr_buf *buf = xdr->buf; 4402 4314 int status, space_left; 4403 4315 __be32 nfserr; 4316 + 4317 + /* 4318 + * Splice read doesn't work if encoding has already wandered 4319 + * into the XDR buf's page array. 4320 + */ 4321 + if (unlikely(xdr->buf->page_len)) { 4322 + WARN_ON_ONCE(1); 4323 + return nfserr_serverfault; 4324 + } 4404 4325 4405 4326 /* 4406 4327 * Make sure there is room at the end of buf->head for ··· 4493 4396 struct nfsd4_compoundargs *argp = resp->rqstp->rq_argp; 4494 4397 struct nfsd4_read *read = &u->read; 4495 4398 struct xdr_stream *xdr = resp->xdr; 4496 - int starting_len = xdr->buf->len; 4497 4399 bool splice_ok = argp->splice_ok; 4400 + unsigned int eof_offset; 4498 4401 unsigned long maxcount; 4402 + __be32 wire_data[2]; 4499 4403 struct file *file; 4500 - __be32 *p; 4501 4404 4502 4405 if (nfserr) 4503 4406 return nfserr; 4407 + 4408 + eof_offset = xdr->buf->len; 4504 4409 file = read->rd_nf->nf_file; 4505 4410 4506 - p = xdr_reserve_space(xdr, 8); /* eof flag and byte count */ 4507 - if (!p) { 4411 + /* Reserve space for the eof flag and byte count */ 4412 + if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT * 2))) { 4508 4413 WARN_ON_ONCE(splice_ok); 4509 4414 return nfserr_resource; 4510 - } 4511 - if (resp->xdr->buf->page_len && splice_ok) { 4512 - WARN_ON_ONCE(1); 4513 - return nfserr_serverfault; 4514 4415 } 4515 4416 xdr_commit_encode(xdr); 4516 4417 ··· 4520 4425 else 4521 4426 nfserr = nfsd4_encode_readv(resp, read, file, maxcount); 4522 4427 if (nfserr) { 4523 - xdr_truncate_encode(xdr, starting_len); 4428 + xdr_truncate_encode(xdr, eof_offset); 4524 4429 return nfserr; 4525 4430 } 4526 4431 4527 - p = xdr_encode_bool(p, read->rd_eof); 4528 - *p = cpu_to_be32(read->rd_length); 4432 + wire_data[0] = read->rd_eof ? xdr_one : xdr_zero; 4433 + wire_data[1] = cpu_to_be32(read->rd_length); 4434 + write_bytes_to_xdr_buf(xdr->buf, eof_offset, &wire_data, XDR_UNIT * 2); 4529 4435 return nfs_ok; 4530 4436 } 4531 4437 ··· 4535 4439 union nfsd4_op_u *u) 4536 4440 { 4537 4441 struct nfsd4_readlink *readlink = &u->readlink; 4538 - __be32 *p, *maxcount_p, zero = xdr_zero; 4442 + __be32 *p, wire_count, zero = xdr_zero; 4539 4443 struct xdr_stream *xdr = resp->xdr; 4540 - int length_offset = xdr->buf->len; 4444 + unsigned int length_offset; 4541 4445 int maxcount, status; 4542 4446 4543 - maxcount_p = xdr_reserve_space(xdr, XDR_UNIT); 4544 - if (!maxcount_p) 4447 + /* linktext4.count */ 4448 + length_offset = xdr->buf->len; 4449 + if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT))) 4545 4450 return nfserr_resource; 4546 - maxcount = PAGE_SIZE; 4547 4451 4452 + /* linktext4.data */ 4453 + maxcount = PAGE_SIZE; 4548 4454 p = xdr_reserve_space(xdr, maxcount); 4549 4455 if (!p) 4550 4456 return nfserr_resource; 4551 - /* 4552 - * XXX: By default, vfs_readlink() will truncate symlinks if they 4553 - * would overflow the buffer. Is this kosher in NFSv4? If not, one 4554 - * easy fix is: if vfs_readlink() precisely fills the buffer, assume 4555 - * that truncation occurred, and return NFS4ERR_RESOURCE. 4556 - */ 4557 4457 nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, 4558 4458 (char *)p, &maxcount); 4559 4459 if (nfserr == nfserr_isdir) ··· 4562 4470 nfserr = nfserrno(status); 4563 4471 goto out_err; 4564 4472 } 4565 - *maxcount_p = cpu_to_be32(maxcount); 4473 + 4474 + wire_count = cpu_to_be32(maxcount); 4475 + write_bytes_to_xdr_buf(xdr->buf, length_offset, &wire_count, XDR_UNIT); 4566 4476 xdr_truncate_encode(xdr, length_offset + 4 + xdr_align_size(maxcount)); 4567 4477 write_bytes_to_xdr_buf(xdr->buf, length_offset + 4 + maxcount, &zero, 4568 4478 xdr_pad_size(maxcount)); ··· 4699 4605 } 4700 4606 4701 4607 static __be32 4702 - nfsd4_do_encode_secinfo(struct xdr_stream *xdr, struct svc_export *exp) 4608 + nfsd4_encode_secinfo4(struct xdr_stream *xdr, rpc_authflavor_t pf, 4609 + u32 *supported) 4610 + { 4611 + struct rpcsec_gss_info info; 4612 + __be32 status; 4613 + 4614 + if (rpcauth_get_gssinfo(pf, &info) == 0) { 4615 + (*supported)++; 4616 + 4617 + /* flavor */ 4618 + status = nfsd4_encode_uint32_t(xdr, RPC_AUTH_GSS); 4619 + if (status != nfs_ok) 4620 + return status; 4621 + /* flavor_info */ 4622 + status = nfsd4_encode_rpcsec_gss_info(xdr, &info); 4623 + if (status != nfs_ok) 4624 + return status; 4625 + } else if (pf < RPC_AUTH_MAXFLAVOR) { 4626 + (*supported)++; 4627 + 4628 + /* flavor */ 4629 + status = nfsd4_encode_uint32_t(xdr, pf); 4630 + if (status != nfs_ok) 4631 + return status; 4632 + } 4633 + return nfs_ok; 4634 + } 4635 + 4636 + static __be32 4637 + nfsd4_encode_SECINFO4resok(struct xdr_stream *xdr, struct svc_export *exp) 4703 4638 { 4704 4639 u32 i, nflavs, supported; 4705 4640 struct exp_flavor_info *flavs; 4706 4641 struct exp_flavor_info def_flavs[2]; 4707 - static bool report = true; 4708 - __be32 *flavorsp; 4709 - __be32 status; 4642 + unsigned int count_offset; 4643 + __be32 status, wire_count; 4710 4644 4711 4645 if (exp->ex_nflavors) { 4712 4646 flavs = exp->ex_flavors; ··· 4756 4634 } 4757 4635 } 4758 4636 4759 - supported = 0; 4760 - flavorsp = xdr_reserve_space(xdr, XDR_UNIT); 4761 - if (!flavorsp) 4637 + count_offset = xdr->buf->len; 4638 + if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT))) 4762 4639 return nfserr_resource; 4763 4640 4764 - for (i = 0; i < nflavs; i++) { 4765 - rpc_authflavor_t pf = flavs[i].pseudoflavor; 4766 - struct rpcsec_gss_info info; 4767 - 4768 - if (rpcauth_get_gssinfo(pf, &info) == 0) { 4769 - supported++; 4770 - 4771 - /* flavor */ 4772 - status = nfsd4_encode_uint32_t(xdr, RPC_AUTH_GSS); 4773 - if (status != nfs_ok) 4774 - return status; 4775 - /* flavor_info */ 4776 - status = nfsd4_encode_rpcsec_gss_info(xdr, &info); 4777 - if (status != nfs_ok) 4778 - return status; 4779 - } else if (pf < RPC_AUTH_MAXFLAVOR) { 4780 - supported++; 4781 - 4782 - /* flavor */ 4783 - status = nfsd4_encode_uint32_t(xdr, pf); 4784 - if (status != nfs_ok) 4785 - return status; 4786 - } else { 4787 - if (report) 4788 - pr_warn("NFS: SECINFO: security flavor %u " 4789 - "is not supported\n", pf); 4790 - } 4641 + for (i = 0, supported = 0; i < nflavs; i++) { 4642 + status = nfsd4_encode_secinfo4(xdr, flavs[i].pseudoflavor, 4643 + &supported); 4644 + if (status != nfs_ok) 4645 + return status; 4791 4646 } 4792 4647 4793 - if (nflavs != supported) 4794 - report = false; 4795 - *flavorsp = cpu_to_be32(supported); 4648 + wire_count = cpu_to_be32(supported); 4649 + write_bytes_to_xdr_buf(xdr->buf, count_offset, &wire_count, 4650 + XDR_UNIT); 4796 4651 return 0; 4797 4652 } 4798 4653 ··· 4780 4681 struct nfsd4_secinfo *secinfo = &u->secinfo; 4781 4682 struct xdr_stream *xdr = resp->xdr; 4782 4683 4783 - return nfsd4_do_encode_secinfo(xdr, secinfo->si_exp); 4684 + return nfsd4_encode_SECINFO4resok(xdr, secinfo->si_exp); 4784 4685 } 4785 4686 4786 4687 static __be32 ··· 4790 4691 struct nfsd4_secinfo_no_name *secinfo = &u->secinfo_no_name; 4791 4692 struct xdr_stream *xdr = resp->xdr; 4792 4693 4793 - return nfsd4_do_encode_secinfo(xdr, secinfo->sin_exp); 4694 + return nfsd4_encode_SECINFO4resok(xdr, secinfo->sin_exp); 4794 4695 } 4795 4696 4796 4697 static __be32 ··· 5065 4966 if (nfserr != nfs_ok) 5066 4967 return nfserr; 5067 4968 /* sr_target_highest_slotid */ 5068 - nfserr = nfsd4_encode_slotid4(xdr, seq->maxslots - 1); 4969 + nfserr = nfsd4_encode_slotid4(xdr, seq->target_maxslots - 1); 5069 4970 if (nfserr != nfs_ok) 5070 4971 return nfserr; 5071 4972 /* sr_status_flags */ ··· 5393 5294 struct file *file = read->rd_nf->nf_file; 5394 5295 struct xdr_stream *xdr = resp->xdr; 5395 5296 bool splice_ok = argp->splice_ok; 5297 + unsigned int offset_offset; 5298 + __be32 nfserr, wire_count; 5396 5299 unsigned long maxcount; 5397 - __be32 nfserr, *p; 5300 + __be64 wire_offset; 5398 5301 5399 - /* Content type, offset, byte count */ 5400 - p = xdr_reserve_space(xdr, 4 + 8 + 4); 5401 - if (!p) 5302 + if (xdr_stream_encode_u32(xdr, NFS4_CONTENT_DATA) != XDR_UNIT) 5402 5303 return nfserr_io; 5403 - if (resp->xdr->buf->page_len && splice_ok) { 5404 - WARN_ON_ONCE(splice_ok); 5405 - return nfserr_serverfault; 5406 - } 5304 + 5305 + offset_offset = xdr->buf->len; 5306 + 5307 + /* Reserve space for the byte offset and count */ 5308 + if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT * 3))) 5309 + return nfserr_io; 5310 + xdr_commit_encode(xdr); 5407 5311 5408 5312 maxcount = min_t(unsigned long, read->rd_length, 5409 5313 (xdr->buf->buflen - xdr->buf->len)); ··· 5418 5316 if (nfserr) 5419 5317 return nfserr; 5420 5318 5421 - *p++ = cpu_to_be32(NFS4_CONTENT_DATA); 5422 - p = xdr_encode_hyper(p, read->rd_offset); 5423 - *p = cpu_to_be32(read->rd_length); 5424 - 5319 + wire_offset = cpu_to_be64(read->rd_offset); 5320 + write_bytes_to_xdr_buf(xdr->buf, offset_offset, &wire_offset, 5321 + XDR_UNIT * 2); 5322 + wire_count = cpu_to_be32(read->rd_length); 5323 + write_bytes_to_xdr_buf(xdr->buf, offset_offset + XDR_UNIT * 2, 5324 + &wire_count, XDR_UNIT); 5425 5325 return nfs_ok; 5426 5326 } 5427 5327 ··· 5434 5330 struct nfsd4_read *read = &u->read; 5435 5331 struct file *file = read->rd_nf->nf_file; 5436 5332 struct xdr_stream *xdr = resp->xdr; 5437 - int starting_len = xdr->buf->len; 5333 + unsigned int eof_offset; 5334 + __be32 wire_data[2]; 5438 5335 u32 segments = 0; 5439 - __be32 *p; 5440 5336 5441 5337 if (nfserr) 5442 5338 return nfserr; 5443 5339 5444 - /* eof flag, segment count */ 5445 - p = xdr_reserve_space(xdr, 4 + 4); 5446 - if (!p) 5340 + eof_offset = xdr->buf->len; 5341 + 5342 + /* Reserve space for the eof flag and segment count */ 5343 + if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT * 2))) 5447 5344 return nfserr_io; 5448 5345 xdr_commit_encode(xdr); 5449 5346 ··· 5454 5349 5455 5350 nfserr = nfsd4_encode_read_plus_data(resp, read); 5456 5351 if (nfserr) { 5457 - xdr_truncate_encode(xdr, starting_len); 5352 + xdr_truncate_encode(xdr, eof_offset); 5458 5353 return nfserr; 5459 5354 } 5460 5355 5461 5356 segments++; 5462 5357 5463 5358 out: 5464 - p = xdr_encode_bool(p, read->rd_eof); 5465 - *p = cpu_to_be32(segments); 5359 + wire_data[0] = read->rd_eof ? xdr_one : xdr_zero; 5360 + wire_data[1] = cpu_to_be32(segments); 5361 + write_bytes_to_xdr_buf(xdr->buf, eof_offset, &wire_data, XDR_UNIT * 2); 5466 5362 return nfserr; 5467 5363 } 5468 5364 ··· 5864 5758 struct nfs4_stateowner *so = resp->cstate.replay_owner; 5865 5759 struct svc_rqst *rqstp = resp->rqstp; 5866 5760 const struct nfsd4_operation *opdesc = op->opdesc; 5867 - int post_err_offset; 5761 + unsigned int op_status_offset; 5868 5762 nfsd4_enc encoder; 5869 - __be32 *p; 5870 5763 5871 - p = xdr_reserve_space(xdr, 8); 5872 - if (!p) 5764 + if (xdr_stream_encode_u32(xdr, op->opnum) != XDR_UNIT) 5873 5765 goto release; 5874 - *p++ = cpu_to_be32(op->opnum); 5875 - post_err_offset = xdr->buf->len; 5766 + op_status_offset = xdr->buf->len; 5767 + if (!xdr_reserve_space(xdr, XDR_UNIT)) 5768 + goto release; 5876 5769 5877 5770 if (op->opnum == OP_ILLEGAL) 5878 5771 goto status; ··· 5912 5807 * bug if we had to do this on a non-idempotent op: 5913 5808 */ 5914 5809 warn_on_nonidempotent_op(op); 5915 - xdr_truncate_encode(xdr, post_err_offset); 5810 + xdr_truncate_encode(xdr, op_status_offset + XDR_UNIT); 5916 5811 } 5917 5812 if (so) { 5918 - int len = xdr->buf->len - post_err_offset; 5813 + int len = xdr->buf->len - (op_status_offset + XDR_UNIT); 5919 5814 5920 5815 so->so_replay.rp_status = op->status; 5921 5816 so->so_replay.rp_buflen = len; 5922 - read_bytes_from_xdr_buf(xdr->buf, post_err_offset, 5817 + read_bytes_from_xdr_buf(xdr->buf, op_status_offset + XDR_UNIT, 5923 5818 so->so_replay.rp_buf, len); 5924 5819 } 5925 5820 status: 5926 5821 op->status = nfsd4_map_status(op->status, 5927 5822 resp->cstate.minorversion); 5928 - *p = op->status; 5823 + write_bytes_to_xdr_buf(xdr->buf, op_status_offset, 5824 + &op->status, XDR_UNIT); 5929 5825 release: 5930 5826 if (opdesc && opdesc->op_release) 5931 5827 opdesc->op_release(&op->u);
+256
fs/nfsd/nfs4xdr_gen.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Generated by xdrgen. Manual edits will be lost. 3 + // XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x 4 + // XDR specification modification time: Mon Oct 14 09:10:13 2024 5 + 6 + #include <linux/sunrpc/svc.h> 7 + 8 + #include "nfs4xdr_gen.h" 9 + 10 + static bool __maybe_unused 11 + xdrgen_decode_int64_t(struct xdr_stream *xdr, int64_t *ptr) 12 + { 13 + return xdrgen_decode_hyper(xdr, ptr); 14 + }; 15 + 16 + static bool __maybe_unused 17 + xdrgen_decode_uint32_t(struct xdr_stream *xdr, uint32_t *ptr) 18 + { 19 + return xdrgen_decode_unsigned_int(xdr, ptr); 20 + }; 21 + 22 + static bool __maybe_unused 23 + xdrgen_decode_bitmap4(struct xdr_stream *xdr, bitmap4 *ptr) 24 + { 25 + if (xdr_stream_decode_u32(xdr, &ptr->count) < 0) 26 + return false; 27 + for (u32 i = 0; i < ptr->count; i++) 28 + if (!xdrgen_decode_uint32_t(xdr, &ptr->element[i])) 29 + return false; 30 + return true; 31 + }; 32 + 33 + static bool __maybe_unused 34 + xdrgen_decode_nfstime4(struct xdr_stream *xdr, struct nfstime4 *ptr) 35 + { 36 + if (!xdrgen_decode_int64_t(xdr, &ptr->seconds)) 37 + return false; 38 + if (!xdrgen_decode_uint32_t(xdr, &ptr->nseconds)) 39 + return false; 40 + return true; 41 + }; 42 + 43 + static bool __maybe_unused 44 + xdrgen_decode_fattr4_offline(struct xdr_stream *xdr, fattr4_offline *ptr) 45 + { 46 + return xdrgen_decode_bool(xdr, ptr); 47 + }; 48 + 49 + static bool __maybe_unused 50 + xdrgen_decode_open_arguments4(struct xdr_stream *xdr, struct open_arguments4 *ptr) 51 + { 52 + if (!xdrgen_decode_bitmap4(xdr, &ptr->oa_share_access)) 53 + return false; 54 + if (!xdrgen_decode_bitmap4(xdr, &ptr->oa_share_deny)) 55 + return false; 56 + if (!xdrgen_decode_bitmap4(xdr, &ptr->oa_share_access_want)) 57 + return false; 58 + if (!xdrgen_decode_bitmap4(xdr, &ptr->oa_open_claim)) 59 + return false; 60 + if (!xdrgen_decode_bitmap4(xdr, &ptr->oa_create_mode)) 61 + return false; 62 + return true; 63 + }; 64 + 65 + static bool __maybe_unused 66 + xdrgen_decode_open_args_share_access4(struct xdr_stream *xdr, open_args_share_access4 *ptr) 67 + { 68 + u32 val; 69 + 70 + if (xdr_stream_decode_u32(xdr, &val) < 0) 71 + return false; 72 + *ptr = val; 73 + return true; 74 + } 75 + 76 + static bool __maybe_unused 77 + xdrgen_decode_open_args_share_deny4(struct xdr_stream *xdr, open_args_share_deny4 *ptr) 78 + { 79 + u32 val; 80 + 81 + if (xdr_stream_decode_u32(xdr, &val) < 0) 82 + return false; 83 + *ptr = val; 84 + return true; 85 + } 86 + 87 + static bool __maybe_unused 88 + xdrgen_decode_open_args_share_access_want4(struct xdr_stream *xdr, open_args_share_access_want4 *ptr) 89 + { 90 + u32 val; 91 + 92 + if (xdr_stream_decode_u32(xdr, &val) < 0) 93 + return false; 94 + *ptr = val; 95 + return true; 96 + } 97 + 98 + static bool __maybe_unused 99 + xdrgen_decode_open_args_open_claim4(struct xdr_stream *xdr, open_args_open_claim4 *ptr) 100 + { 101 + u32 val; 102 + 103 + if (xdr_stream_decode_u32(xdr, &val) < 0) 104 + return false; 105 + *ptr = val; 106 + return true; 107 + } 108 + 109 + static bool __maybe_unused 110 + xdrgen_decode_open_args_createmode4(struct xdr_stream *xdr, open_args_createmode4 *ptr) 111 + { 112 + u32 val; 113 + 114 + if (xdr_stream_decode_u32(xdr, &val) < 0) 115 + return false; 116 + *ptr = val; 117 + return true; 118 + } 119 + 120 + bool 121 + xdrgen_decode_fattr4_open_arguments(struct xdr_stream *xdr, fattr4_open_arguments *ptr) 122 + { 123 + return xdrgen_decode_open_arguments4(xdr, ptr); 124 + }; 125 + 126 + bool 127 + xdrgen_decode_fattr4_time_deleg_access(struct xdr_stream *xdr, fattr4_time_deleg_access *ptr) 128 + { 129 + return xdrgen_decode_nfstime4(xdr, ptr); 130 + }; 131 + 132 + bool 133 + xdrgen_decode_fattr4_time_deleg_modify(struct xdr_stream *xdr, fattr4_time_deleg_modify *ptr) 134 + { 135 + return xdrgen_decode_nfstime4(xdr, ptr); 136 + }; 137 + 138 + static bool __maybe_unused 139 + xdrgen_decode_open_delegation_type4(struct xdr_stream *xdr, open_delegation_type4 *ptr) 140 + { 141 + u32 val; 142 + 143 + if (xdr_stream_decode_u32(xdr, &val) < 0) 144 + return false; 145 + *ptr = val; 146 + return true; 147 + } 148 + 149 + static bool __maybe_unused 150 + xdrgen_encode_int64_t(struct xdr_stream *xdr, const int64_t value) 151 + { 152 + return xdrgen_encode_hyper(xdr, value); 153 + }; 154 + 155 + static bool __maybe_unused 156 + xdrgen_encode_uint32_t(struct xdr_stream *xdr, const uint32_t value) 157 + { 158 + return xdrgen_encode_unsigned_int(xdr, value); 159 + }; 160 + 161 + static bool __maybe_unused 162 + xdrgen_encode_bitmap4(struct xdr_stream *xdr, const bitmap4 value) 163 + { 164 + if (xdr_stream_encode_u32(xdr, value.count) != XDR_UNIT) 165 + return false; 166 + for (u32 i = 0; i < value.count; i++) 167 + if (!xdrgen_encode_uint32_t(xdr, value.element[i])) 168 + return false; 169 + return true; 170 + }; 171 + 172 + static bool __maybe_unused 173 + xdrgen_encode_nfstime4(struct xdr_stream *xdr, const struct nfstime4 *value) 174 + { 175 + if (!xdrgen_encode_int64_t(xdr, value->seconds)) 176 + return false; 177 + if (!xdrgen_encode_uint32_t(xdr, value->nseconds)) 178 + return false; 179 + return true; 180 + }; 181 + 182 + static bool __maybe_unused 183 + xdrgen_encode_fattr4_offline(struct xdr_stream *xdr, const fattr4_offline value) 184 + { 185 + return xdrgen_encode_bool(xdr, value); 186 + }; 187 + 188 + static bool __maybe_unused 189 + xdrgen_encode_open_arguments4(struct xdr_stream *xdr, const struct open_arguments4 *value) 190 + { 191 + if (!xdrgen_encode_bitmap4(xdr, value->oa_share_access)) 192 + return false; 193 + if (!xdrgen_encode_bitmap4(xdr, value->oa_share_deny)) 194 + return false; 195 + if (!xdrgen_encode_bitmap4(xdr, value->oa_share_access_want)) 196 + return false; 197 + if (!xdrgen_encode_bitmap4(xdr, value->oa_open_claim)) 198 + return false; 199 + if (!xdrgen_encode_bitmap4(xdr, value->oa_create_mode)) 200 + return false; 201 + return true; 202 + }; 203 + 204 + static bool __maybe_unused 205 + xdrgen_encode_open_args_share_access4(struct xdr_stream *xdr, open_args_share_access4 value) 206 + { 207 + return xdr_stream_encode_u32(xdr, value) == XDR_UNIT; 208 + } 209 + 210 + static bool __maybe_unused 211 + xdrgen_encode_open_args_share_deny4(struct xdr_stream *xdr, open_args_share_deny4 value) 212 + { 213 + return xdr_stream_encode_u32(xdr, value) == XDR_UNIT; 214 + } 215 + 216 + static bool __maybe_unused 217 + xdrgen_encode_open_args_share_access_want4(struct xdr_stream *xdr, open_args_share_access_want4 value) 218 + { 219 + return xdr_stream_encode_u32(xdr, value) == XDR_UNIT; 220 + } 221 + 222 + static bool __maybe_unused 223 + xdrgen_encode_open_args_open_claim4(struct xdr_stream *xdr, open_args_open_claim4 value) 224 + { 225 + return xdr_stream_encode_u32(xdr, value) == XDR_UNIT; 226 + } 227 + 228 + static bool __maybe_unused 229 + xdrgen_encode_open_args_createmode4(struct xdr_stream *xdr, open_args_createmode4 value) 230 + { 231 + return xdr_stream_encode_u32(xdr, value) == XDR_UNIT; 232 + } 233 + 234 + bool 235 + xdrgen_encode_fattr4_open_arguments(struct xdr_stream *xdr, const fattr4_open_arguments *value) 236 + { 237 + return xdrgen_encode_open_arguments4(xdr, value); 238 + }; 239 + 240 + bool 241 + xdrgen_encode_fattr4_time_deleg_access(struct xdr_stream *xdr, const fattr4_time_deleg_access *value) 242 + { 243 + return xdrgen_encode_nfstime4(xdr, value); 244 + }; 245 + 246 + bool 247 + xdrgen_encode_fattr4_time_deleg_modify(struct xdr_stream *xdr, const fattr4_time_deleg_modify *value) 248 + { 249 + return xdrgen_encode_nfstime4(xdr, value); 250 + }; 251 + 252 + static bool __maybe_unused 253 + xdrgen_encode_open_delegation_type4(struct xdr_stream *xdr, open_delegation_type4 value) 254 + { 255 + return xdr_stream_encode_u32(xdr, value) == XDR_UNIT; 256 + }
+25
fs/nfsd/nfs4xdr_gen.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Generated by xdrgen. Manual edits will be lost. */ 3 + /* XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x */ 4 + /* XDR specification modification time: Mon Oct 14 09:10:13 2024 */ 5 + 6 + #ifndef _LINUX_XDRGEN_NFS4_1_DECL_H 7 + #define _LINUX_XDRGEN_NFS4_1_DECL_H 8 + 9 + #include <linux/types.h> 10 + 11 + #include <linux/sunrpc/xdr.h> 12 + #include <linux/sunrpc/xdrgen/_defs.h> 13 + #include <linux/sunrpc/xdrgen/_builtins.h> 14 + #include <linux/sunrpc/xdrgen/nfs4_1.h> 15 + 16 + bool xdrgen_decode_fattr4_open_arguments(struct xdr_stream *xdr, fattr4_open_arguments *ptr); 17 + bool xdrgen_encode_fattr4_open_arguments(struct xdr_stream *xdr, const fattr4_open_arguments *value); 18 + 19 + bool xdrgen_decode_fattr4_time_deleg_access(struct xdr_stream *xdr, fattr4_time_deleg_access *ptr); 20 + bool xdrgen_encode_fattr4_time_deleg_access(struct xdr_stream *xdr, const fattr4_time_deleg_access *value); 21 + 22 + bool xdrgen_decode_fattr4_time_deleg_modify(struct xdr_stream *xdr, fattr4_time_deleg_modify *ptr); 23 + bool xdrgen_encode_fattr4_time_deleg_modify(struct xdr_stream *xdr, const fattr4_time_deleg_modify *value); 24 + 25 + #endif /* _LINUX_XDRGEN_NFS4_1_DECL_H */
-42
fs/nfsd/nfsctl.c
··· 48 48 NFSD_Versions, 49 49 NFSD_Ports, 50 50 NFSD_MaxBlkSize, 51 - NFSD_MaxConnections, 52 51 NFSD_Filecache, 53 52 NFSD_Leasetime, 54 53 NFSD_Gracetime, ··· 67 68 static ssize_t write_versions(struct file *file, char *buf, size_t size); 68 69 static ssize_t write_ports(struct file *file, char *buf, size_t size); 69 70 static ssize_t write_maxblksize(struct file *file, char *buf, size_t size); 70 - static ssize_t write_maxconn(struct file *file, char *buf, size_t size); 71 71 #ifdef CONFIG_NFSD_V4 72 72 static ssize_t write_leasetime(struct file *file, char *buf, size_t size); 73 73 static ssize_t write_gracetime(struct file *file, char *buf, size_t size); ··· 85 87 [NFSD_Versions] = write_versions, 86 88 [NFSD_Ports] = write_ports, 87 89 [NFSD_MaxBlkSize] = write_maxblksize, 88 - [NFSD_MaxConnections] = write_maxconn, 89 90 #ifdef CONFIG_NFSD_V4 90 91 [NFSD_Leasetime] = write_leasetime, 91 92 [NFSD_Gracetime] = write_gracetime, ··· 899 902 nfsd_max_blksize); 900 903 } 901 904 902 - /* 903 - * write_maxconn - Set or report the current max number of connections 904 - * 905 - * Input: 906 - * buf: ignored 907 - * size: zero 908 - * OR 909 - * 910 - * Input: 911 - * buf: C string containing an unsigned 912 - * integer value representing the new 913 - * number of max connections 914 - * size: non-zero length of C string in @buf 915 - * Output: 916 - * On success: passed-in buffer filled with '\n'-terminated C string 917 - * containing numeric value of max_connections setting 918 - * for this net namespace; 919 - * return code is the size in bytes of the string 920 - * On error: return code is zero or a negative errno value 921 - */ 922 - static ssize_t write_maxconn(struct file *file, char *buf, size_t size) 923 - { 924 - char *mesg = buf; 925 - struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id); 926 - unsigned int maxconn = nn->max_connections; 927 - 928 - if (size > 0) { 929 - int rv = get_uint(&mesg, &maxconn); 930 - 931 - if (rv) 932 - return rv; 933 - trace_nfsd_ctl_maxconn(netns(file), maxconn); 934 - nn->max_connections = maxconn; 935 - } 936 - 937 - return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%u\n", maxconn); 938 - } 939 - 940 905 #ifdef CONFIG_NFSD_V4 941 906 static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size, 942 907 time64_t *time, struct nfsd_net *nn) ··· 1331 1372 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, 1332 1373 [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, 1333 1374 [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, 1334 - [NFSD_MaxConnections] = {"max_connections", &transaction_ops, S_IWUSR|S_IRUGO}, 1335 1375 [NFSD_Filecache] = {"filecache", &nfsd_file_cache_stats_fops, S_IRUGO}, 1336 1376 #ifdef CONFIG_NFSD_V4 1337 1377 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
+8 -5
fs/nfsd/nfsd.h
··· 88 88 extern struct svc_program nfsd_programs[]; 89 89 extern const struct svc_version nfsd_version2, nfsd_version3, nfsd_version4; 90 90 extern struct mutex nfsd_mutex; 91 - extern spinlock_t nfsd_drc_lock; 92 - extern unsigned long nfsd_drc_max_mem; 93 - extern unsigned long nfsd_drc_mem_used; 94 91 extern atomic_t nfsd_th_cnt; /* number of available threads */ 95 92 96 93 extern const struct seq_operations nfs_exports_op; ··· 455 458 (NFSD4_1_SUPPORTED_ATTRS_WORD2 | \ 456 459 FATTR4_WORD2_MODE_UMASK | \ 457 460 NFSD4_2_SECURITY_ATTRS | \ 458 - FATTR4_WORD2_XATTR_SUPPORT) 461 + FATTR4_WORD2_XATTR_SUPPORT | \ 462 + FATTR4_WORD2_TIME_DELEG_ACCESS | \ 463 + FATTR4_WORD2_TIME_DELEG_MODIFY | \ 464 + FATTR4_WORD2_OPEN_ARGUMENTS) 459 465 460 466 extern const u32 nfsd_suppattrs[3][3]; 461 467 ··· 528 528 #endif 529 529 #define NFSD_WRITEABLE_ATTRS_WORD2 \ 530 530 (FATTR4_WORD2_MODE_UMASK \ 531 - | MAYBE_FATTR4_WORD2_SECURITY_LABEL) 531 + | MAYBE_FATTR4_WORD2_SECURITY_LABEL \ 532 + | FATTR4_WORD2_TIME_DELEG_ACCESS \ 533 + | FATTR4_WORD2_TIME_DELEG_MODIFY \ 534 + ) 532 535 533 536 #define NFSD_SUPPATTR_EXCLCREAT_WORD0 \ 534 537 NFSD_WRITEABLE_ATTRS_WORD0
+2
fs/nfsd/nfsfh.c
··· 381 381 if (error) 382 382 goto out; 383 383 384 + svc_xprt_set_valid(rqstp->rq_xprt); 385 + 384 386 /* Finally, check access permissions. */ 385 387 error = nfsd_permission(cred, exp, dentry, access); 386 388 out:
-37
fs/nfsd/nfssvc.c
··· 70 70 */ 71 71 DEFINE_MUTEX(nfsd_mutex); 72 72 73 - /* 74 - * nfsd_drc_lock protects nfsd_drc_max_pages and nfsd_drc_pages_used. 75 - * nfsd_drc_max_pages limits the total amount of memory available for 76 - * version 4.1 DRC caches. 77 - * nfsd_drc_pages_used tracks the current version 4.1 DRC memory usage. 78 - */ 79 - DEFINE_SPINLOCK(nfsd_drc_lock); 80 - unsigned long nfsd_drc_max_mem; 81 - unsigned long nfsd_drc_mem_used; 82 - 83 73 #if IS_ENABLED(CONFIG_NFS_LOCALIO) 84 74 static const struct svc_version *localio_versions[] = { 85 75 [1] = &localio_version1, ··· 565 575 } 566 576 } 567 577 568 - /* 569 - * Each session guarantees a negotiated per slot memory cache for replies 570 - * which in turn consumes memory beyond the v2/v3/v4.0 server. A dedicated 571 - * NFSv4.1 server might want to use more memory for a DRC than a machine 572 - * with mutiple services. 573 - * 574 - * Impose a hard limit on the number of pages for the DRC which varies 575 - * according to the machines free pages. This is of course only a default. 576 - * 577 - * For now this is a #defined shift which could be under admin control 578 - * in the future. 579 - */ 580 - static void set_max_drc(void) 581 - { 582 - #define NFSD_DRC_SIZE_SHIFT 7 583 - nfsd_drc_max_mem = (nr_free_buffer_pages() 584 - >> NFSD_DRC_SIZE_SHIFT) * PAGE_SIZE; 585 - nfsd_drc_mem_used = 0; 586 - dprintk("%s nfsd_drc_max_mem %lu \n", __func__, nfsd_drc_max_mem); 587 - } 588 - 589 578 static int nfsd_get_default_max_blksize(void) 590 579 { 591 580 struct sysinfo i; ··· 637 668 if (serv == NULL) 638 669 return -ENOMEM; 639 670 640 - serv->sv_maxconn = nn->max_connections; 641 671 error = svc_bind(serv, net); 642 672 if (error < 0) { 643 673 svc_destroy(&serv); ··· 646 678 nn->nfsd_serv = serv; 647 679 spin_unlock(&nfsd_notifier_lock); 648 680 649 - set_max_drc(); 650 681 /* check if the notifier is already set */ 651 682 if (atomic_inc_return(&nfsd_notifier_refcount) == 1) { 652 683 register_inetaddr_notifier(&nfsd_inetaddr_notifier); ··· 921 954 * The main request loop 922 955 */ 923 956 while (!svc_thread_should_stop(rqstp)) { 924 - /* Update sv_maxconn if it has changed */ 925 - rqstp->rq_server->sv_maxconn = nn->max_connections; 926 - 927 957 svc_recv(rqstp); 928 - 929 958 nfsd_file_net_dispose(nn); 930 959 } 931 960
+31 -5
fs/nfsd/state.h
··· 159 159 /* from CB_GETATTR reply */ 160 160 u64 ncf_cb_change; 161 161 u64 ncf_cb_fsize; 162 + struct timespec64 ncf_cb_mtime; 163 + struct timespec64 ncf_cb_atime; 162 164 163 165 unsigned long ncf_cb_flags; 164 166 bool ncf_file_modified; ··· 209 207 struct nfs4_cb_fattr dl_cb_fattr; 210 208 }; 211 209 210 + static inline bool deleg_is_read(u32 dl_type) 211 + { 212 + return (dl_type == OPEN_DELEGATE_READ || dl_type == OPEN_DELEGATE_READ_ATTRS_DELEG); 213 + } 214 + 215 + static inline bool deleg_is_write(u32 dl_type) 216 + { 217 + return (dl_type == OPEN_DELEGATE_WRITE || dl_type == OPEN_DELEGATE_WRITE_ATTRS_DELEG); 218 + } 219 + 220 + static inline bool deleg_attrs_deleg(u32 dl_type) 221 + { 222 + return dl_type == OPEN_DELEGATE_READ_ATTRS_DELEG || 223 + dl_type == OPEN_DELEGATE_WRITE_ATTRS_DELEG; 224 + } 225 + 212 226 #define cb_to_delegation(cb) \ 213 227 container_of(cb, struct nfs4_delegation, dl_recall) 214 228 ··· 245 227 return container_of(s, struct nfs4_delegation, dl_stid); 246 228 } 247 229 248 - /* Maximum number of slots per session. 160 is useful for long haul TCP */ 249 - #define NFSD_MAX_SLOTS_PER_SESSION 160 230 + /* Maximum number of slots per session. This is for sanity-check only. 231 + * It could be increased if we had a mechanism to shutdown misbehaving clients. 232 + * A large number can be needed to get good throughput on high-latency servers. 233 + */ 234 + #define NFSD_MAX_SLOTS_PER_SESSION 2048 250 235 /* Maximum session per slot cache size */ 251 236 #define NFSD_SLOT_CACHE_SIZE 2048 252 237 /* Maximum number of NFSD_SLOT_CACHE_SIZE slots per session */ ··· 263 242 struct svc_cred sl_cred; 264 243 u32 sl_datalen; 265 244 u16 sl_opcnt; 245 + u16 sl_generation; 266 246 #define NFSD4_SLOT_INUSE (1 << 0) 267 247 #define NFSD4_SLOT_CACHETHIS (1 << 1) 268 248 #define NFSD4_SLOT_INITIALIZED (1 << 2) 269 249 #define NFSD4_SLOT_CACHED (1 << 3) 250 + #define NFSD4_SLOT_REUSED (1 << 4) 270 251 u8 sl_flags; 271 252 char sl_data[]; 272 253 }; ··· 341 318 u32 se_cb_slot_avail; /* bitmap of available slots */ 342 319 u32 se_cb_highest_slot; /* highest slot client wants */ 343 320 u32 se_cb_prog; 344 - bool se_dead; 345 321 struct list_head se_hash; /* hash by sessionid */ 346 322 struct list_head se_perclnt; 323 + struct list_head se_all_sessions;/* global list of sessions */ 347 324 struct nfs4_client *se_client; 348 325 struct nfs4_sessionid se_sessionid; 349 326 struct nfsd4_channel_attrs se_fchannel; 350 327 struct nfsd4_cb_sec se_cb_sec; 351 328 struct list_head se_conns; 352 329 u32 se_cb_seq_nr[NFSD_BC_SLOT_TABLE_SIZE]; 353 - struct nfsd4_slot *se_slots[]; /* forward channel slots */ 330 + struct xarray se_slots; /* forward channel slots */ 331 + u16 se_slot_gen; 332 + bool se_dead; 333 + u32 se_target_maxslots; 354 334 }; 355 335 356 336 /* formatted contents of nfs4_sessionid */ ··· 531 505 unsigned int rp_buflen; 532 506 char *rp_buf; 533 507 struct knfsd_fh rp_openfh; 534 - atomic_t rp_locked; 508 + int rp_locked; 535 509 char rp_ibuf[NFSD4_REPLAY_ISIZE]; 536 510 }; 537 511
-1
fs/nfsd/trace.h
··· 626 626 DEFINE_STATEID_EVENT(deleg_read); 627 627 DEFINE_STATEID_EVENT(deleg_write); 628 628 DEFINE_STATEID_EVENT(deleg_return); 629 - DEFINE_STATEID_EVENT(deleg_recall); 630 629 631 630 DECLARE_EVENT_CLASS(nfsd_stateseqid_class, 632 631 TP_PROTO(u32 seqid, const stateid_t *stp),
-2
fs/nfsd/xdr4.h
··· 576 576 u32 slotid; /* request/response */ 577 577 u32 maxslots; /* request/response */ 578 578 u32 cachethis; /* request */ 579 - #if 0 580 579 u32 target_maxslots; /* response */ 581 - #endif /* not yet */ 582 580 u32 status_flags; /* response */ 583 581 }; 584 582
+7 -3
fs/nfsd/xdr4cb.h
··· 59 59 * 1: CB_GETATTR opcode (32-bit) 60 60 * N: file_handle 61 61 * 1: number of entry in attribute array (32-bit) 62 - * 1: entry 0 in attribute array (32-bit) 62 + * 3: entry 0-2 in attribute array (32-bit * 3) 63 63 */ 64 64 #define NFS4_enc_cb_getattr_sz (cb_compound_enc_hdr_sz + \ 65 65 cb_sequence_enc_sz + \ 66 - 1 + enc_nfs4_fh_sz + 1 + 1) 66 + 1 + enc_nfs4_fh_sz + 1 + 3) 67 67 /* 68 68 * 4: fattr_bitmap_maxsz 69 69 * 1: attribute array len 70 70 * 2: change attr (64-bit) 71 71 * 2: size (64-bit) 72 + * 2: atime.seconds (64-bit) 73 + * 1: atime.nanoseconds (32-bit) 74 + * 2: mtime.seconds (64-bit) 75 + * 1: mtime.nanoseconds (32-bit) 72 76 */ 73 77 #define NFS4_dec_cb_getattr_sz (cb_compound_dec_hdr_sz + \ 74 - cb_sequence_dec_sz + 4 + 1 + 2 + 2 + op_dec_sz) 78 + cb_sequence_dec_sz + 4 + 1 + 2 + 2 + 2 + 1 + 2 + 1 + op_dec_sz)
+2 -7
include/linux/nfs4.h
··· 17 17 #include <linux/uidgid.h> 18 18 #include <uapi/linux/nfs4.h> 19 19 #include <linux/sunrpc/msg_prot.h> 20 + #include <linux/sunrpc/xdrgen/nfs4_1.h> 20 21 21 22 enum nfs4_acl_whotype { 22 23 NFS4_ACL_WHO_NAMED = 0, ··· 366 365 NFS4_LIMIT_BLOCKS = 2 367 366 }; 368 367 369 - enum open_delegation_type4 { 368 + enum nfs4_open_delegation_type4 { 370 369 NFS4_OPEN_DELEGATE_NONE = 0, 371 370 NFS4_OPEN_DELEGATE_READ = 1, 372 371 NFS4_OPEN_DELEGATE_WRITE = 2, ··· 511 510 */ 512 511 enum { 513 512 FATTR4_XATTR_SUPPORT = 82, 514 - }; 515 - 516 - enum { 517 - FATTR4_TIME_DELEG_ACCESS = 84, 518 - FATTR4_TIME_DELEG_MODIFY = 85, 519 - FATTR4_OPEN_ARGUMENTS = 86, 520 513 }; 521 514 522 515 /*
-5
include/linux/nfs_xdr.h
··· 1315 1315 1316 1316 #endif /* CONFIG_NFS_V4 */ 1317 1317 1318 - struct nfstime4 { 1319 - u64 seconds; 1320 - u32 nseconds; 1321 - }; 1322 - 1323 1318 #ifdef CONFIG_NFS_V4_1 1324 1319 1325 1320 struct pnfs_commit_bucket {
+2
include/linux/sunrpc/cache.h
··· 222 222 return detail->flush_time >= h->last_refresh; 223 223 } 224 224 225 + extern int cache_check_rcu(struct cache_detail *detail, 226 + struct cache_head *h, struct cache_req *rqstp); 225 227 extern int cache_check(struct cache_detail *detail, 226 228 struct cache_head *h, struct cache_req *rqstp); 227 229 extern void cache_flush(void);
-81
include/linux/sunrpc/gss_asn1.h
··· 1 - /* 2 - * linux/include/linux/sunrpc/gss_asn1.h 3 - * 4 - * minimal asn1 for generic encoding/decoding of gss tokens 5 - * 6 - * Adapted from MIT Kerberos 5-1.2.1 lib/include/krb5.h, 7 - * lib/gssapi/krb5/gssapiP_krb5.h, and others 8 - * 9 - * Copyright (c) 2000 The Regents of the University of Michigan. 10 - * All rights reserved. 11 - * 12 - * Andy Adamson <andros@umich.edu> 13 - */ 14 - 15 - /* 16 - * Copyright 1995 by the Massachusetts Institute of Technology. 17 - * All Rights Reserved. 18 - * 19 - * Export of this software from the United States of America may 20 - * require a specific license from the United States Government. 21 - * It is the responsibility of any person or organization contemplating 22 - * export to obtain such a license before exporting. 23 - * 24 - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 25 - * distribute this software and its documentation for any purpose and 26 - * without fee is hereby granted, provided that the above copyright 27 - * notice appear in all copies and that both that copyright notice and 28 - * this permission notice appear in supporting documentation, and that 29 - * the name of M.I.T. not be used in advertising or publicity pertaining 30 - * to distribution of the software without specific, written prior 31 - * permission. Furthermore if you modify this software you must label 32 - * your software as modified software and not distribute it in such a 33 - * fashion that it might be confused with the original M.I.T. software. 34 - * M.I.T. makes no representations about the suitability of 35 - * this software for any purpose. It is provided "as is" without express 36 - * or implied warranty. 37 - * 38 - */ 39 - 40 - 41 - #include <linux/sunrpc/gss_api.h> 42 - 43 - #define SIZEOF_INT 4 44 - 45 - /* from gssapi_err_generic.h */ 46 - #define G_BAD_SERVICE_NAME (-2045022976L) 47 - #define G_BAD_STRING_UID (-2045022975L) 48 - #define G_NOUSER (-2045022974L) 49 - #define G_VALIDATE_FAILED (-2045022973L) 50 - #define G_BUFFER_ALLOC (-2045022972L) 51 - #define G_BAD_MSG_CTX (-2045022971L) 52 - #define G_WRONG_SIZE (-2045022970L) 53 - #define G_BAD_USAGE (-2045022969L) 54 - #define G_UNKNOWN_QOP (-2045022968L) 55 - #define G_NO_HOSTNAME (-2045022967L) 56 - #define G_BAD_HOSTNAME (-2045022966L) 57 - #define G_WRONG_MECH (-2045022965L) 58 - #define G_BAD_TOK_HEADER (-2045022964L) 59 - #define G_BAD_DIRECTION (-2045022963L) 60 - #define G_TOK_TRUNC (-2045022962L) 61 - #define G_REFLECT (-2045022961L) 62 - #define G_WRONG_TOKID (-2045022960L) 63 - 64 - #define g_OID_equal(o1,o2) \ 65 - (((o1)->len == (o2)->len) && \ 66 - (memcmp((o1)->data,(o2)->data,(int) (o1)->len) == 0)) 67 - 68 - u32 g_verify_token_header( 69 - struct xdr_netobj *mech, 70 - int *body_size, 71 - unsigned char **buf_in, 72 - int toksize); 73 - 74 - int g_token_size( 75 - struct xdr_netobj *mech, 76 - unsigned int body_size); 77 - 78 - void g_make_token_header( 79 - struct xdr_netobj *mech, 80 - int body_size, 81 - unsigned char **buf);
-1
include/linux/sunrpc/gss_krb5.h
··· 40 40 #include <crypto/skcipher.h> 41 41 #include <linux/sunrpc/auth_gss.h> 42 42 #include <linux/sunrpc/gss_err.h> 43 - #include <linux/sunrpc/gss_asn1.h> 44 43 45 44 /* Length of constant used in key derivation */ 46 45 #define GSS_KRB5_K5CLENGTH (5)
+2 -11
include/linux/sunrpc/svc.h
··· 72 72 spinlock_t sv_lock; 73 73 unsigned int sv_nprogs; /* Number of sv_programs */ 74 74 unsigned int sv_nrthreads; /* # of server threads */ 75 - unsigned int sv_maxconn; /* max connections allowed or 76 - * '0' causing max to be based 77 - * on number of threads. */ 78 - 79 75 unsigned int sv_max_payload; /* datagram payload size */ 80 76 unsigned int sv_max_mesg; /* max_payload + 1 page for overheads */ 81 77 unsigned int sv_xdrsize; /* XDR buffer size */ 82 78 struct list_head sv_permsocks; /* all permanent sockets */ 83 79 struct list_head sv_tempsocks; /* all temporary sockets */ 84 - int sv_tmpcnt; /* count of temporary sockets */ 80 + int sv_tmpcnt; /* count of temporary "valid" sockets */ 85 81 struct timer_list sv_temptimer; /* timer for aging temporary sockets */ 86 82 87 83 char * sv_name; /* service name */ ··· 323 327 */ 324 328 static inline void svc_thread_init_status(struct svc_rqst *rqstp, int err) 325 329 { 326 - rqstp->rq_err = err; 327 - /* memory barrier ensures assignment to error above is visible before 328 - * waitqueue_active() test below completes. 329 - */ 330 - smp_mb(); 331 - wake_up_var(&rqstp->rq_err); 330 + store_release_wake_up(&rqstp->rq_err, err); 332 331 if (err) 333 332 kthread_exit(1); 334 333 }
+22
include/linux/sunrpc/svc_xprt.h
··· 99 99 XPT_HANDSHAKE, /* xprt requests a handshake */ 100 100 XPT_TLS_SESSION, /* transport-layer security established */ 101 101 XPT_PEER_AUTH, /* peer has been authenticated */ 102 + XPT_PEER_VALID, /* peer has presented a filehandle that 103 + * it has access to. It is NOT counted 104 + * in ->sv_tmpcnt. 105 + */ 102 106 }; 107 + 108 + /* 109 + * Maximum number of "tmp" connections - those without XPT_PEER_VALID - 110 + * permitted on any service. 111 + */ 112 + #define XPT_MAX_TMP_CONN 64 113 + 114 + static inline void svc_xprt_set_valid(struct svc_xprt *xpt) 115 + { 116 + if (test_bit(XPT_TEMP, &xpt->xpt_flags) && 117 + !test_and_set_bit(XPT_PEER_VALID, &xpt->xpt_flags)) { 118 + struct svc_serv *serv = xpt->xpt_server; 119 + 120 + spin_lock(&serv->sv_lock); 121 + serv->sv_tmpcnt -= 1; 122 + spin_unlock(&serv->sv_lock); 123 + } 124 + } 103 125 104 126 static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u) 105 127 {
+153
include/linux/sunrpc/xdrgen/nfs4_1.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Generated by xdrgen. Manual edits will be lost. */ 3 + /* XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x */ 4 + /* XDR specification modification time: Mon Oct 14 09:10:13 2024 */ 5 + 6 + #ifndef _LINUX_XDRGEN_NFS4_1_DEF_H 7 + #define _LINUX_XDRGEN_NFS4_1_DEF_H 8 + 9 + #include <linux/types.h> 10 + #include <linux/sunrpc/xdrgen/_defs.h> 11 + 12 + typedef s64 int64_t; 13 + 14 + typedef u32 uint32_t; 15 + 16 + typedef struct { 17 + u32 count; 18 + uint32_t *element; 19 + } bitmap4; 20 + 21 + struct nfstime4 { 22 + int64_t seconds; 23 + uint32_t nseconds; 24 + }; 25 + 26 + typedef bool fattr4_offline; 27 + 28 + enum { FATTR4_OFFLINE = 83 }; 29 + 30 + struct open_arguments4 { 31 + bitmap4 oa_share_access; 32 + bitmap4 oa_share_deny; 33 + bitmap4 oa_share_access_want; 34 + bitmap4 oa_open_claim; 35 + bitmap4 oa_create_mode; 36 + }; 37 + 38 + enum open_args_share_access4 { 39 + OPEN_ARGS_SHARE_ACCESS_READ = 1, 40 + OPEN_ARGS_SHARE_ACCESS_WRITE = 2, 41 + OPEN_ARGS_SHARE_ACCESS_BOTH = 3, 42 + }; 43 + typedef enum open_args_share_access4 open_args_share_access4; 44 + 45 + enum open_args_share_deny4 { 46 + OPEN_ARGS_SHARE_DENY_NONE = 0, 47 + OPEN_ARGS_SHARE_DENY_READ = 1, 48 + OPEN_ARGS_SHARE_DENY_WRITE = 2, 49 + OPEN_ARGS_SHARE_DENY_BOTH = 3, 50 + }; 51 + typedef enum open_args_share_deny4 open_args_share_deny4; 52 + 53 + enum open_args_share_access_want4 { 54 + OPEN_ARGS_SHARE_ACCESS_WANT_ANY_DELEG = 3, 55 + OPEN_ARGS_SHARE_ACCESS_WANT_NO_DELEG = 4, 56 + OPEN_ARGS_SHARE_ACCESS_WANT_CANCEL = 5, 57 + OPEN_ARGS_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL = 17, 58 + OPEN_ARGS_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED = 18, 59 + OPEN_ARGS_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS = 20, 60 + OPEN_ARGS_SHARE_ACCESS_WANT_OPEN_XOR_DELEGATION = 21, 61 + }; 62 + typedef enum open_args_share_access_want4 open_args_share_access_want4; 63 + 64 + enum open_args_open_claim4 { 65 + OPEN_ARGS_OPEN_CLAIM_NULL = 0, 66 + OPEN_ARGS_OPEN_CLAIM_PREVIOUS = 1, 67 + OPEN_ARGS_OPEN_CLAIM_DELEGATE_CUR = 2, 68 + OPEN_ARGS_OPEN_CLAIM_DELEGATE_PREV = 3, 69 + OPEN_ARGS_OPEN_CLAIM_FH = 4, 70 + OPEN_ARGS_OPEN_CLAIM_DELEG_CUR_FH = 5, 71 + OPEN_ARGS_OPEN_CLAIM_DELEG_PREV_FH = 6, 72 + }; 73 + typedef enum open_args_open_claim4 open_args_open_claim4; 74 + 75 + enum open_args_createmode4 { 76 + OPEN_ARGS_CREATEMODE_UNCHECKED4 = 0, 77 + OPEN_ARGS_CREATE_MODE_GUARDED = 1, 78 + OPEN_ARGS_CREATEMODE_EXCLUSIVE4 = 2, 79 + OPEN_ARGS_CREATE_MODE_EXCLUSIVE4_1 = 3, 80 + }; 81 + typedef enum open_args_createmode4 open_args_createmode4; 82 + 83 + typedef struct open_arguments4 fattr4_open_arguments; 84 + 85 + enum { FATTR4_OPEN_ARGUMENTS = 86 }; 86 + 87 + enum { OPEN4_RESULT_NO_OPEN_STATEID = 0x00000010 }; 88 + 89 + typedef struct nfstime4 fattr4_time_deleg_access; 90 + 91 + typedef struct nfstime4 fattr4_time_deleg_modify; 92 + 93 + enum { FATTR4_TIME_DELEG_ACCESS = 84 }; 94 + 95 + enum { FATTR4_TIME_DELEG_MODIFY = 85 }; 96 + 97 + enum { OPEN4_SHARE_ACCESS_WANT_DELEG_MASK = 0xFF00 }; 98 + 99 + enum { OPEN4_SHARE_ACCESS_WANT_NO_PREFERENCE = 0x0000 }; 100 + 101 + enum { OPEN4_SHARE_ACCESS_WANT_READ_DELEG = 0x0100 }; 102 + 103 + enum { OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG = 0x0200 }; 104 + 105 + enum { OPEN4_SHARE_ACCESS_WANT_ANY_DELEG = 0x0300 }; 106 + 107 + enum { OPEN4_SHARE_ACCESS_WANT_NO_DELEG = 0x0400 }; 108 + 109 + enum { OPEN4_SHARE_ACCESS_WANT_CANCEL = 0x0500 }; 110 + 111 + enum { OPEN4_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL = 0x10000 }; 112 + 113 + enum { OPEN4_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED = 0x20000 }; 114 + 115 + enum { OPEN4_SHARE_ACCESS_WANT_DELEG_TIMESTAMPS = 0x100000 }; 116 + 117 + enum { OPEN4_SHARE_ACCESS_WANT_OPEN_XOR_DELEGATION = 0x200000 }; 118 + 119 + enum open_delegation_type4 { 120 + OPEN_DELEGATE_NONE = 0, 121 + OPEN_DELEGATE_READ = 1, 122 + OPEN_DELEGATE_WRITE = 2, 123 + OPEN_DELEGATE_NONE_EXT = 3, 124 + OPEN_DELEGATE_READ_ATTRS_DELEG = 4, 125 + OPEN_DELEGATE_WRITE_ATTRS_DELEG = 5, 126 + }; 127 + typedef enum open_delegation_type4 open_delegation_type4; 128 + 129 + #define NFS4_int64_t_sz \ 130 + (XDR_hyper) 131 + #define NFS4_uint32_t_sz \ 132 + (XDR_unsigned_int) 133 + #define NFS4_bitmap4_sz (XDR_unsigned_int) 134 + #define NFS4_nfstime4_sz \ 135 + (NFS4_int64_t_sz + NFS4_uint32_t_sz) 136 + #define NFS4_fattr4_offline_sz \ 137 + (XDR_bool) 138 + #define NFS4_open_arguments4_sz \ 139 + (NFS4_bitmap4_sz + NFS4_bitmap4_sz + NFS4_bitmap4_sz + NFS4_bitmap4_sz + NFS4_bitmap4_sz) 140 + #define NFS4_open_args_share_access4_sz (XDR_int) 141 + #define NFS4_open_args_share_deny4_sz (XDR_int) 142 + #define NFS4_open_args_share_access_want4_sz (XDR_int) 143 + #define NFS4_open_args_open_claim4_sz (XDR_int) 144 + #define NFS4_open_args_createmode4_sz (XDR_int) 145 + #define NFS4_fattr4_open_arguments_sz \ 146 + (NFS4_open_arguments4_sz) 147 + #define NFS4_fattr4_time_deleg_access_sz \ 148 + (NFS4_nfstime4_sz) 149 + #define NFS4_fattr4_time_deleg_modify_sz \ 150 + (NFS4_nfstime4_sz) 151 + #define NFS4_open_delegation_type4_sz (XDR_int) 152 + 153 + #endif /* _LINUX_XDRGEN_NFS4_1_DEF_H */
-1
include/linux/sunrpc/xprtmultipath.h
··· 75 75 struct rpc_xprt_switch *newswitch); 76 76 77 77 extern struct rpc_xprt *xprt_iter_xprt(struct rpc_xprt_iter *xpi); 78 - extern struct rpc_xprt *xprt_iter_get_xprt(struct rpc_xprt_iter *xpi); 79 78 extern struct rpc_xprt *xprt_iter_get_next(struct rpc_xprt_iter *xpi); 80 79 81 80 extern bool rpc_xprt_switch_has_addr(struct rpc_xprt_switch *xps,
+5
include/linux/time64.h
··· 49 49 return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec); 50 50 } 51 51 52 + static inline bool timespec64_is_epoch(const struct timespec64 *ts) 53 + { 54 + return ts->tv_sec == 0 && ts->tv_nsec == 0; 55 + } 56 + 52 57 /* 53 58 * lhs < rhs: return <0 54 59 * lhs == rhs: return 0
+5 -2
include/uapi/linux/nfs4.h
··· 58 58 #define NFS4_SHARE_DENY_BOTH 0x0003 59 59 60 60 /* nfs41 */ 61 - #define NFS4_SHARE_WANT_MASK 0xFF00 61 + #define NFS4_SHARE_WANT_TYPE_MASK 0xFF00 62 62 #define NFS4_SHARE_WANT_NO_PREFERENCE 0x0000 63 63 #define NFS4_SHARE_WANT_READ_DELEG 0x0100 64 64 #define NFS4_SHARE_WANT_WRITE_DELEG 0x0200 ··· 66 66 #define NFS4_SHARE_WANT_NO_DELEG 0x0400 67 67 #define NFS4_SHARE_WANT_CANCEL 0x0500 68 68 69 - #define NFS4_SHARE_WHEN_MASK 0xF0000 69 + #define NFS4_SHARE_WHEN_MASK 0xF0000 70 70 #define NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL 0x10000 71 71 #define NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED 0x20000 72 72 73 + #define NFS4_SHARE_WANT_MOD_MASK 0xF00000 73 74 #define NFS4_SHARE_WANT_DELEG_TIMESTAMPS 0x100000 74 75 #define NFS4_SHARE_WANT_OPEN_XOR_DELEGATION 0x200000 76 + 77 + #define NFS4_SHARE_WANT_MASK (NFS4_SHARE_WANT_TYPE_MASK | NFS4_SHARE_WANT_MOD_MASK) 75 78 76 79 #define NFS4_CDFC4_FORE 0x1 77 80 #define NFS4_CDFC4_BACK 0x2
+1 -1
net/sunrpc/auth_gss/Makefile
··· 5 5 6 6 obj-$(CONFIG_SUNRPC_GSS) += auth_rpcgss.o 7 7 8 - auth_rpcgss-y := auth_gss.o gss_generic_token.o \ 8 + auth_rpcgss-y := auth_gss.o \ 9 9 gss_mech_switch.o svcauth_gss.o \ 10 10 gss_rpc_upcall.o gss_rpc_xdr.o trace.o 11 11
-231
net/sunrpc/auth_gss/gss_generic_token.c
··· 1 - /* 2 - * linux/net/sunrpc/gss_generic_token.c 3 - * 4 - * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/generic/util_token.c 5 - * 6 - * Copyright (c) 2000 The Regents of the University of Michigan. 7 - * All rights reserved. 8 - * 9 - * Andy Adamson <andros@umich.edu> 10 - */ 11 - 12 - /* 13 - * Copyright 1993 by OpenVision Technologies, Inc. 14 - * 15 - * Permission to use, copy, modify, distribute, and sell this software 16 - * and its documentation for any purpose is hereby granted without fee, 17 - * provided that the above copyright notice appears in all copies and 18 - * that both that copyright notice and this permission notice appear in 19 - * supporting documentation, and that the name of OpenVision not be used 20 - * in advertising or publicity pertaining to distribution of the software 21 - * without specific, written prior permission. OpenVision makes no 22 - * representations about the suitability of this software for any 23 - * purpose. It is provided "as is" without express or implied warranty. 24 - * 25 - * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 26 - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 27 - * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR 28 - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 29 - * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 30 - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 31 - * PERFORMANCE OF THIS SOFTWARE. 32 - */ 33 - 34 - #include <linux/types.h> 35 - #include <linux/module.h> 36 - #include <linux/string.h> 37 - #include <linux/sunrpc/sched.h> 38 - #include <linux/sunrpc/gss_asn1.h> 39 - 40 - 41 - #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) 42 - # define RPCDBG_FACILITY RPCDBG_AUTH 43 - #endif 44 - 45 - 46 - /* TWRITE_STR from gssapiP_generic.h */ 47 - #define TWRITE_STR(ptr, str, len) \ 48 - memcpy((ptr), (char *) (str), (len)); \ 49 - (ptr) += (len); 50 - 51 - /* XXXX this code currently makes the assumption that a mech oid will 52 - never be longer than 127 bytes. This assumption is not inherent in 53 - the interfaces, so the code can be fixed if the OSI namespace 54 - balloons unexpectedly. */ 55 - 56 - /* Each token looks like this: 57 - 58 - 0x60 tag for APPLICATION 0, SEQUENCE 59 - (constructed, definite-length) 60 - <length> possible multiple bytes, need to parse/generate 61 - 0x06 tag for OBJECT IDENTIFIER 62 - <moid_length> compile-time constant string (assume 1 byte) 63 - <moid_bytes> compile-time constant string 64 - <inner_bytes> the ANY containing the application token 65 - bytes 0,1 are the token type 66 - bytes 2,n are the token data 67 - 68 - For the purposes of this abstraction, the token "header" consists of 69 - the sequence tag and length octets, the mech OID DER encoding, and the 70 - first two inner bytes, which indicate the token type. The token 71 - "body" consists of everything else. 72 - 73 - */ 74 - 75 - static int 76 - der_length_size( int length) 77 - { 78 - if (length < (1<<7)) 79 - return 1; 80 - else if (length < (1<<8)) 81 - return 2; 82 - #if (SIZEOF_INT == 2) 83 - else 84 - return 3; 85 - #else 86 - else if (length < (1<<16)) 87 - return 3; 88 - else if (length < (1<<24)) 89 - return 4; 90 - else 91 - return 5; 92 - #endif 93 - } 94 - 95 - static void 96 - der_write_length(unsigned char **buf, int length) 97 - { 98 - if (length < (1<<7)) { 99 - *(*buf)++ = (unsigned char) length; 100 - } else { 101 - *(*buf)++ = (unsigned char) (der_length_size(length)+127); 102 - #if (SIZEOF_INT > 2) 103 - if (length >= (1<<24)) 104 - *(*buf)++ = (unsigned char) (length>>24); 105 - if (length >= (1<<16)) 106 - *(*buf)++ = (unsigned char) ((length>>16)&0xff); 107 - #endif 108 - if (length >= (1<<8)) 109 - *(*buf)++ = (unsigned char) ((length>>8)&0xff); 110 - *(*buf)++ = (unsigned char) (length&0xff); 111 - } 112 - } 113 - 114 - /* returns decoded length, or < 0 on failure. Advances buf and 115 - decrements bufsize */ 116 - 117 - static int 118 - der_read_length(unsigned char **buf, int *bufsize) 119 - { 120 - unsigned char sf; 121 - int ret; 122 - 123 - if (*bufsize < 1) 124 - return -1; 125 - sf = *(*buf)++; 126 - (*bufsize)--; 127 - if (sf & 0x80) { 128 - if ((sf &= 0x7f) > ((*bufsize)-1)) 129 - return -1; 130 - if (sf > SIZEOF_INT) 131 - return -1; 132 - ret = 0; 133 - for (; sf; sf--) { 134 - ret = (ret<<8) + (*(*buf)++); 135 - (*bufsize)--; 136 - } 137 - } else { 138 - ret = sf; 139 - } 140 - 141 - return ret; 142 - } 143 - 144 - /* returns the length of a token, given the mech oid and the body size */ 145 - 146 - int 147 - g_token_size(struct xdr_netobj *mech, unsigned int body_size) 148 - { 149 - /* set body_size to sequence contents size */ 150 - body_size += 2 + (int) mech->len; /* NEED overflow check */ 151 - return 1 + der_length_size(body_size) + body_size; 152 - } 153 - 154 - EXPORT_SYMBOL_GPL(g_token_size); 155 - 156 - /* fills in a buffer with the token header. The buffer is assumed to 157 - be the right size. buf is advanced past the token header */ 158 - 159 - void 160 - g_make_token_header(struct xdr_netobj *mech, int body_size, unsigned char **buf) 161 - { 162 - *(*buf)++ = 0x60; 163 - der_write_length(buf, 2 + mech->len + body_size); 164 - *(*buf)++ = 0x06; 165 - *(*buf)++ = (unsigned char) mech->len; 166 - TWRITE_STR(*buf, mech->data, ((int) mech->len)); 167 - } 168 - 169 - EXPORT_SYMBOL_GPL(g_make_token_header); 170 - 171 - /* 172 - * Given a buffer containing a token, reads and verifies the token, 173 - * leaving buf advanced past the token header, and setting body_size 174 - * to the number of remaining bytes. Returns 0 on success, 175 - * G_BAD_TOK_HEADER for a variety of errors, and G_WRONG_MECH if the 176 - * mechanism in the token does not match the mech argument. buf and 177 - * *body_size are left unmodified on error. 178 - */ 179 - u32 180 - g_verify_token_header(struct xdr_netobj *mech, int *body_size, 181 - unsigned char **buf_in, int toksize) 182 - { 183 - unsigned char *buf = *buf_in; 184 - int seqsize; 185 - struct xdr_netobj toid; 186 - int ret = 0; 187 - 188 - if ((toksize-=1) < 0) 189 - return G_BAD_TOK_HEADER; 190 - if (*buf++ != 0x60) 191 - return G_BAD_TOK_HEADER; 192 - 193 - if ((seqsize = der_read_length(&buf, &toksize)) < 0) 194 - return G_BAD_TOK_HEADER; 195 - 196 - if (seqsize != toksize) 197 - return G_BAD_TOK_HEADER; 198 - 199 - if ((toksize-=1) < 0) 200 - return G_BAD_TOK_HEADER; 201 - if (*buf++ != 0x06) 202 - return G_BAD_TOK_HEADER; 203 - 204 - if ((toksize-=1) < 0) 205 - return G_BAD_TOK_HEADER; 206 - toid.len = *buf++; 207 - 208 - if ((toksize-=toid.len) < 0) 209 - return G_BAD_TOK_HEADER; 210 - toid.data = buf; 211 - buf+=toid.len; 212 - 213 - if (! g_OID_equal(&toid, mech)) 214 - ret = G_WRONG_MECH; 215 - 216 - /* G_WRONG_MECH is not returned immediately because it's more important 217 - to return G_BAD_TOK_HEADER if the token header is in fact bad */ 218 - 219 - if ((toksize-=2) < 0) 220 - return G_BAD_TOK_HEADER; 221 - 222 - if (ret) 223 - return ret; 224 - 225 - *buf_in = buf; 226 - *body_size = toksize; 227 - 228 - return ret; 229 - } 230 - 231 - EXPORT_SYMBOL_GPL(g_verify_token_header);
-55
net/sunrpc/auth_gss/gss_krb5_crypto.c
··· 442 442 return 0; 443 443 } 444 444 445 - int 446 - gss_encrypt_xdr_buf(struct crypto_sync_skcipher *tfm, struct xdr_buf *buf, 447 - int offset, struct page **pages) 448 - { 449 - int ret; 450 - struct encryptor_desc desc; 451 - SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); 452 - 453 - BUG_ON((buf->len - offset) % crypto_sync_skcipher_blocksize(tfm) != 0); 454 - 455 - skcipher_request_set_sync_tfm(req, tfm); 456 - skcipher_request_set_callback(req, 0, NULL, NULL); 457 - 458 - memset(desc.iv, 0, sizeof(desc.iv)); 459 - desc.req = req; 460 - desc.pos = offset; 461 - desc.outbuf = buf; 462 - desc.pages = pages; 463 - desc.fragno = 0; 464 - desc.fraglen = 0; 465 - 466 - sg_init_table(desc.infrags, 4); 467 - sg_init_table(desc.outfrags, 4); 468 - 469 - ret = xdr_process_buf(buf, offset, buf->len - offset, encryptor, &desc); 470 - skcipher_request_zero(req); 471 - return ret; 472 - } 473 - 474 445 struct decryptor_desc { 475 446 u8 iv[GSS_KRB5_MAX_BLOCKSIZE]; 476 447 struct skcipher_request *req; ··· 494 523 desc->fraglen = 0; 495 524 } 496 525 return 0; 497 - } 498 - 499 - int 500 - gss_decrypt_xdr_buf(struct crypto_sync_skcipher *tfm, struct xdr_buf *buf, 501 - int offset) 502 - { 503 - int ret; 504 - struct decryptor_desc desc; 505 - SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); 506 - 507 - /* XXXJBF: */ 508 - BUG_ON((buf->len - offset) % crypto_sync_skcipher_blocksize(tfm) != 0); 509 - 510 - skcipher_request_set_sync_tfm(req, tfm); 511 - skcipher_request_set_callback(req, 0, NULL, NULL); 512 - 513 - memset(desc.iv, 0, sizeof(desc.iv)); 514 - desc.req = req; 515 - desc.fragno = 0; 516 - desc.fraglen = 0; 517 - 518 - sg_init_table(desc.frags, 4); 519 - 520 - ret = xdr_process_buf(buf, offset, buf->len - offset, decryptor, &desc); 521 - skcipher_request_zero(req); 522 - return ret; 523 526 } 524 527 525 528 /*
-7
net/sunrpc/auth_gss/gss_krb5_internal.h
··· 172 172 int xdr_extend_head(struct xdr_buf *buf, unsigned int base, 173 173 unsigned int shiftlen); 174 174 175 - int gss_encrypt_xdr_buf(struct crypto_sync_skcipher *tfm, 176 - struct xdr_buf *outbuf, int offset, 177 - struct page **pages); 178 - 179 - int gss_decrypt_xdr_buf(struct crypto_sync_skcipher *tfm, 180 - struct xdr_buf *inbuf, int offset); 181 - 182 175 u32 gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, 183 176 struct xdr_buf *buf, struct page **pages); 184 177
-1
net/sunrpc/auth_gss/gss_mech_switch.c
··· 13 13 #include <linux/module.h> 14 14 #include <linux/oid_registry.h> 15 15 #include <linux/sunrpc/msg_prot.h> 16 - #include <linux/sunrpc/gss_asn1.h> 17 16 #include <linux/sunrpc/auth_gss.h> 18 17 #include <linux/sunrpc/svcauth_gss.h> 19 18 #include <linux/sunrpc/gss_err.h>
+29 -24
net/sunrpc/cache.c
··· 281 281 return rv; 282 282 } 283 283 284 - /* 285 - * This is the generic cache management routine for all 286 - * the authentication caches. 287 - * It checks the currency of a cache item and will (later) 288 - * initiate an upcall to fill it if needed. 289 - * 290 - * 291 - * Returns 0 if the cache_head can be used, or cache_puts it and returns 292 - * -EAGAIN if upcall is pending and request has been queued 293 - * -ETIMEDOUT if upcall failed or request could not be queue or 294 - * upcall completed but item is still invalid (implying that 295 - * the cache item has been replaced with a newer one). 296 - * -ENOENT if cache entry was negative 297 - */ 298 - int cache_check(struct cache_detail *detail, 284 + int cache_check_rcu(struct cache_detail *detail, 299 285 struct cache_head *h, struct cache_req *rqstp) 300 286 { 301 287 int rv; ··· 322 336 rv = -ETIMEDOUT; 323 337 } 324 338 } 339 + 340 + return rv; 341 + } 342 + EXPORT_SYMBOL_GPL(cache_check_rcu); 343 + 344 + /* 345 + * This is the generic cache management routine for all 346 + * the authentication caches. 347 + * It checks the currency of a cache item and will (later) 348 + * initiate an upcall to fill it if needed. 349 + * 350 + * 351 + * Returns 0 if the cache_head can be used, or cache_puts it and returns 352 + * -EAGAIN if upcall is pending and request has been queued 353 + * -ETIMEDOUT if upcall failed or request could not be queue or 354 + * upcall completed but item is still invalid (implying that 355 + * the cache item has been replaced with a newer one). 356 + * -ENOENT if cache entry was negative 357 + */ 358 + int cache_check(struct cache_detail *detail, 359 + struct cache_head *h, struct cache_req *rqstp) 360 + { 361 + int rv; 362 + 363 + rv = cache_check_rcu(detail, h, rqstp); 325 364 if (rv) 326 365 cache_put(h, detail); 327 366 return rv; ··· 1438 1427 seq_printf(m, "# expiry=%lld refcnt=%d flags=%lx\n", 1439 1428 convert_to_wallclock(cp->expiry_time), 1440 1429 kref_read(&cp->ref), cp->flags); 1441 - if (!cache_get_rcu(cp)) 1442 - return 0; 1443 1430 1444 - if (cache_check(cd, cp, NULL)) 1445 - /* cache_check does a cache_put on failure */ 1431 + if (cache_check_rcu(cd, cp, NULL)) 1446 1432 seq_puts(m, "# "); 1447 - else { 1448 - if (cache_is_expired(cd, cp)) 1449 - seq_puts(m, "# "); 1450 - cache_put(cp, cd); 1451 - } 1433 + else if (cache_is_expired(cd, cp)) 1434 + seq_puts(m, "# "); 1452 1435 1453 1436 return cd->cache_show(m, cd, cp); 1454 1437 }
+16 -22
net/sunrpc/svc_xprt.c
··· 606 606 } 607 607 608 608 /* 609 - * Make sure that we don't have too many active connections. If we have, 609 + * Make sure that we don't have too many connections that have not yet 610 + * demonstrated that they have access to the NFS server. If we have, 610 611 * something must be dropped. It's not clear what will happen if we allow 611 612 * "too many" connections, but when dealing with network-facing software, 612 613 * we have to code defensively. Here we do that by imposing hard limits. ··· 619 618 * The only somewhat efficient mechanism would be if drop old 620 619 * connections from the same IP first. But right now we don't even 621 620 * record the client IP in svc_sock. 622 - * 623 - * single-threaded services that expect a lot of clients will probably 624 - * need to set sv_maxconn to override the default value which is based 625 - * on the number of threads 626 621 */ 627 622 static void svc_check_conn_limits(struct svc_serv *serv) 628 623 { 629 - unsigned int limit = serv->sv_maxconn ? serv->sv_maxconn : 630 - (serv->sv_nrthreads+3) * 20; 631 - 632 - if (serv->sv_tmpcnt > limit) { 633 - struct svc_xprt *xprt = NULL; 624 + if (serv->sv_tmpcnt > XPT_MAX_TMP_CONN) { 625 + struct svc_xprt *xprt = NULL, *xprti; 634 626 spin_lock_bh(&serv->sv_lock); 635 627 if (!list_empty(&serv->sv_tempsocks)) { 636 - /* Try to help the admin */ 637 - net_notice_ratelimited("%s: too many open connections, consider increasing the %s\n", 638 - serv->sv_name, serv->sv_maxconn ? 639 - "max number of connections" : 640 - "number of threads"); 641 628 /* 642 629 * Always select the oldest connection. It's not fair, 643 - * but so is life 630 + * but nor is life. 644 631 */ 645 - xprt = list_entry(serv->sv_tempsocks.prev, 646 - struct svc_xprt, 647 - xpt_list); 648 - set_bit(XPT_CLOSE, &xprt->xpt_flags); 649 - svc_xprt_get(xprt); 632 + list_for_each_entry_reverse(xprti, &serv->sv_tempsocks, 633 + xpt_list) { 634 + if (!test_bit(XPT_PEER_VALID, &xprti->xpt_flags)) { 635 + xprt = xprti; 636 + set_bit(XPT_CLOSE, &xprt->xpt_flags); 637 + svc_xprt_get(xprt); 638 + break; 639 + } 640 + } 650 641 } 651 642 spin_unlock_bh(&serv->sv_lock); 652 643 ··· 1031 1038 1032 1039 spin_lock_bh(&serv->sv_lock); 1033 1040 list_del_init(&xprt->xpt_list); 1034 - if (test_bit(XPT_TEMP, &xprt->xpt_flags)) 1041 + if (test_bit(XPT_TEMP, &xprt->xpt_flags) && 1042 + !test_bit(XPT_PEER_VALID, &xprt->xpt_flags)) 1035 1043 serv->sv_tmpcnt--; 1036 1044 spin_unlock_bh(&serv->sv_lock); 1037 1045
+1 -11
net/sunrpc/svcsock.c
··· 1083 1083 /* If we have more data, signal svc_xprt_enqueue() to try again */ 1084 1084 svsk->sk_tcplen = 0; 1085 1085 svsk->sk_marker = xdr_zero; 1086 - 1087 - smp_wmb(); 1088 - tcp_set_rcvlowat(svsk->sk_sk, 1); 1089 1086 } 1090 1087 1091 1088 /** ··· 1172 1175 goto err_delete; 1173 1176 if (len == want) 1174 1177 svc_tcp_fragment_received(svsk); 1175 - else { 1176 - /* Avoid more ->sk_data_ready() calls until the rest 1177 - * of the message has arrived. This reduces service 1178 - * thread wake-ups on large incoming messages. */ 1179 - tcp_set_rcvlowat(svsk->sk_sk, 1180 - svc_sock_reclen(svsk) - svsk->sk_tcplen); 1181 - 1178 + else 1182 1179 trace_svcsock_tcp_recv_short(&svsk->sk_xprt, 1183 1180 svc_sock_reclen(svsk), 1184 1181 svsk->sk_tcplen - sizeof(rpc_fraghdr)); 1185 - } 1186 1182 goto err_noclose; 1187 1183 error: 1188 1184 if (len != -EAGAIN)
+6
net/sunrpc/xdr.c
··· 1097 1097 * Checks that we have enough buffer space to encode 'nbytes' more 1098 1098 * bytes of data. If so, update the total xdr_buf length, and 1099 1099 * adjust the length of the current kvec. 1100 + * 1101 + * The returned pointer is valid only until the next call to 1102 + * xdr_reserve_space() or xdr_commit_encode() on @xdr. The current 1103 + * implementation of this API guarantees that space reserved for a 1104 + * four-byte data item remains valid until @xdr is destroyed, but 1105 + * that might not always be true in the future. 1100 1106 */ 1101 1107 __be32 * xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes) 1102 1108 {
-17
net/sunrpc/xprtmultipath.c
··· 603 603 } 604 604 605 605 /** 606 - * xprt_iter_get_xprt - Returns the rpc_xprt pointed to by the cursor 607 - * @xpi: pointer to rpc_xprt_iter 608 - * 609 - * Returns a reference to the struct rpc_xprt that is currently 610 - * pointed to by the cursor. 611 - */ 612 - struct rpc_xprt *xprt_iter_get_xprt(struct rpc_xprt_iter *xpi) 613 - { 614 - struct rpc_xprt *xprt; 615 - 616 - rcu_read_lock(); 617 - xprt = xprt_iter_get_helper(xpi, xprt_iter_ops(xpi)->xpi_xprt); 618 - rcu_read_unlock(); 619 - return xprt; 620 - } 621 - 622 - /** 623 606 * xprt_iter_get_next - Returns the next rpc_xprt following the cursor 624 607 * @xpi: pointer to rpc_xprt_iter 625 608 *