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

Merge branch 'for-2.6.29' of git://linux-nfs.org/~bfields/linux

* 'for-2.6.29' of git://linux-nfs.org/~bfields/linux: (67 commits)
nfsd: get rid of NFSD_VERSION
nfsd: last_byte_offset
nfsd: delete wrong file comment from nfsd/nfs4xdr.c
nfsd: git rid of nfs4_cb_null_ops declaration
nfsd: dprint each op status in nfsd4_proc_compound
nfsd: add etoosmall to nfserrno
NFSD: FIDs need to take precedence over UUIDs
SUNRPC: The sunrpc server code should not be used by out-of-tree modules
svc: Clean up deferred requests on transport destruction
nfsd: fix double-locks of directory mutex
svc: Move kfree of deferral record to common code
CRED: Fix NFSD regression
NLM: Clean up flow of control in make_socks() function
NLM: Refactor make_socks() function
nfsd: Ensure nfsv4 calls the underlying filesystem on LOCKT
SUNRPC: Ensure the server closes sockets in a timely fashion
NFSD: Add documenting comments for nfsctl interface
NFSD: Replace open-coded integer with macro
NFSD: Fix a handful of coding style issues in write_filehandle()
NFSD: clean up failover sysctl function naming
...

+1225 -572
+2 -5
fs/lockd/clntproc.c
··· 16 16 #include <linux/sunrpc/clnt.h> 17 17 #include <linux/sunrpc/svc.h> 18 18 #include <linux/lockd/lockd.h> 19 - #include <linux/lockd/sm_inter.h> 20 19 21 20 #define NLMDBG_FACILITY NLMDBG_CLIENT 22 21 #define NLMCLNT_GRACE_WAIT (5*HZ) ··· 517 518 unsigned char fl_type; 518 519 int status = -ENOLCK; 519 520 520 - if (nsm_monitor(host) < 0) { 521 - printk(KERN_NOTICE "lockd: failed to monitor %s\n", 522 - host->h_name); 521 + if (nsm_monitor(host) < 0) 523 522 goto out; 524 - } 523 + 525 524 fl->fl_flags |= FL_ACCESS; 526 525 status = do_vfs_lock(fl); 527 526 fl->fl_flags = fl_flags;
+17 -153
fs/lockd/host.c
··· 15 15 #include <linux/sunrpc/clnt.h> 16 16 #include <linux/sunrpc/svc.h> 17 17 #include <linux/lockd/lockd.h> 18 - #include <linux/lockd/sm_inter.h> 19 18 #include <linux/mutex.h> 20 19 21 20 #include <net/ipv6.h> ··· 31 32 static DEFINE_MUTEX(nlm_host_mutex); 32 33 33 34 static void nlm_gc_hosts(void); 34 - static struct nsm_handle *nsm_find(const struct sockaddr *sap, 35 - const size_t salen, 36 - const char *hostname, 37 - const size_t hostname_len, 38 - const int create); 39 35 40 36 struct nlm_lookup_host_info { 41 37 const int server; /* search for server|client */ ··· 99 105 } 100 106 } 101 107 102 - static void nlm_display_address(const struct sockaddr *sap, 103 - char *buf, const size_t len) 104 - { 105 - const struct sockaddr_in *sin = (struct sockaddr_in *)sap; 106 - const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; 107 - 108 - switch (sap->sa_family) { 109 - case AF_UNSPEC: 110 - snprintf(buf, len, "unspecified"); 111 - break; 112 - case AF_INET: 113 - snprintf(buf, len, "%pI4", &sin->sin_addr.s_addr); 114 - break; 115 - case AF_INET6: 116 - if (ipv6_addr_v4mapped(&sin6->sin6_addr)) 117 - snprintf(buf, len, "%pI4", 118 - &sin6->sin6_addr.s6_addr32[3]); 119 - else 120 - snprintf(buf, len, "%pI6", &sin6->sin6_addr); 121 - break; 122 - default: 123 - snprintf(buf, len, "unsupported address family"); 124 - break; 125 - } 126 - } 127 - 128 108 /* 129 109 * Common host lookup routine for server & client 130 110 */ ··· 158 190 atomic_inc(&nsm->sm_count); 159 191 else { 160 192 host = NULL; 161 - nsm = nsm_find(ni->sap, ni->salen, 162 - ni->hostname, ni->hostname_len, 1); 193 + nsm = nsm_get_handle(ni->sap, ni->salen, 194 + ni->hostname, ni->hostname_len); 163 195 if (!nsm) { 164 196 dprintk("lockd: nlm_lookup_host failed; " 165 197 "no nsm handle\n"); ··· 174 206 goto out; 175 207 } 176 208 host->h_name = nsm->sm_name; 209 + host->h_addrbuf = nsm->sm_addrbuf; 177 210 memcpy(nlm_addr(host), ni->sap, ni->salen); 178 211 host->h_addrlen = ni->salen; 179 212 nlm_clear_port(nlm_addr(host)); ··· 201 232 202 233 nrhosts++; 203 234 204 - nlm_display_address((struct sockaddr *)&host->h_addr, 205 - host->h_addrbuf, sizeof(host->h_addrbuf)); 206 - nlm_display_address((struct sockaddr *)&host->h_srcaddr, 207 - host->h_srcaddrbuf, sizeof(host->h_srcaddrbuf)); 208 - 209 235 dprintk("lockd: nlm_lookup_host created host %s\n", 210 236 host->h_name); 211 237 ··· 220 256 BUG_ON(!list_empty(&host->h_lockowners)); 221 257 BUG_ON(atomic_read(&host->h_count)); 222 258 223 - /* 224 - * Release NSM handle and unmonitor host. 225 - */ 226 259 nsm_unmonitor(host); 260 + nsm_release(host->h_nsmhandle); 227 261 228 262 clnt = host->h_rpcclnt; 229 263 if (clnt != NULL) ··· 340 378 { 341 379 struct rpc_clnt *clnt; 342 380 343 - dprintk("lockd: nlm_bind_host %s (%s), my addr=%s\n", 344 - host->h_name, host->h_addrbuf, host->h_srcaddrbuf); 381 + dprintk("lockd: nlm_bind_host %s (%s)\n", 382 + host->h_name, host->h_addrbuf); 345 383 346 384 /* Lock host handle */ 347 385 mutex_lock(&host->h_mutex); ··· 443 481 } 444 482 } 445 483 446 - /* 447 - * We were notified that the host indicated by address &sin 448 - * has rebooted. 449 - * Release all resources held by that peer. 484 + /** 485 + * nlm_host_rebooted - Release all resources held by rebooted host 486 + * @info: pointer to decoded results of NLM_SM_NOTIFY call 487 + * 488 + * We were notified that the specified host has rebooted. Release 489 + * all resources held by that peer. 450 490 */ 451 - void nlm_host_rebooted(const struct sockaddr_in *sin, 452 - const char *hostname, 453 - unsigned int hostname_len, 454 - u32 new_state) 491 + void nlm_host_rebooted(const struct nlm_reboot *info) 455 492 { 456 493 struct hlist_head *chain; 457 494 struct hlist_node *pos; 458 495 struct nsm_handle *nsm; 459 496 struct nlm_host *host; 460 497 461 - nsm = nsm_find((struct sockaddr *)sin, sizeof(*sin), 462 - hostname, hostname_len, 0); 463 - if (nsm == NULL) { 464 - dprintk("lockd: never saw rebooted peer '%.*s' before\n", 465 - hostname_len, hostname); 498 + nsm = nsm_reboot_lookup(info); 499 + if (unlikely(nsm == NULL)) 466 500 return; 467 - } 468 - 469 - dprintk("lockd: nlm_host_rebooted(%.*s, %s)\n", 470 - hostname_len, hostname, nsm->sm_addrbuf); 471 - 472 - /* When reclaiming locks on this peer, make sure that 473 - * we set up a new notification */ 474 - nsm->sm_monitored = 0; 475 501 476 502 /* Mark all hosts tied to this NSM state as having rebooted. 477 503 * We run the loop repeatedly, because we drop the host table ··· 470 520 for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { 471 521 hlist_for_each_entry(host, pos, chain, h_hash) { 472 522 if (host->h_nsmhandle == nsm 473 - && host->h_nsmstate != new_state) { 474 - host->h_nsmstate = new_state; 523 + && host->h_nsmstate != info->state) { 524 + host->h_nsmstate = info->state; 475 525 host->h_state++; 476 526 477 527 nlm_get_host(host); ··· 578 628 } 579 629 580 630 next_gc = jiffies + NLM_HOST_COLLECT; 581 - } 582 - 583 - 584 - /* 585 - * Manage NSM handles 586 - */ 587 - static LIST_HEAD(nsm_handles); 588 - static DEFINE_SPINLOCK(nsm_lock); 589 - 590 - static struct nsm_handle *nsm_find(const struct sockaddr *sap, 591 - const size_t salen, 592 - const char *hostname, 593 - const size_t hostname_len, 594 - const int create) 595 - { 596 - struct nsm_handle *nsm = NULL; 597 - struct nsm_handle *pos; 598 - 599 - if (!sap) 600 - return NULL; 601 - 602 - if (hostname && memchr(hostname, '/', hostname_len) != NULL) { 603 - if (printk_ratelimit()) { 604 - printk(KERN_WARNING "Invalid hostname \"%.*s\" " 605 - "in NFS lock request\n", 606 - (int)hostname_len, hostname); 607 - } 608 - return NULL; 609 - } 610 - 611 - retry: 612 - spin_lock(&nsm_lock); 613 - list_for_each_entry(pos, &nsm_handles, sm_link) { 614 - 615 - if (hostname && nsm_use_hostnames) { 616 - if (strlen(pos->sm_name) != hostname_len 617 - || memcmp(pos->sm_name, hostname, hostname_len)) 618 - continue; 619 - } else if (!nlm_cmp_addr(nsm_addr(pos), sap)) 620 - continue; 621 - atomic_inc(&pos->sm_count); 622 - kfree(nsm); 623 - nsm = pos; 624 - goto found; 625 - } 626 - if (nsm) { 627 - list_add(&nsm->sm_link, &nsm_handles); 628 - goto found; 629 - } 630 - spin_unlock(&nsm_lock); 631 - 632 - if (!create) 633 - return NULL; 634 - 635 - nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL); 636 - if (nsm == NULL) 637 - return NULL; 638 - 639 - memcpy(nsm_addr(nsm), sap, salen); 640 - nsm->sm_addrlen = salen; 641 - nsm->sm_name = (char *) (nsm + 1); 642 - memcpy(nsm->sm_name, hostname, hostname_len); 643 - nsm->sm_name[hostname_len] = '\0'; 644 - nlm_display_address((struct sockaddr *)&nsm->sm_addr, 645 - nsm->sm_addrbuf, sizeof(nsm->sm_addrbuf)); 646 - atomic_set(&nsm->sm_count, 1); 647 - goto retry; 648 - 649 - found: 650 - spin_unlock(&nsm_lock); 651 - return nsm; 652 - } 653 - 654 - /* 655 - * Release an NSM handle 656 - */ 657 - void 658 - nsm_release(struct nsm_handle *nsm) 659 - { 660 - if (!nsm) 661 - return; 662 - if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) { 663 - list_del(&nsm->sm_link); 664 - spin_unlock(&nsm_lock); 665 - kfree(nsm); 666 - } 667 631 }
+424 -145
fs/lockd/mon.c
··· 9 9 #include <linux/types.h> 10 10 #include <linux/utsname.h> 11 11 #include <linux/kernel.h> 12 + #include <linux/ktime.h> 13 + 12 14 #include <linux/sunrpc/clnt.h> 13 15 #include <linux/sunrpc/xprtsock.h> 14 16 #include <linux/sunrpc/svc.h> 15 17 #include <linux/lockd/lockd.h> 16 - #include <linux/lockd/sm_inter.h> 17 - 18 18 19 19 #define NLMDBG_FACILITY NLMDBG_MONITOR 20 + #define NSM_PROGRAM 100024 21 + #define NSM_VERSION 1 20 22 21 - #define XDR_ADDRBUF_LEN (20) 23 + enum { 24 + NSMPROC_NULL, 25 + NSMPROC_STAT, 26 + NSMPROC_MON, 27 + NSMPROC_UNMON, 28 + NSMPROC_UNMON_ALL, 29 + NSMPROC_SIMU_CRASH, 30 + NSMPROC_NOTIFY, 31 + }; 22 32 23 - static struct rpc_clnt * nsm_create(void); 33 + struct nsm_args { 34 + struct nsm_private *priv; 35 + u32 prog; /* RPC callback info */ 36 + u32 vers; 37 + u32 proc; 38 + 39 + char *mon_name; 40 + }; 41 + 42 + struct nsm_res { 43 + u32 status; 44 + u32 state; 45 + }; 24 46 25 47 static struct rpc_program nsm_program; 48 + static LIST_HEAD(nsm_handles); 49 + static DEFINE_SPINLOCK(nsm_lock); 26 50 27 51 /* 28 52 * Local NSM state 29 53 */ 30 - int nsm_local_state; 54 + int __read_mostly nsm_local_state; 55 + int __read_mostly nsm_use_hostnames; 31 56 32 - /* 33 - * Common procedure for SM_MON/SM_UNMON calls 34 - */ 35 - static int 36 - nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res) 57 + static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm) 58 + { 59 + return (struct sockaddr *)&nsm->sm_addr; 60 + } 61 + 62 + static void nsm_display_ipv4_address(const struct sockaddr *sap, char *buf, 63 + const size_t len) 64 + { 65 + const struct sockaddr_in *sin = (struct sockaddr_in *)sap; 66 + snprintf(buf, len, "%pI4", &sin->sin_addr.s_addr); 67 + } 68 + 69 + static void nsm_display_ipv6_address(const struct sockaddr *sap, char *buf, 70 + const size_t len) 71 + { 72 + const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; 73 + 74 + if (ipv6_addr_v4mapped(&sin6->sin6_addr)) 75 + snprintf(buf, len, "%pI4", &sin6->sin6_addr.s6_addr32[3]); 76 + else if (sin6->sin6_scope_id != 0) 77 + snprintf(buf, len, "%pI6%%%u", &sin6->sin6_addr, 78 + sin6->sin6_scope_id); 79 + else 80 + snprintf(buf, len, "%pI6", &sin6->sin6_addr); 81 + } 82 + 83 + static void nsm_display_address(const struct sockaddr *sap, 84 + char *buf, const size_t len) 85 + { 86 + switch (sap->sa_family) { 87 + case AF_INET: 88 + nsm_display_ipv4_address(sap, buf, len); 89 + break; 90 + case AF_INET6: 91 + nsm_display_ipv6_address(sap, buf, len); 92 + break; 93 + default: 94 + snprintf(buf, len, "unsupported address family"); 95 + break; 96 + } 97 + } 98 + 99 + static struct rpc_clnt *nsm_create(void) 100 + { 101 + struct sockaddr_in sin = { 102 + .sin_family = AF_INET, 103 + .sin_addr.s_addr = htonl(INADDR_LOOPBACK), 104 + }; 105 + struct rpc_create_args args = { 106 + .protocol = XPRT_TRANSPORT_UDP, 107 + .address = (struct sockaddr *)&sin, 108 + .addrsize = sizeof(sin), 109 + .servername = "rpc.statd", 110 + .program = &nsm_program, 111 + .version = NSM_VERSION, 112 + .authflavor = RPC_AUTH_NULL, 113 + }; 114 + 115 + return rpc_create(&args); 116 + } 117 + 118 + static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res) 37 119 { 38 120 struct rpc_clnt *clnt; 39 121 int status; 40 - struct nsm_args args; 122 + struct nsm_args args = { 123 + .priv = &nsm->sm_priv, 124 + .prog = NLM_PROGRAM, 125 + .vers = 3, 126 + .proc = NLMPROC_NSM_NOTIFY, 127 + .mon_name = nsm->sm_mon_name, 128 + }; 41 129 struct rpc_message msg = { 42 130 .rpc_argp = &args, 43 131 .rpc_resp = res, ··· 134 46 clnt = nsm_create(); 135 47 if (IS_ERR(clnt)) { 136 48 status = PTR_ERR(clnt); 49 + dprintk("lockd: failed to create NSM upcall transport, " 50 + "status=%d\n", status); 137 51 goto out; 138 52 } 139 53 140 - memset(&args, 0, sizeof(args)); 141 - args.mon_name = nsm->sm_name; 142 - args.addr = nsm_addr_in(nsm)->sin_addr.s_addr; 143 - args.prog = NLM_PROGRAM; 144 - args.vers = 3; 145 - args.proc = NLMPROC_NSM_NOTIFY; 146 54 memset(res, 0, sizeof(*res)); 147 55 148 56 msg.rpc_proc = &clnt->cl_procinfo[proc]; 149 57 status = rpc_call_sync(clnt, &msg, 0); 150 58 if (status < 0) 151 - printk(KERN_DEBUG "nsm_mon_unmon: rpc failed, status=%d\n", 152 - status); 59 + dprintk("lockd: NSM upcall RPC failed, status=%d\n", 60 + status); 153 61 else 154 62 status = 0; 155 63 rpc_shutdown_client(clnt); ··· 153 69 return status; 154 70 } 155 71 156 - /* 157 - * Set up monitoring of a remote host 72 + /** 73 + * nsm_monitor - Notify a peer in case we reboot 74 + * @host: pointer to nlm_host of peer to notify 75 + * 76 + * If this peer is not already monitored, this function sends an 77 + * upcall to the local rpc.statd to record the name/address of 78 + * the peer to notify in case we reboot. 79 + * 80 + * Returns zero if the peer is monitored by the local rpc.statd; 81 + * otherwise a negative errno value is returned. 158 82 */ 159 - int 160 - nsm_monitor(struct nlm_host *host) 83 + int nsm_monitor(const struct nlm_host *host) 161 84 { 162 85 struct nsm_handle *nsm = host->h_nsmhandle; 163 86 struct nsm_res res; 164 87 int status; 165 88 166 - dprintk("lockd: nsm_monitor(%s)\n", host->h_name); 167 - BUG_ON(nsm == NULL); 89 + dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name); 168 90 169 91 if (nsm->sm_monitored) 170 92 return 0; 171 93 172 - status = nsm_mon_unmon(nsm, SM_MON, &res); 94 + /* 95 + * Choose whether to record the caller_name or IP address of 96 + * this peer in the local rpc.statd's database. 97 + */ 98 + nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf; 173 99 174 - if (status < 0 || res.status != 0) 175 - printk(KERN_NOTICE "lockd: cannot monitor %s\n", host->h_name); 100 + status = nsm_mon_unmon(nsm, NSMPROC_MON, &res); 101 + if (res.status != 0) 102 + status = -EIO; 103 + if (status < 0) 104 + printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name); 176 105 else 177 106 nsm->sm_monitored = 1; 178 107 return status; 179 108 } 180 109 181 - /* 182 - * Cease to monitor remote host 110 + /** 111 + * nsm_unmonitor - Unregister peer notification 112 + * @host: pointer to nlm_host of peer to stop monitoring 113 + * 114 + * If this peer is monitored, this function sends an upcall to 115 + * tell the local rpc.statd not to send this peer a notification 116 + * when we reboot. 183 117 */ 184 - int 185 - nsm_unmonitor(struct nlm_host *host) 118 + void nsm_unmonitor(const struct nlm_host *host) 186 119 { 187 120 struct nsm_handle *nsm = host->h_nsmhandle; 188 121 struct nsm_res res; 189 - int status = 0; 190 - 191 - if (nsm == NULL) 192 - return 0; 193 - host->h_nsmhandle = NULL; 122 + int status; 194 123 195 124 if (atomic_read(&nsm->sm_count) == 1 196 125 && nsm->sm_monitored && !nsm->sm_sticky) { 197 - dprintk("lockd: nsm_unmonitor(%s)\n", host->h_name); 126 + dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name); 198 127 199 - status = nsm_mon_unmon(nsm, SM_UNMON, &res); 128 + status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res); 129 + if (res.status != 0) 130 + status = -EIO; 200 131 if (status < 0) 201 132 printk(KERN_NOTICE "lockd: cannot unmonitor %s\n", 202 - host->h_name); 133 + nsm->sm_name); 203 134 else 204 135 nsm->sm_monitored = 0; 205 136 } 206 - nsm_release(nsm); 207 - return status; 137 + } 138 + 139 + static struct nsm_handle *nsm_lookup_hostname(const char *hostname, 140 + const size_t len) 141 + { 142 + struct nsm_handle *nsm; 143 + 144 + list_for_each_entry(nsm, &nsm_handles, sm_link) 145 + if (strlen(nsm->sm_name) == len && 146 + memcmp(nsm->sm_name, hostname, len) == 0) 147 + return nsm; 148 + return NULL; 149 + } 150 + 151 + static struct nsm_handle *nsm_lookup_addr(const struct sockaddr *sap) 152 + { 153 + struct nsm_handle *nsm; 154 + 155 + list_for_each_entry(nsm, &nsm_handles, sm_link) 156 + if (nlm_cmp_addr(nsm_addr(nsm), sap)) 157 + return nsm; 158 + return NULL; 159 + } 160 + 161 + static struct nsm_handle *nsm_lookup_priv(const struct nsm_private *priv) 162 + { 163 + struct nsm_handle *nsm; 164 + 165 + list_for_each_entry(nsm, &nsm_handles, sm_link) 166 + if (memcmp(nsm->sm_priv.data, priv->data, 167 + sizeof(priv->data)) == 0) 168 + return nsm; 169 + return NULL; 208 170 } 209 171 210 172 /* 211 - * Create NSM client for the local host 173 + * Construct a unique cookie to match this nsm_handle to this monitored 174 + * host. It is passed to the local rpc.statd via NSMPROC_MON, and 175 + * returned via NLMPROC_SM_NOTIFY, in the "priv" field of these 176 + * requests. 177 + * 178 + * The NSM protocol requires that these cookies be unique while the 179 + * system is running. We prefer a stronger requirement of making them 180 + * unique across reboots. If user space bugs cause a stale cookie to 181 + * be sent to the kernel, it could cause the wrong host to lose its 182 + * lock state if cookies were not unique across reboots. 183 + * 184 + * The cookies are exposed only to local user space via loopback. They 185 + * do not appear on the physical network. If we want greater security 186 + * for some reason, nsm_init_private() could perform a one-way hash to 187 + * obscure the contents of the cookie. 212 188 */ 213 - static struct rpc_clnt * 214 - nsm_create(void) 189 + static void nsm_init_private(struct nsm_handle *nsm) 215 190 { 216 - struct sockaddr_in sin = { 217 - .sin_family = AF_INET, 218 - .sin_addr.s_addr = htonl(INADDR_LOOPBACK), 219 - .sin_port = 0, 220 - }; 221 - struct rpc_create_args args = { 222 - .protocol = XPRT_TRANSPORT_UDP, 223 - .address = (struct sockaddr *)&sin, 224 - .addrsize = sizeof(sin), 225 - .servername = "localhost", 226 - .program = &nsm_program, 227 - .version = SM_VERSION, 228 - .authflavor = RPC_AUTH_NULL, 229 - }; 191 + u64 *p = (u64 *)&nsm->sm_priv.data; 192 + struct timespec ts; 230 193 231 - return rpc_create(&args); 194 + ktime_get_ts(&ts); 195 + *p++ = timespec_to_ns(&ts); 196 + *p = (unsigned long)nsm; 197 + } 198 + 199 + static struct nsm_handle *nsm_create_handle(const struct sockaddr *sap, 200 + const size_t salen, 201 + const char *hostname, 202 + const size_t hostname_len) 203 + { 204 + struct nsm_handle *new; 205 + 206 + new = kzalloc(sizeof(*new) + hostname_len + 1, GFP_KERNEL); 207 + if (unlikely(new == NULL)) 208 + return NULL; 209 + 210 + atomic_set(&new->sm_count, 1); 211 + new->sm_name = (char *)(new + 1); 212 + memcpy(nsm_addr(new), sap, salen); 213 + new->sm_addrlen = salen; 214 + nsm_init_private(new); 215 + nsm_display_address((const struct sockaddr *)&new->sm_addr, 216 + new->sm_addrbuf, sizeof(new->sm_addrbuf)); 217 + memcpy(new->sm_name, hostname, hostname_len); 218 + new->sm_name[hostname_len] = '\0'; 219 + 220 + return new; 221 + } 222 + 223 + /** 224 + * nsm_get_handle - Find or create a cached nsm_handle 225 + * @sap: pointer to socket address of handle to find 226 + * @salen: length of socket address 227 + * @hostname: pointer to C string containing hostname to find 228 + * @hostname_len: length of C string 229 + * 230 + * Behavior is modulated by the global nsm_use_hostnames variable. 231 + * 232 + * Returns a cached nsm_handle after bumping its ref count, or 233 + * returns a fresh nsm_handle if a handle that matches @sap and/or 234 + * @hostname cannot be found in the handle cache. Returns NULL if 235 + * an error occurs. 236 + */ 237 + struct nsm_handle *nsm_get_handle(const struct sockaddr *sap, 238 + const size_t salen, const char *hostname, 239 + const size_t hostname_len) 240 + { 241 + struct nsm_handle *cached, *new = NULL; 242 + 243 + if (hostname && memchr(hostname, '/', hostname_len) != NULL) { 244 + if (printk_ratelimit()) { 245 + printk(KERN_WARNING "Invalid hostname \"%.*s\" " 246 + "in NFS lock request\n", 247 + (int)hostname_len, hostname); 248 + } 249 + return NULL; 250 + } 251 + 252 + retry: 253 + spin_lock(&nsm_lock); 254 + 255 + if (nsm_use_hostnames && hostname != NULL) 256 + cached = nsm_lookup_hostname(hostname, hostname_len); 257 + else 258 + cached = nsm_lookup_addr(sap); 259 + 260 + if (cached != NULL) { 261 + atomic_inc(&cached->sm_count); 262 + spin_unlock(&nsm_lock); 263 + kfree(new); 264 + dprintk("lockd: found nsm_handle for %s (%s), " 265 + "cnt %d\n", cached->sm_name, 266 + cached->sm_addrbuf, 267 + atomic_read(&cached->sm_count)); 268 + return cached; 269 + } 270 + 271 + if (new != NULL) { 272 + list_add(&new->sm_link, &nsm_handles); 273 + spin_unlock(&nsm_lock); 274 + dprintk("lockd: created nsm_handle for %s (%s)\n", 275 + new->sm_name, new->sm_addrbuf); 276 + return new; 277 + } 278 + 279 + spin_unlock(&nsm_lock); 280 + 281 + new = nsm_create_handle(sap, salen, hostname, hostname_len); 282 + if (unlikely(new == NULL)) 283 + return NULL; 284 + goto retry; 285 + } 286 + 287 + /** 288 + * nsm_reboot_lookup - match NLMPROC_SM_NOTIFY arguments to an nsm_handle 289 + * @info: pointer to NLMPROC_SM_NOTIFY arguments 290 + * 291 + * Returns a matching nsm_handle if found in the nsm cache; the returned 292 + * nsm_handle's reference count is bumped and sm_monitored is cleared. 293 + * Otherwise returns NULL if some error occurred. 294 + */ 295 + struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info) 296 + { 297 + struct nsm_handle *cached; 298 + 299 + spin_lock(&nsm_lock); 300 + 301 + cached = nsm_lookup_priv(&info->priv); 302 + if (unlikely(cached == NULL)) { 303 + spin_unlock(&nsm_lock); 304 + dprintk("lockd: never saw rebooted peer '%.*s' before\n", 305 + info->len, info->mon); 306 + return cached; 307 + } 308 + 309 + atomic_inc(&cached->sm_count); 310 + spin_unlock(&nsm_lock); 311 + 312 + /* 313 + * During subsequent lock activity, force a fresh 314 + * notification to be set up for this host. 315 + */ 316 + cached->sm_monitored = 0; 317 + 318 + dprintk("lockd: host %s (%s) rebooted, cnt %d\n", 319 + cached->sm_name, cached->sm_addrbuf, 320 + atomic_read(&cached->sm_count)); 321 + return cached; 322 + } 323 + 324 + /** 325 + * nsm_release - Release an NSM handle 326 + * @nsm: pointer to handle to be released 327 + * 328 + */ 329 + void nsm_release(struct nsm_handle *nsm) 330 + { 331 + if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) { 332 + list_del(&nsm->sm_link); 333 + spin_unlock(&nsm_lock); 334 + dprintk("lockd: destroyed nsm_handle for %s (%s)\n", 335 + nsm->sm_name, nsm->sm_addrbuf); 336 + kfree(nsm); 337 + } 232 338 } 233 339 234 340 /* ··· 428 154 * Status Monitor wire protocol. 429 155 */ 430 156 431 - static __be32 *xdr_encode_nsm_string(__be32 *p, char *string) 157 + static int encode_nsm_string(struct xdr_stream *xdr, const char *string) 432 158 { 433 - size_t len = strlen(string); 159 + const u32 len = strlen(string); 160 + __be32 *p; 434 161 435 - if (len > SM_MAXSTRLEN) 436 - len = SM_MAXSTRLEN; 437 - return xdr_encode_opaque(p, string, len); 162 + if (unlikely(len > SM_MAXSTRLEN)) 163 + return -EIO; 164 + p = xdr_reserve_space(xdr, sizeof(u32) + len); 165 + if (unlikely(p == NULL)) 166 + return -EIO; 167 + xdr_encode_opaque(p, string, len); 168 + return 0; 438 169 } 439 170 440 171 /* 441 172 * "mon_name" specifies the host to be monitored. 442 - * 443 - * Linux uses a text version of the IP address of the remote 444 - * host as the host identifier (the "mon_name" argument). 445 - * 446 - * Linux statd always looks up the canonical hostname first for 447 - * whatever remote hostname it receives, so this works alright. 448 173 */ 449 - static __be32 *xdr_encode_mon_name(__be32 *p, struct nsm_args *argp) 174 + static int encode_mon_name(struct xdr_stream *xdr, const struct nsm_args *argp) 450 175 { 451 - char buffer[XDR_ADDRBUF_LEN + 1]; 452 - char *name = argp->mon_name; 453 - 454 - if (!nsm_use_hostnames) { 455 - snprintf(buffer, XDR_ADDRBUF_LEN, 456 - "%pI4", &argp->addr); 457 - name = buffer; 458 - } 459 - 460 - return xdr_encode_nsm_string(p, name); 176 + return encode_nsm_string(xdr, argp->mon_name); 461 177 } 462 178 463 179 /* 464 180 * The "my_id" argument specifies the hostname and RPC procedure 465 181 * to be called when the status manager receives notification 466 - * (via the SM_NOTIFY call) that the state of host "mon_name" 182 + * (via the NLMPROC_SM_NOTIFY call) that the state of host "mon_name" 467 183 * has changed. 468 184 */ 469 - static __be32 *xdr_encode_my_id(__be32 *p, struct nsm_args *argp) 185 + static int encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp) 470 186 { 471 - p = xdr_encode_nsm_string(p, utsname()->nodename); 472 - if (!p) 473 - return ERR_PTR(-EIO); 187 + int status; 188 + __be32 *p; 474 189 190 + status = encode_nsm_string(xdr, utsname()->nodename); 191 + if (unlikely(status != 0)) 192 + return status; 193 + p = xdr_reserve_space(xdr, 3 * sizeof(u32)); 194 + if (unlikely(p == NULL)) 195 + return -EIO; 475 196 *p++ = htonl(argp->prog); 476 197 *p++ = htonl(argp->vers); 477 198 *p++ = htonl(argp->proc); 478 - 479 - return p; 199 + return 0; 480 200 } 481 201 482 202 /* 483 203 * The "mon_id" argument specifies the non-private arguments 484 - * of an SM_MON or SM_UNMON call. 204 + * of an NSMPROC_MON or NSMPROC_UNMON call. 485 205 */ 486 - static __be32 *xdr_encode_mon_id(__be32 *p, struct nsm_args *argp) 206 + static int encode_mon_id(struct xdr_stream *xdr, const struct nsm_args *argp) 487 207 { 488 - p = xdr_encode_mon_name(p, argp); 489 - if (!p) 490 - return ERR_PTR(-EIO); 208 + int status; 491 209 492 - return xdr_encode_my_id(p, argp); 210 + status = encode_mon_name(xdr, argp); 211 + if (unlikely(status != 0)) 212 + return status; 213 + return encode_my_id(xdr, argp); 493 214 } 494 215 495 216 /* 496 217 * The "priv" argument may contain private information required 497 - * by the SM_MON call. This information will be supplied in the 498 - * SM_NOTIFY call. 499 - * 500 - * Linux provides the raw IP address of the monitored host, 501 - * left in network byte order. 218 + * by the NSMPROC_MON call. This information will be supplied in the 219 + * NLMPROC_SM_NOTIFY call. 502 220 */ 503 - static __be32 *xdr_encode_priv(__be32 *p, struct nsm_args *argp) 221 + static int encode_priv(struct xdr_stream *xdr, const struct nsm_args *argp) 504 222 { 505 - *p++ = argp->addr; 506 - *p++ = 0; 507 - *p++ = 0; 508 - *p++ = 0; 223 + __be32 *p; 509 224 510 - return p; 511 - } 512 - 513 - static int 514 - xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) 515 - { 516 - p = xdr_encode_mon_id(p, argp); 517 - if (IS_ERR(p)) 518 - return PTR_ERR(p); 519 - 520 - p = xdr_encode_priv(p, argp); 521 - if (IS_ERR(p)) 522 - return PTR_ERR(p); 523 - 524 - rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p); 225 + p = xdr_reserve_space(xdr, SM_PRIV_SIZE); 226 + if (unlikely(p == NULL)) 227 + return -EIO; 228 + xdr_encode_opaque_fixed(p, argp->priv->data, SM_PRIV_SIZE); 525 229 return 0; 526 230 } 527 231 528 - static int 529 - xdr_encode_unmon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) 232 + static int xdr_enc_mon(struct rpc_rqst *req, __be32 *p, 233 + const struct nsm_args *argp) 530 234 { 531 - p = xdr_encode_mon_id(p, argp); 532 - if (IS_ERR(p)) 533 - return PTR_ERR(p); 534 - rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p); 535 - return 0; 235 + struct xdr_stream xdr; 236 + int status; 237 + 238 + xdr_init_encode(&xdr, &req->rq_snd_buf, p); 239 + status = encode_mon_id(&xdr, argp); 240 + if (unlikely(status)) 241 + return status; 242 + return encode_priv(&xdr, argp); 536 243 } 537 244 538 - static int 539 - xdr_decode_stat_res(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp) 245 + static int xdr_enc_unmon(struct rpc_rqst *req, __be32 *p, 246 + const struct nsm_args *argp) 540 247 { 248 + struct xdr_stream xdr; 249 + 250 + xdr_init_encode(&xdr, &req->rq_snd_buf, p); 251 + return encode_mon_id(&xdr, argp); 252 + } 253 + 254 + static int xdr_dec_stat_res(struct rpc_rqst *rqstp, __be32 *p, 255 + struct nsm_res *resp) 256 + { 257 + struct xdr_stream xdr; 258 + 259 + xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); 260 + p = xdr_inline_decode(&xdr, 2 * sizeof(u32)); 261 + if (unlikely(p == NULL)) 262 + return -EIO; 541 263 resp->status = ntohl(*p++); 542 - resp->state = ntohl(*p++); 543 - dprintk("nsm: xdr_decode_stat_res status %d state %d\n", 264 + resp->state = ntohl(*p); 265 + 266 + dprintk("lockd: xdr_dec_stat_res status %d state %d\n", 544 267 resp->status, resp->state); 545 268 return 0; 546 269 } 547 270 548 - static int 549 - xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp) 271 + static int xdr_dec_stat(struct rpc_rqst *rqstp, __be32 *p, 272 + struct nsm_res *resp) 550 273 { 551 - resp->state = ntohl(*p++); 274 + struct xdr_stream xdr; 275 + 276 + xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); 277 + p = xdr_inline_decode(&xdr, sizeof(u32)); 278 + if (unlikely(p == NULL)) 279 + return -EIO; 280 + resp->state = ntohl(*p); 281 + 282 + dprintk("lockd: xdr_dec_stat state %d\n", resp->state); 552 283 return 0; 553 284 } 554 285 ··· 567 288 #define SM_unmonres_sz 1 568 289 569 290 static struct rpc_procinfo nsm_procedures[] = { 570 - [SM_MON] = { 571 - .p_proc = SM_MON, 572 - .p_encode = (kxdrproc_t) xdr_encode_mon, 573 - .p_decode = (kxdrproc_t) xdr_decode_stat_res, 291 + [NSMPROC_MON] = { 292 + .p_proc = NSMPROC_MON, 293 + .p_encode = (kxdrproc_t)xdr_enc_mon, 294 + .p_decode = (kxdrproc_t)xdr_dec_stat_res, 574 295 .p_arglen = SM_mon_sz, 575 296 .p_replen = SM_monres_sz, 576 - .p_statidx = SM_MON, 297 + .p_statidx = NSMPROC_MON, 577 298 .p_name = "MONITOR", 578 299 }, 579 - [SM_UNMON] = { 580 - .p_proc = SM_UNMON, 581 - .p_encode = (kxdrproc_t) xdr_encode_unmon, 582 - .p_decode = (kxdrproc_t) xdr_decode_stat, 300 + [NSMPROC_UNMON] = { 301 + .p_proc = NSMPROC_UNMON, 302 + .p_encode = (kxdrproc_t)xdr_enc_unmon, 303 + .p_decode = (kxdrproc_t)xdr_dec_stat, 583 304 .p_arglen = SM_mon_id_sz, 584 305 .p_replen = SM_unmonres_sz, 585 - .p_statidx = SM_UNMON, 306 + .p_statidx = NSMPROC_UNMON, 586 307 .p_name = "UNMONITOR", 587 308 }, 588 309 }; ··· 601 322 602 323 static struct rpc_program nsm_program = { 603 324 .name = "statd", 604 - .number = SM_PROGRAM, 325 + .number = NSM_PROGRAM, 605 326 .nrvers = ARRAY_SIZE(nsm_version), 606 327 .version = nsm_version, 607 328 .stats = &nsm_stats
+48 -24
fs/lockd/svc.c
··· 35 35 #include <linux/sunrpc/svcsock.h> 36 36 #include <net/ip.h> 37 37 #include <linux/lockd/lockd.h> 38 - #include <linux/lockd/sm_inter.h> 39 38 #include <linux/nfs.h> 40 39 41 40 #define NLMDBG_FACILITY NLMDBG_SVC ··· 53 54 unsigned long nlmsvc_timeout; 54 55 55 56 /* 57 + * If the kernel has IPv6 support available, always listen for 58 + * both AF_INET and AF_INET6 requests. 59 + */ 60 + #if (defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)) && \ 61 + defined(CONFIG_SUNRPC_REGISTER_V4) 62 + static const sa_family_t nlmsvc_family = AF_INET6; 63 + #else /* (CONFIG_IPV6 || CONFIG_IPV6_MODULE) && CONFIG_SUNRPC_REGISTER_V4 */ 64 + static const sa_family_t nlmsvc_family = AF_INET; 65 + #endif /* (CONFIG_IPV6 || CONFIG_IPV6_MODULE) && CONFIG_SUNRPC_REGISTER_V4 */ 66 + 67 + /* 56 68 * These can be set at insmod time (useful for NFS as root filesystem), 57 69 * and also changed through the sysctl interface. -- Jamie Lokier, Aug 2003 58 70 */ 59 71 static unsigned long nlm_grace_period; 60 72 static unsigned long nlm_timeout = LOCKD_DFLT_TIMEO; 61 73 static int nlm_udpport, nlm_tcpport; 62 - int nsm_use_hostnames = 0; 74 + 75 + /* RLIM_NOFILE defaults to 1024. That seems like a reasonable default here. */ 76 + static unsigned int nlm_max_connections = 1024; 63 77 64 78 /* 65 79 * Constants needed for the sysctl interface. ··· 155 143 long timeout = MAX_SCHEDULE_TIMEOUT; 156 144 RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); 157 145 146 + /* update sv_maxconn if it has changed */ 147 + rqstp->rq_server->sv_maxconn = nlm_max_connections; 148 + 158 149 if (signalled()) { 159 150 flush_signals(current); 160 151 if (nlmsvc_ops) { ··· 204 189 return 0; 205 190 } 206 191 192 + static int create_lockd_listener(struct svc_serv *serv, char *name, 193 + unsigned short port) 194 + { 195 + struct svc_xprt *xprt; 196 + 197 + xprt = svc_find_xprt(serv, name, 0, 0); 198 + if (xprt == NULL) 199 + return svc_create_xprt(serv, name, port, SVC_SOCK_DEFAULTS); 200 + 201 + svc_xprt_put(xprt); 202 + return 0; 203 + } 204 + 207 205 /* 208 206 * Ensure there are active UDP and TCP listeners for lockd. 209 207 * ··· 230 202 static int make_socks(struct svc_serv *serv) 231 203 { 232 204 static int warned; 233 - struct svc_xprt *xprt; 234 - int err = 0; 205 + int err; 235 206 236 - xprt = svc_find_xprt(serv, "udp", 0, 0); 237 - if (!xprt) 238 - err = svc_create_xprt(serv, "udp", nlm_udpport, 239 - SVC_SOCK_DEFAULTS); 240 - else 241 - svc_xprt_put(xprt); 242 - if (err >= 0) { 243 - xprt = svc_find_xprt(serv, "tcp", 0, 0); 244 - if (!xprt) 245 - err = svc_create_xprt(serv, "tcp", nlm_tcpport, 246 - SVC_SOCK_DEFAULTS); 247 - else 248 - svc_xprt_put(xprt); 249 - } 250 - if (err >= 0) { 251 - warned = 0; 252 - err = 0; 253 - } else if (warned++ == 0) 207 + err = create_lockd_listener(serv, "udp", nlm_udpport); 208 + if (err < 0) 209 + goto out_err; 210 + 211 + err = create_lockd_listener(serv, "tcp", nlm_tcpport); 212 + if (err < 0) 213 + goto out_err; 214 + 215 + warned = 0; 216 + return 0; 217 + 218 + out_err: 219 + if (warned++ == 0) 254 220 printk(KERN_WARNING 255 - "lockd_up: makesock failed, error=%d\n", err); 221 + "lockd_up: makesock failed, error=%d\n", err); 256 222 return err; 257 223 } 258 224 ··· 274 252 "lockd_up: no pid, %d users??\n", nlmsvc_users); 275 253 276 254 error = -ENOMEM; 277 - serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, AF_INET, NULL); 255 + serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, nlmsvc_family, NULL); 278 256 if (!serv) { 279 257 printk(KERN_WARNING "lockd_up: create service failed\n"); 280 258 goto out; ··· 298 276 } 299 277 300 278 svc_sock_update_bufs(serv); 279 + serv->sv_maxconn = nlm_max_connections; 301 280 302 281 nlmsvc_task = kthread_run(lockd, nlmsvc_rqst, serv->sv_name); 303 282 if (IS_ERR(nlmsvc_task)) { ··· 508 485 module_param_call(nlm_tcpport, param_set_port, param_get_int, 509 486 &nlm_tcpport, 0644); 510 487 module_param(nsm_use_hostnames, bool, 0644); 488 + module_param(nlm_max_connections, uint, 0644); 511 489 512 490 /* 513 491 * Initialising and terminating the module.
+1 -12
fs/lockd/svc4proc.c
··· 16 16 #include <linux/nfsd/nfsd.h> 17 17 #include <linux/lockd/lockd.h> 18 18 #include <linux/lockd/share.h> 19 - #include <linux/lockd/sm_inter.h> 20 - 21 19 22 20 #define NLMDBG_FACILITY NLMDBG_CLIENT 23 21 ··· 417 419 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, 418 420 void *resp) 419 421 { 420 - struct sockaddr_in saddr; 421 - 422 422 dprintk("lockd: SM_NOTIFY called\n"); 423 423 424 424 if (!nlm_privileged_requester(rqstp)) { ··· 426 430 return rpc_system_err; 427 431 } 428 432 429 - /* Obtain the host pointer for this NFS server and try to 430 - * reclaim all locks we hold on this server. 431 - */ 432 - memset(&saddr, 0, sizeof(saddr)); 433 - saddr.sin_family = AF_INET; 434 - saddr.sin_addr.s_addr = argp->addr; 435 - nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state); 436 - 433 + nlm_host_rebooted(argp); 437 434 return rpc_success; 438 435 } 439 436
+1 -12
fs/lockd/svcproc.c
··· 16 16 #include <linux/nfsd/nfsd.h> 17 17 #include <linux/lockd/lockd.h> 18 18 #include <linux/lockd/share.h> 19 - #include <linux/lockd/sm_inter.h> 20 - 21 19 22 20 #define NLMDBG_FACILITY NLMDBG_CLIENT 23 21 ··· 449 451 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, 450 452 void *resp) 451 453 { 452 - struct sockaddr_in saddr; 453 - 454 454 dprintk("lockd: SM_NOTIFY called\n"); 455 455 456 456 if (!nlm_privileged_requester(rqstp)) { ··· 458 462 return rpc_system_err; 459 463 } 460 464 461 - /* Obtain the host pointer for this NFS server and try to 462 - * reclaim all locks we hold on this server. 463 - */ 464 - memset(&saddr, 0, sizeof(saddr)); 465 - saddr.sin_family = AF_INET; 466 - saddr.sin_addr.s_addr = argp->addr; 467 - nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state); 468 - 465 + nlm_host_rebooted(argp); 469 466 return rpc_success; 470 467 } 471 468
-1
fs/lockd/svcsubs.c
··· 17 17 #include <linux/nfsd/export.h> 18 18 #include <linux/lockd/lockd.h> 19 19 #include <linux/lockd/share.h> 20 - #include <linux/lockd/sm_inter.h> 21 20 #include <linux/module.h> 22 21 #include <linux/mount.h> 23 22
+2 -3
fs/lockd/xdr.c
··· 16 16 #include <linux/sunrpc/svc.h> 17 17 #include <linux/sunrpc/stats.h> 18 18 #include <linux/lockd/lockd.h> 19 - #include <linux/lockd/sm_inter.h> 20 19 21 20 #define NLMDBG_FACILITY NLMDBG_XDR 22 21 ··· 348 349 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) 349 350 return 0; 350 351 argp->state = ntohl(*p++); 351 - /* Preserve the address in network byte order */ 352 - argp->addr = *p++; 352 + memcpy(&argp->priv.data, p, sizeof(argp->priv.data)); 353 + p += XDR_QUADLEN(SM_PRIV_SIZE); 353 354 return xdr_argsize_check(rqstp, p); 354 355 } 355 356
+2 -3
fs/lockd/xdr4.c
··· 17 17 #include <linux/sunrpc/svc.h> 18 18 #include <linux/sunrpc/stats.h> 19 19 #include <linux/lockd/lockd.h> 20 - #include <linux/lockd/sm_inter.h> 21 20 22 21 #define NLMDBG_FACILITY NLMDBG_XDR 23 22 ··· 355 356 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) 356 357 return 0; 357 358 argp->state = ntohl(*p++); 358 - /* Preserve the address in network byte order */ 359 - argp->addr = *p++; 359 + memcpy(&argp->priv.data, p, sizeof(argp->priv.data)); 360 + p += XDR_QUADLEN(SM_PRIV_SIZE); 360 361 return xdr_argsize_check(rqstp, p); 361 362 } 362 363
+2 -2
fs/nfsd/auth.c
··· 76 76 77 77 ret = set_groups(new, gi); 78 78 put_group_info(gi); 79 - if (!ret) 79 + if (ret < 0) 80 80 goto error; 81 81 82 - if (new->uid) 82 + if (new->fsuid) 83 83 new->cap_effective = cap_drop_nfsd_set(new->cap_effective); 84 84 else 85 85 new->cap_effective = cap_raise_nfsd_set(new->cap_effective,
-3
fs/nfsd/nfs4callback.c
··· 53 53 #define NFSPROC4_CB_NULL 0 54 54 #define NFSPROC4_CB_COMPOUND 1 55 55 56 - /* declarations */ 57 - static const struct rpc_call_ops nfs4_cb_null_ops; 58 - 59 56 /* Index of predefined Linux callback client operations */ 60 57 61 58 enum {
+5
fs/nfsd/nfs4proc.c
··· 946 946 nfsd4_encode_operation(resp, op); 947 947 status = op->status; 948 948 } 949 + 950 + dprintk("nfsv4 compound op %p opcnt %d #%d: %d: status %d\n", 951 + args->ops, args->opcnt, resp->opcnt, op->opnum, 952 + be32_to_cpu(status)); 953 + 949 954 if (cstate->replay_owner) { 950 955 nfs4_put_stateowner(cstate->replay_owner); 951 956 cstate->replay_owner = NULL;
+1 -1
fs/nfsd/nfs4recover.c
··· 116 116 117 117 md5_to_hex(dname, cksum.data); 118 118 119 - kfree(cksum.data); 120 119 status = nfs_ok; 121 120 out: 121 + kfree(cksum.data); 122 122 crypto_free_hash(desc.tfm); 123 123 out_no_tfm: 124 124 return status;
+50 -29
fs/nfsd/nfs4state.c
··· 2416 2416 #define LOCK_HASH_SIZE (1 << LOCK_HASH_BITS) 2417 2417 #define LOCK_HASH_MASK (LOCK_HASH_SIZE - 1) 2418 2418 2419 + static inline u64 2420 + end_offset(u64 start, u64 len) 2421 + { 2422 + u64 end; 2423 + 2424 + end = start + len; 2425 + return end >= start ? end: NFS4_MAX_UINT64; 2426 + } 2427 + 2428 + /* last octet in a range */ 2429 + static inline u64 2430 + last_byte_offset(u64 start, u64 len) 2431 + { 2432 + u64 end; 2433 + 2434 + BUG_ON(!len); 2435 + end = start + len; 2436 + return end > start ? end - 1: NFS4_MAX_UINT64; 2437 + } 2438 + 2419 2439 #define lockownerid_hashval(id) \ 2420 2440 ((id) & LOCK_HASH_MASK) 2421 2441 ··· 2455 2435 static struct nfs4_stateid * 2456 2436 find_stateid(stateid_t *stid, int flags) 2457 2437 { 2458 - struct nfs4_stateid *local = NULL; 2438 + struct nfs4_stateid *local; 2459 2439 u32 st_id = stid->si_stateownerid; 2460 2440 u32 f_id = stid->si_fileid; 2461 2441 unsigned int hashval; 2462 2442 2463 2443 dprintk("NFSD: find_stateid flags 0x%x\n",flags); 2464 - if ((flags & LOCK_STATE) || (flags & RD_STATE) || (flags & WR_STATE)) { 2444 + if (flags & (LOCK_STATE | RD_STATE | WR_STATE)) { 2465 2445 hashval = stateid_hashval(st_id, f_id); 2466 2446 list_for_each_entry(local, &lockstateid_hashtbl[hashval], st_hash) { 2467 2447 if ((local->st_stateid.si_stateownerid == st_id) && ··· 2469 2449 return local; 2470 2450 } 2471 2451 } 2472 - if ((flags & OPEN_STATE) || (flags & RD_STATE) || (flags & WR_STATE)) { 2452 + 2453 + if (flags & (OPEN_STATE | RD_STATE | WR_STATE)) { 2473 2454 hashval = stateid_hashval(st_id, f_id); 2474 2455 list_for_each_entry(local, &stateid_hashtbl[hashval], st_hash) { 2475 2456 if ((local->st_stateid.si_stateownerid == st_id) && ··· 2539 2518 deny->ld_clientid.cl_id = 0; 2540 2519 } 2541 2520 deny->ld_start = fl->fl_start; 2542 - deny->ld_length = ~(u64)0; 2543 - if (fl->fl_end != ~(u64)0) 2521 + deny->ld_length = NFS4_MAX_UINT64; 2522 + if (fl->fl_end != NFS4_MAX_UINT64) 2544 2523 deny->ld_length = fl->fl_end - fl->fl_start + 1; 2545 2524 deny->ld_type = NFS4_READ_LT; 2546 2525 if (fl->fl_type != F_RDLCK) ··· 2637 2616 static int 2638 2617 check_lock_length(u64 offset, u64 length) 2639 2618 { 2640 - return ((length == 0) || ((length != ~(u64)0) && 2619 + return ((length == 0) || ((length != NFS4_MAX_UINT64) && 2641 2620 LOFF_OVERFLOW(offset, length))); 2642 2621 } 2643 2622 ··· 2757 2736 file_lock.fl_lmops = &nfsd_posix_mng_ops; 2758 2737 2759 2738 file_lock.fl_start = lock->lk_offset; 2760 - if ((lock->lk_length == ~(u64)0) || 2761 - LOFF_OVERFLOW(lock->lk_offset, lock->lk_length)) 2762 - file_lock.fl_end = ~(u64)0; 2763 - else 2764 - file_lock.fl_end = lock->lk_offset + lock->lk_length - 1; 2739 + file_lock.fl_end = last_byte_offset(lock->lk_offset, lock->lk_length); 2765 2740 nfs4_transform_lock_offset(&file_lock); 2766 2741 2767 2742 /* ··· 2798 2781 } 2799 2782 2800 2783 /* 2784 + * The NFSv4 spec allows a client to do a LOCKT without holding an OPEN, 2785 + * so we do a temporary open here just to get an open file to pass to 2786 + * vfs_test_lock. (Arguably perhaps test_lock should be done with an 2787 + * inode operation.) 2788 + */ 2789 + static int nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock) 2790 + { 2791 + struct file *file; 2792 + int err; 2793 + 2794 + err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); 2795 + if (err) 2796 + return err; 2797 + err = vfs_test_lock(file, lock); 2798 + nfsd_close(file); 2799 + return err; 2800 + } 2801 + 2802 + /* 2801 2803 * LOCKT operation 2802 2804 */ 2803 2805 __be32 ··· 2824 2788 struct nfsd4_lockt *lockt) 2825 2789 { 2826 2790 struct inode *inode; 2827 - struct file file; 2828 2791 struct file_lock file_lock; 2829 2792 int error; 2830 2793 __be32 status; ··· 2874 2839 file_lock.fl_lmops = &nfsd_posix_mng_ops; 2875 2840 2876 2841 file_lock.fl_start = lockt->lt_offset; 2877 - if ((lockt->lt_length == ~(u64)0) || LOFF_OVERFLOW(lockt->lt_offset, lockt->lt_length)) 2878 - file_lock.fl_end = ~(u64)0; 2879 - else 2880 - file_lock.fl_end = lockt->lt_offset + lockt->lt_length - 1; 2842 + file_lock.fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length); 2881 2843 2882 2844 nfs4_transform_lock_offset(&file_lock); 2883 2845 2884 - /* vfs_test_lock uses the struct file _only_ to resolve the inode. 2885 - * since LOCKT doesn't require an OPEN, and therefore a struct 2886 - * file may not exist, pass vfs_test_lock a struct file with 2887 - * only the dentry:inode set. 2888 - */ 2889 - memset(&file, 0, sizeof (struct file)); 2890 - file.f_path.dentry = cstate->current_fh.fh_dentry; 2891 - 2892 2846 status = nfs_ok; 2893 - error = vfs_test_lock(&file, &file_lock); 2847 + error = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock); 2894 2848 if (error) { 2895 2849 status = nfserrno(error); 2896 2850 goto out; ··· 2930 2906 file_lock.fl_lmops = &nfsd_posix_mng_ops; 2931 2907 file_lock.fl_start = locku->lu_offset; 2932 2908 2933 - if ((locku->lu_length == ~(u64)0) || LOFF_OVERFLOW(locku->lu_offset, locku->lu_length)) 2934 - file_lock.fl_end = ~(u64)0; 2935 - else 2936 - file_lock.fl_end = locku->lu_offset + locku->lu_length - 1; 2909 + file_lock.fl_end = last_byte_offset(locku->lu_offset, locku->lu_length); 2937 2910 nfs4_transform_lock_offset(&file_lock); 2938 2911 2939 2912 /*
-2
fs/nfsd/nfs4xdr.c
··· 1 1 /* 2 - * fs/nfs/nfs4xdr.c 3 - * 4 2 * Server-side XDR for NFSv4 5 3 * 6 4 * Copyright (c) 2002 The Regents of the University of Michigan.
+451 -28
fs/nfsd/nfsctl.c
··· 84 84 static ssize_t write_getfd(struct file *file, char *buf, size_t size); 85 85 static ssize_t write_getfs(struct file *file, char *buf, size_t size); 86 86 static ssize_t write_filehandle(struct file *file, char *buf, size_t size); 87 + static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size); 88 + static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size); 87 89 static ssize_t write_threads(struct file *file, char *buf, size_t size); 88 90 static ssize_t write_pool_threads(struct file *file, char *buf, size_t size); 89 91 static ssize_t write_versions(struct file *file, char *buf, size_t size); ··· 96 94 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); 97 95 #endif 98 96 99 - static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size); 100 - static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size); 101 - 102 97 static ssize_t (*write_op[])(struct file *, char *, size_t) = { 103 98 [NFSD_Svc] = write_svc, 104 99 [NFSD_Add] = write_add, ··· 105 106 [NFSD_Getfd] = write_getfd, 106 107 [NFSD_Getfs] = write_getfs, 107 108 [NFSD_Fh] = write_filehandle, 108 - [NFSD_FO_UnlockIP] = failover_unlock_ip, 109 - [NFSD_FO_UnlockFS] = failover_unlock_fs, 109 + [NFSD_FO_UnlockIP] = write_unlock_ip, 110 + [NFSD_FO_UnlockFS] = write_unlock_fs, 110 111 [NFSD_Threads] = write_threads, 111 112 [NFSD_Pool_Threads] = write_pool_threads, 112 113 [NFSD_Versions] = write_versions, ··· 175 176 /*----------------------------------------------------------------------------*/ 176 177 /* 177 178 * payload - write methods 178 - * If the method has a response, the response should be put in buf, 179 - * and the length returned. Otherwise return 0 or and -error. 180 179 */ 181 180 181 + /** 182 + * write_svc - Start kernel's NFSD server 183 + * 184 + * Deprecated. /proc/fs/nfsd/threads is preferred. 185 + * Function remains to support old versions of nfs-utils. 186 + * 187 + * Input: 188 + * buf: struct nfsctl_svc 189 + * svc_port: port number of this 190 + * server's listener 191 + * svc_nthreads: number of threads to start 192 + * size: size in bytes of passed in nfsctl_svc 193 + * Output: 194 + * On success: returns zero 195 + * On error: return code is negative errno value 196 + */ 182 197 static ssize_t write_svc(struct file *file, char *buf, size_t size) 183 198 { 184 199 struct nfsctl_svc *data; ··· 202 189 return nfsd_svc(data->svc_port, data->svc_nthreads); 203 190 } 204 191 192 + /** 193 + * write_add - Add or modify client entry in auth unix cache 194 + * 195 + * Deprecated. /proc/net/rpc/auth.unix.ip is preferred. 196 + * Function remains to support old versions of nfs-utils. 197 + * 198 + * Input: 199 + * buf: struct nfsctl_client 200 + * cl_ident: '\0'-terminated C string 201 + * containing domain name 202 + * of client 203 + * cl_naddr: no. of items in cl_addrlist 204 + * cl_addrlist: array of client addresses 205 + * cl_fhkeytype: ignored 206 + * cl_fhkeylen: ignored 207 + * cl_fhkey: ignored 208 + * size: size in bytes of passed in nfsctl_client 209 + * Output: 210 + * On success: returns zero 211 + * On error: return code is negative errno value 212 + * 213 + * Note: Only AF_INET client addresses are passed in, since 214 + * nfsctl_client.cl_addrlist contains only in_addr fields for addresses. 215 + */ 205 216 static ssize_t write_add(struct file *file, char *buf, size_t size) 206 217 { 207 218 struct nfsctl_client *data; ··· 235 198 return exp_addclient(data); 236 199 } 237 200 201 + /** 202 + * write_del - Remove client from auth unix cache 203 + * 204 + * Deprecated. /proc/net/rpc/auth.unix.ip is preferred. 205 + * Function remains to support old versions of nfs-utils. 206 + * 207 + * Input: 208 + * buf: struct nfsctl_client 209 + * cl_ident: '\0'-terminated C string 210 + * containing domain name 211 + * of client 212 + * cl_naddr: ignored 213 + * cl_addrlist: ignored 214 + * cl_fhkeytype: ignored 215 + * cl_fhkeylen: ignored 216 + * cl_fhkey: ignored 217 + * size: size in bytes of passed in nfsctl_client 218 + * Output: 219 + * On success: returns zero 220 + * On error: return code is negative errno value 221 + * 222 + * Note: Only AF_INET client addresses are passed in, since 223 + * nfsctl_client.cl_addrlist contains only in_addr fields for addresses. 224 + */ 238 225 static ssize_t write_del(struct file *file, char *buf, size_t size) 239 226 { 240 227 struct nfsctl_client *data; ··· 268 207 return exp_delclient(data); 269 208 } 270 209 210 + /** 211 + * write_export - Export part or all of a local file system 212 + * 213 + * Deprecated. /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred. 214 + * Function remains to support old versions of nfs-utils. 215 + * 216 + * Input: 217 + * buf: struct nfsctl_export 218 + * ex_client: '\0'-terminated C string 219 + * containing domain name 220 + * of client allowed to access 221 + * this export 222 + * ex_path: '\0'-terminated C string 223 + * containing pathname of 224 + * directory in local file system 225 + * ex_dev: fsid to use for this export 226 + * ex_ino: ignored 227 + * ex_flags: export flags for this export 228 + * ex_anon_uid: UID to use for anonymous 229 + * requests 230 + * ex_anon_gid: GID to use for anonymous 231 + * requests 232 + * size: size in bytes of passed in nfsctl_export 233 + * Output: 234 + * On success: returns zero 235 + * On error: return code is negative errno value 236 + */ 271 237 static ssize_t write_export(struct file *file, char *buf, size_t size) 272 238 { 273 239 struct nfsctl_export *data; ··· 304 216 return exp_export(data); 305 217 } 306 218 219 + /** 220 + * write_unexport - Unexport a previously exported file system 221 + * 222 + * Deprecated. /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred. 223 + * Function remains to support old versions of nfs-utils. 224 + * 225 + * Input: 226 + * buf: struct nfsctl_export 227 + * ex_client: '\0'-terminated C string 228 + * containing domain name 229 + * of client no longer allowed 230 + * to access this export 231 + * ex_path: '\0'-terminated C string 232 + * containing pathname of 233 + * directory in local file system 234 + * ex_dev: ignored 235 + * ex_ino: ignored 236 + * ex_flags: ignored 237 + * ex_anon_uid: ignored 238 + * ex_anon_gid: ignored 239 + * size: size in bytes of passed in nfsctl_export 240 + * Output: 241 + * On success: returns zero 242 + * On error: return code is negative errno value 243 + */ 307 244 static ssize_t write_unexport(struct file *file, char *buf, size_t size) 308 245 { 309 246 struct nfsctl_export *data; ··· 339 226 return exp_unexport(data); 340 227 } 341 228 229 + /** 230 + * write_getfs - Get a variable-length NFS file handle by path 231 + * 232 + * Deprecated. /proc/fs/nfsd/filehandle is preferred. 233 + * Function remains to support old versions of nfs-utils. 234 + * 235 + * Input: 236 + * buf: struct nfsctl_fsparm 237 + * gd_addr: socket address of client 238 + * gd_path: '\0'-terminated C string 239 + * containing pathname of 240 + * directory in local file system 241 + * gd_maxlen: maximum size of returned file 242 + * handle 243 + * size: size in bytes of passed in nfsctl_fsparm 244 + * Output: 245 + * On success: passed-in buffer filled with a knfsd_fh structure 246 + * (a variable-length raw NFS file handle); 247 + * return code is the size in bytes of the file handle 248 + * On error: return code is negative errno value 249 + * 250 + * Note: Only AF_INET client addresses are passed in, since gd_addr 251 + * is the same size as a struct sockaddr_in. 252 + */ 342 253 static ssize_t write_getfs(struct file *file, char *buf, size_t size) 343 254 { 344 255 struct nfsctl_fsparm *data; ··· 402 265 return err; 403 266 } 404 267 268 + /** 269 + * write_getfd - Get a fixed-length NFS file handle by path (used by mountd) 270 + * 271 + * Deprecated. /proc/fs/nfsd/filehandle is preferred. 272 + * Function remains to support old versions of nfs-utils. 273 + * 274 + * Input: 275 + * buf: struct nfsctl_fdparm 276 + * gd_addr: socket address of client 277 + * gd_path: '\0'-terminated C string 278 + * containing pathname of 279 + * directory in local file system 280 + * gd_version: fdparm structure version 281 + * size: size in bytes of passed in nfsctl_fdparm 282 + * Output: 283 + * On success: passed-in buffer filled with nfsctl_res 284 + * (a fixed-length raw NFS file handle); 285 + * return code is the size in bytes of the file handle 286 + * On error: return code is negative errno value 287 + * 288 + * Note: Only AF_INET client addresses are passed in, since gd_addr 289 + * is the same size as a struct sockaddr_in. 290 + */ 405 291 static ssize_t write_getfd(struct file *file, char *buf, size_t size) 406 292 { 407 293 struct nfsctl_fdparm *data; ··· 469 309 return err; 470 310 } 471 311 472 - static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size) 312 + /** 313 + * write_unlock_ip - Release all locks used by a client 314 + * 315 + * Experimental. 316 + * 317 + * Input: 318 + * buf: '\n'-terminated C string containing a 319 + * presentation format IPv4 address 320 + * size: length of C string in @buf 321 + * Output: 322 + * On success: returns zero if all specified locks were released; 323 + * returns one if one or more locks were not released 324 + * On error: return code is negative errno value 325 + * 326 + * Note: Only AF_INET client addresses are passed in 327 + */ 328 + static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size) 473 329 { 474 330 struct sockaddr_in sin = { 475 331 .sin_family = AF_INET, ··· 515 339 return nlmsvc_unlock_all_by_ip((struct sockaddr *)&sin); 516 340 } 517 341 518 - static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size) 342 + /** 343 + * write_unlock_fs - Release all locks on a local file system 344 + * 345 + * Experimental. 346 + * 347 + * Input: 348 + * buf: '\n'-terminated C string containing the 349 + * absolute pathname of a local file system 350 + * size: length of C string in @buf 351 + * Output: 352 + * On success: returns zero if all specified locks were released; 353 + * returns one if one or more locks were not released 354 + * On error: return code is negative errno value 355 + */ 356 + static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size) 519 357 { 520 358 struct path path; 521 359 char *fo_path; ··· 550 360 if (error) 551 361 return error; 552 362 363 + /* 364 + * XXX: Needs better sanity checking. Otherwise we could end up 365 + * releasing locks on the wrong file system. 366 + * 367 + * For example: 368 + * 1. Does the path refer to a directory? 369 + * 2. Is that directory a mount point, or 370 + * 3. Is that directory the root of an exported file system? 371 + */ 553 372 error = nlmsvc_unlock_all_by_sb(path.mnt->mnt_sb); 554 373 555 374 path_put(&path); 556 375 return error; 557 376 } 558 377 378 + /** 379 + * write_filehandle - Get a variable-length NFS file handle by path 380 + * 381 + * On input, the buffer contains a '\n'-terminated C string comprised of 382 + * three alphanumeric words separated by whitespace. The string may 383 + * contain escape sequences. 384 + * 385 + * Input: 386 + * buf: 387 + * domain: client domain name 388 + * path: export pathname 389 + * maxsize: numeric maximum size of 390 + * @buf 391 + * size: length of C string in @buf 392 + * Output: 393 + * On success: passed-in buffer filled with '\n'-terminated C 394 + * string containing a ASCII hex text version 395 + * of the NFS file handle; 396 + * return code is the size in bytes of the string 397 + * On error: return code is negative errno value 398 + */ 559 399 static ssize_t write_filehandle(struct file *file, char *buf, size_t size) 560 400 { 561 - /* request is: 562 - * domain path maxsize 563 - * response is 564 - * filehandle 565 - * 566 - * qword quoting is used, so filehandle will be \x.... 567 - */ 568 401 char *dname, *path; 569 402 int uninitialized_var(maxsize); 570 403 char *mesg = buf; ··· 604 391 605 392 dname = mesg; 606 393 len = qword_get(&mesg, dname, size); 607 - if (len <= 0) return -EINVAL; 394 + if (len <= 0) 395 + return -EINVAL; 608 396 609 397 path = dname+len+1; 610 398 len = qword_get(&mesg, path, size); 611 - if (len <= 0) return -EINVAL; 399 + if (len <= 0) 400 + return -EINVAL; 612 401 613 402 len = get_int(&mesg, &maxsize); 614 403 if (len) ··· 634 419 if (len) 635 420 return len; 636 421 637 - mesg = buf; len = SIMPLE_TRANSACTION_LIMIT; 422 + mesg = buf; 423 + len = SIMPLE_TRANSACTION_LIMIT; 638 424 qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size); 639 425 mesg[-1] = '\n'; 640 426 return mesg - buf; 641 427 } 642 428 429 + /** 430 + * write_threads - Start NFSD, or report the current number of running threads 431 + * 432 + * Input: 433 + * buf: ignored 434 + * size: zero 435 + * Output: 436 + * On success: passed-in buffer filled with '\n'-terminated C 437 + * string numeric value representing the number of 438 + * running NFSD threads; 439 + * return code is the size in bytes of the string 440 + * On error: return code is zero 441 + * 442 + * OR 443 + * 444 + * Input: 445 + * buf: C string containing an unsigned 446 + * integer value representing the 447 + * number of NFSD threads to start 448 + * size: non-zero length of C string in @buf 449 + * Output: 450 + * On success: NFS service is started; 451 + * passed-in buffer filled with '\n'-terminated C 452 + * string numeric value representing the number of 453 + * running NFSD threads; 454 + * return code is the size in bytes of the string 455 + * On error: return code is zero or a negative errno value 456 + */ 643 457 static ssize_t write_threads(struct file *file, char *buf, size_t size) 644 458 { 645 - /* if size > 0, look for a number of threads and call nfsd_svc 646 - * then write out number of threads as reply 647 - */ 648 459 char *mesg = buf; 649 460 int rv; 650 461 if (size > 0) { ··· 678 437 rv = get_int(&mesg, &newthreads); 679 438 if (rv) 680 439 return rv; 681 - if (newthreads <0) 440 + if (newthreads < 0) 682 441 return -EINVAL; 683 - rv = nfsd_svc(2049, newthreads); 442 + rv = nfsd_svc(NFS_PORT, newthreads); 684 443 if (rv) 685 444 return rv; 686 445 } ··· 688 447 return strlen(buf); 689 448 } 690 449 450 + /** 451 + * write_pool_threads - Set or report the current number of threads per pool 452 + * 453 + * Input: 454 + * buf: ignored 455 + * size: zero 456 + * 457 + * OR 458 + * 459 + * Input: 460 + * buf: C string containing whitespace- 461 + * separated unsigned integer values 462 + * representing the number of NFSD 463 + * threads to start in each pool 464 + * size: non-zero length of C string in @buf 465 + * Output: 466 + * On success: passed-in buffer filled with '\n'-terminated C 467 + * string containing integer values representing the 468 + * number of NFSD threads in each pool; 469 + * return code is the size in bytes of the string 470 + * On error: return code is zero or a negative errno value 471 + */ 691 472 static ssize_t write_pool_threads(struct file *file, char *buf, size_t size) 692 473 { 693 474 /* if size > 0, look for an array of number of threads per node ··· 780 517 781 518 static ssize_t __write_versions(struct file *file, char *buf, size_t size) 782 519 { 783 - /* 784 - * Format: 785 - * [-/+]vers [-/+]vers ... 786 - */ 787 520 char *mesg = buf; 788 521 char *vers, sign; 789 522 int len, num; ··· 837 578 return len; 838 579 } 839 580 581 + /** 582 + * write_versions - Set or report the available NFS protocol versions 583 + * 584 + * Input: 585 + * buf: ignored 586 + * size: zero 587 + * Output: 588 + * On success: passed-in buffer filled with '\n'-terminated C 589 + * string containing positive or negative integer 590 + * values representing the current status of each 591 + * protocol version; 592 + * return code is the size in bytes of the string 593 + * On error: return code is zero or a negative errno value 594 + * 595 + * OR 596 + * 597 + * Input: 598 + * buf: C string containing whitespace- 599 + * separated positive or negative 600 + * integer values representing NFS 601 + * protocol versions to enable ("+n") 602 + * or disable ("-n") 603 + * size: non-zero length of C string in @buf 604 + * Output: 605 + * On success: status of zero or more protocol versions has 606 + * been updated; passed-in buffer filled with 607 + * '\n'-terminated C string containing positive 608 + * or negative integer values representing the 609 + * current status of each protocol version; 610 + * return code is the size in bytes of the string 611 + * On error: return code is zero or a negative errno value 612 + */ 840 613 static ssize_t write_versions(struct file *file, char *buf, size_t size) 841 614 { 842 615 ssize_t rv; ··· 978 687 return -EINVAL; 979 688 } 980 689 690 + /** 691 + * write_ports - Pass a socket file descriptor or transport name to listen on 692 + * 693 + * Input: 694 + * buf: ignored 695 + * size: zero 696 + * Output: 697 + * On success: passed-in buffer filled with a '\n'-terminated C 698 + * string containing a whitespace-separated list of 699 + * named NFSD listeners; 700 + * return code is the size in bytes of the string 701 + * On error: return code is zero or a negative errno value 702 + * 703 + * OR 704 + * 705 + * Input: 706 + * buf: C string containing an unsigned 707 + * integer value representing a bound 708 + * but unconnected socket that is to be 709 + * used as an NFSD listener 710 + * size: non-zero length of C string in @buf 711 + * Output: 712 + * On success: NFS service is started; 713 + * passed-in buffer filled with a '\n'-terminated C 714 + * string containing a unique alphanumeric name of 715 + * the listener; 716 + * return code is the size in bytes of the string 717 + * On error: return code is a negative errno value 718 + * 719 + * OR 720 + * 721 + * Input: 722 + * buf: C string containing a "-" followed 723 + * by an integer value representing a 724 + * previously passed in socket file 725 + * descriptor 726 + * size: non-zero length of C string in @buf 727 + * Output: 728 + * On success: NFS service no longer listens on that socket; 729 + * passed-in buffer filled with a '\n'-terminated C 730 + * string containing a unique name of the listener; 731 + * return code is the size in bytes of the string 732 + * On error: return code is a negative errno value 733 + * 734 + * OR 735 + * 736 + * Input: 737 + * buf: C string containing a transport 738 + * name and an unsigned integer value 739 + * representing the port to listen on, 740 + * separated by whitespace 741 + * size: non-zero length of C string in @buf 742 + * Output: 743 + * On success: returns zero; NFS service is started 744 + * On error: return code is a negative errno value 745 + * 746 + * OR 747 + * 748 + * Input: 749 + * buf: C string containing a "-" followed 750 + * by a transport name and an unsigned 751 + * integer value representing the port 752 + * to listen on, separated by whitespace 753 + * size: non-zero length of C string in @buf 754 + * Output: 755 + * On success: returns zero; NFS service no longer listens 756 + * on that transport 757 + * On error: return code is a negative errno value 758 + */ 981 759 static ssize_t write_ports(struct file *file, char *buf, size_t size) 982 760 { 983 761 ssize_t rv; ··· 1060 700 1061 701 int nfsd_max_blksize; 1062 702 703 + /** 704 + * write_maxblksize - Set or report the current NFS blksize 705 + * 706 + * Input: 707 + * buf: ignored 708 + * size: zero 709 + * 710 + * OR 711 + * 712 + * Input: 713 + * buf: C string containing an unsigned 714 + * integer value representing the new 715 + * NFS blksize 716 + * size: non-zero length of C string in @buf 717 + * Output: 718 + * On success: passed-in buffer filled with '\n'-terminated C string 719 + * containing numeric value of the current NFS blksize 720 + * setting; 721 + * return code is the size in bytes of the string 722 + * On error: return code is zero or a negative errno value 723 + */ 1063 724 static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) 1064 725 { 1065 726 char *mesg = buf; ··· 1133 752 return strlen(buf); 1134 753 } 1135 754 755 + /** 756 + * write_leasetime - Set or report the current NFSv4 lease time 757 + * 758 + * Input: 759 + * buf: ignored 760 + * size: zero 761 + * 762 + * OR 763 + * 764 + * Input: 765 + * buf: C string containing an unsigned 766 + * integer value representing the new 767 + * NFSv4 lease expiry time 768 + * size: non-zero length of C string in @buf 769 + * Output: 770 + * On success: passed-in buffer filled with '\n'-terminated C 771 + * string containing unsigned integer value of the 772 + * current lease expiry time; 773 + * return code is the size in bytes of the string 774 + * On error: return code is zero or a negative errno value 775 + */ 1136 776 static ssize_t write_leasetime(struct file *file, char *buf, size_t size) 1137 777 { 1138 778 ssize_t rv; ··· 1190 788 return strlen(buf); 1191 789 } 1192 790 791 + /** 792 + * write_recoverydir - Set or report the pathname of the recovery directory 793 + * 794 + * Input: 795 + * buf: ignored 796 + * size: zero 797 + * 798 + * OR 799 + * 800 + * Input: 801 + * buf: C string containing the pathname 802 + * of the directory on a local file 803 + * system containing permanent NFSv4 804 + * recovery data 805 + * size: non-zero length of C string in @buf 806 + * Output: 807 + * On success: passed-in buffer filled with '\n'-terminated C string 808 + * containing the current recovery pathname setting; 809 + * return code is the size in bytes of the string 810 + * On error: return code is zero or a negative errno value 811 + */ 1193 812 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) 1194 813 { 1195 814 ssize_t rv;
+27 -9
fs/nfsd/nfsfh.c
··· 258 258 return error; 259 259 } 260 260 261 - /* 262 - * Perform sanity checks on the dentry in a client's file handle. 261 + /** 262 + * fh_verify - filehandle lookup and access checking 263 + * @rqstp: pointer to current rpc request 264 + * @fhp: filehandle to be verified 265 + * @type: expected type of object pointed to by filehandle 266 + * @access: type of access needed to object 263 267 * 264 - * Note that the file handle dentry may need to be freed even after 265 - * an error return. 268 + * Look up a dentry from the on-the-wire filehandle, check the client's 269 + * access to the export, and set the current task's credentials. 266 270 * 267 - * This is only called at the start of an nfsproc call, so fhp points to 268 - * a svc_fh which is all 0 except for the over-the-wire file handle. 271 + * Regardless of success or failure of fh_verify(), fh_put() should be 272 + * called on @fhp when the caller is finished with the filehandle. 273 + * 274 + * fh_verify() may be called multiple times on a given filehandle, for 275 + * example, when processing an NFSv4 compound. The first call will look 276 + * up a dentry using the on-the-wire filehandle. Subsequent calls will 277 + * skip the lookup and just perform the other checks and possibly change 278 + * the current task's credentials. 279 + * 280 + * @type specifies the type of object expected using one of the S_IF* 281 + * constants defined in include/linux/stat.h. The caller may use zero 282 + * to indicate that it doesn't care, or a negative integer to indicate 283 + * that it expects something not of the given type. 284 + * 285 + * @access is formed from the NFSD_MAY_* constants defined in 286 + * include/linux/nfsd/nfsd.h. 269 287 */ 270 288 __be32 271 289 fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ··· 484 466 goto retry; 485 467 break; 486 468 } 469 + } else if (exp->ex_flags & NFSEXP_FSID) { 470 + fsid_type = FSID_NUM; 487 471 } else if (exp->ex_uuid) { 488 472 if (fhp->fh_maxsize >= 64) { 489 473 if (root_export) ··· 498 478 else 499 479 fsid_type = FSID_UUID4_INUM; 500 480 } 501 - } else if (exp->ex_flags & NFSEXP_FSID) 502 - fsid_type = FSID_NUM; 503 - else if (!old_valid_dev(ex_dev)) 481 + } else if (!old_valid_dev(ex_dev)) 504 482 /* for newer device numbers, we must use a newer fsid format */ 505 483 fsid_type = FSID_ENCODE_DEV; 506 484 else
+1
fs/nfsd/nfsproc.c
··· 622 622 { nfserr_badname, -ESRCH }, 623 623 { nfserr_io, -ETXTBSY }, 624 624 { nfserr_notsupp, -EOPNOTSUPP }, 625 + { nfserr_toosmall, -ETOOSMALL }, 625 626 }; 626 627 int i; 627 628
+31 -3
fs/nfsd/vfs.c
··· 744 744 fput(filp); 745 745 } 746 746 747 + /* 748 + * Sync a file 749 + * As this calls fsync (not fdatasync) there is no need for a write_inode 750 + * after it. 751 + */ 752 + static inline int nfsd_dosync(struct file *filp, struct dentry *dp, 753 + const struct file_operations *fop) 754 + { 755 + struct inode *inode = dp->d_inode; 756 + int (*fsync) (struct file *, struct dentry *, int); 757 + int err; 758 + 759 + err = filemap_fdatawrite(inode->i_mapping); 760 + if (err == 0 && fop && (fsync = fop->fsync)) 761 + err = fsync(filp, dp, 0); 762 + if (err == 0) 763 + err = filemap_fdatawait(inode->i_mapping); 764 + 765 + return err; 766 + } 767 + 747 768 static int 748 769 nfsd_sync(struct file *filp) 749 770 { 750 - return vfs_fsync(filp, filp->f_path.dentry, 0); 771 + int err; 772 + struct inode *inode = filp->f_path.dentry->d_inode; 773 + dprintk("nfsd: sync file %s\n", filp->f_path.dentry->d_name.name); 774 + mutex_lock(&inode->i_mutex); 775 + err=nfsd_dosync(filp, filp->f_path.dentry, filp->f_op); 776 + mutex_unlock(&inode->i_mutex); 777 + 778 + return err; 751 779 } 752 780 753 781 int 754 - nfsd_sync_dir(struct dentry *dentry) 782 + nfsd_sync_dir(struct dentry *dp) 755 783 { 756 - return vfs_fsync(NULL, dentry, 0); 784 + return nfsd_dosync(NULL, dp, dp->d_inode->i_fop); 757 785 } 758 786 759 787 /*
+43 -25
include/linux/lockd/lockd.h
··· 43 43 struct sockaddr_storage h_addr; /* peer address */ 44 44 size_t h_addrlen; 45 45 struct sockaddr_storage h_srcaddr; /* our address (optional) */ 46 - struct rpc_clnt * h_rpcclnt; /* RPC client to talk to peer */ 47 - char * h_name; /* remote hostname */ 46 + struct rpc_clnt *h_rpcclnt; /* RPC client to talk to peer */ 47 + char *h_name; /* remote hostname */ 48 48 u32 h_version; /* interface version */ 49 49 unsigned short h_proto; /* transport proto */ 50 50 unsigned short h_reclaiming : 1, ··· 64 64 spinlock_t h_lock; 65 65 struct list_head h_granted; /* Locks in GRANTED state */ 66 66 struct list_head h_reclaim; /* Locks in RECLAIM state */ 67 - struct nsm_handle * h_nsmhandle; /* NSM status handle */ 68 - 69 - char h_addrbuf[48], /* address eyecatchers */ 70 - h_srcaddrbuf[48]; 67 + struct nsm_handle *h_nsmhandle; /* NSM status handle */ 68 + char *h_addrbuf; /* address eyecatcher */ 71 69 }; 70 + 71 + /* 72 + * The largest string sm_addrbuf should hold is a full-size IPv6 address 73 + * (no "::" anywhere) with a scope ID. The buffer size is computed to 74 + * hold eight groups of colon-separated four-hex-digit numbers, a 75 + * percent sign, a scope id (at most 32 bits, in decimal), and NUL. 76 + */ 77 + #define NSM_ADDRBUF ((8 * 4 + 7) + (1 + 10) + 1) 72 78 73 79 struct nsm_handle { 74 80 struct list_head sm_link; 75 81 atomic_t sm_count; 76 - char * sm_name; 82 + char *sm_mon_name; 83 + char *sm_name; 77 84 struct sockaddr_storage sm_addr; 78 85 size_t sm_addrlen; 79 86 unsigned int sm_monitored : 1, 80 87 sm_sticky : 1; /* don't unmonitor */ 81 - char sm_addrbuf[48]; /* address eyecatcher */ 88 + struct nsm_private sm_priv; 89 + char sm_addrbuf[NSM_ADDRBUF]; 82 90 }; 83 91 84 92 /* ··· 110 102 static inline struct sockaddr *nlm_srcaddr(const struct nlm_host *host) 111 103 { 112 104 return (struct sockaddr *)&host->h_srcaddr; 113 - } 114 - 115 - static inline struct sockaddr_in *nsm_addr_in(const struct nsm_handle *handle) 116 - { 117 - return (struct sockaddr_in *)&handle->sm_addr; 118 - } 119 - 120 - static inline struct sockaddr *nsm_addr(const struct nsm_handle *handle) 121 - { 122 - return (struct sockaddr *)&handle->sm_addr; 123 105 } 124 106 125 107 /* ··· 195 197 extern int nlmsvc_grace_period; 196 198 extern unsigned long nlmsvc_timeout; 197 199 extern int nsm_use_hostnames; 200 + extern int nsm_local_state; 198 201 199 202 /* 200 203 * Lockd client functions ··· 230 231 struct nlm_host * nlm_get_host(struct nlm_host *); 231 232 void nlm_release_host(struct nlm_host *); 232 233 void nlm_shutdown_hosts(void); 233 - extern void nlm_host_rebooted(const struct sockaddr_in *, const char *, 234 - unsigned int, u32); 235 - void nsm_release(struct nsm_handle *); 234 + void nlm_host_rebooted(const struct nlm_reboot *); 236 235 236 + /* 237 + * Host monitoring 238 + */ 239 + int nsm_monitor(const struct nlm_host *host); 240 + void nsm_unmonitor(const struct nlm_host *host); 241 + 242 + struct nsm_handle *nsm_get_handle(const struct sockaddr *sap, 243 + const size_t salen, 244 + const char *hostname, 245 + const size_t hostname_len); 246 + struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info); 247 + void nsm_release(struct nsm_handle *nsm); 237 248 238 249 /* 239 250 * This is used in garbage collection and resource reclaim ··· 291 282 static inline int __nlm_privileged_request4(const struct sockaddr *sap) 292 283 { 293 284 const struct sockaddr_in *sin = (struct sockaddr_in *)sap; 294 - return (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) && 295 - (ntohs(sin->sin_port) < 1024); 285 + 286 + if (ntohs(sin->sin_port) > 1023) 287 + return 0; 288 + 289 + return ipv4_is_loopback(sin->sin_addr.s_addr); 296 290 } 297 291 298 292 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 299 293 static inline int __nlm_privileged_request6(const struct sockaddr *sap) 300 294 { 301 295 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; 302 - return (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LOOPBACK) && 303 - (ntohs(sin6->sin6_port) < 1024); 296 + 297 + if (ntohs(sin6->sin6_port) > 1023) 298 + return 0; 299 + 300 + if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) 301 + return ipv4_is_loopback(sin6->sin6_addr.s6_addr32[3]); 302 + 303 + return ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LOOPBACK; 304 304 } 305 305 #else /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ 306 306 static inline int __nlm_privileged_request6(const struct sockaddr *sap)
-48
include/linux/lockd/sm_inter.h
··· 1 - /* 2 - * linux/include/linux/lockd/sm_inter.h 3 - * 4 - * Declarations for the kernel statd client. 5 - * 6 - * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> 7 - */ 8 - 9 - #ifndef LINUX_LOCKD_SM_INTER_H 10 - #define LINUX_LOCKD_SM_INTER_H 11 - 12 - #define SM_PROGRAM 100024 13 - #define SM_VERSION 1 14 - #define SM_STAT 1 15 - #define SM_MON 2 16 - #define SM_UNMON 3 17 - #define SM_UNMON_ALL 4 18 - #define SM_SIMU_CRASH 5 19 - #define SM_NOTIFY 6 20 - 21 - #define SM_MAXSTRLEN 1024 22 - #define SM_PRIV_SIZE 16 23 - 24 - /* 25 - * Arguments for all calls to statd 26 - */ 27 - struct nsm_args { 28 - __be32 addr; /* remote address */ 29 - u32 prog; /* RPC callback info */ 30 - u32 vers; 31 - u32 proc; 32 - 33 - char * mon_name; 34 - }; 35 - 36 - /* 37 - * Result returned by statd 38 - */ 39 - struct nsm_res { 40 - u32 status; 41 - u32 state; 42 - }; 43 - 44 - int nsm_monitor(struct nlm_host *); 45 - int nsm_unmonitor(struct nlm_host *); 46 - extern int nsm_local_state; 47 - 48 - #endif /* LINUX_LOCKD_SM_INTER_H */
+11 -4
include/linux/lockd/xdr.h
··· 13 13 #include <linux/nfs.h> 14 14 #include <linux/sunrpc/xdr.h> 15 15 16 + #define SM_MAXSTRLEN 1024 17 + #define SM_PRIV_SIZE 16 18 + 19 + struct nsm_private { 20 + unsigned char data[SM_PRIV_SIZE]; 21 + }; 22 + 16 23 struct svc_rqst; 17 24 18 25 #define NLM_MAXCOOKIELEN 32 ··· 84 77 * statd callback when client has rebooted 85 78 */ 86 79 struct nlm_reboot { 87 - char * mon; 88 - unsigned int len; 89 - u32 state; 90 - __be32 addr; 80 + char *mon; 81 + unsigned int len; 82 + u32 state; 83 + struct nsm_private priv; 91 84 }; 92 85 93 86 /*
+2
include/linux/nfs4.h
··· 88 88 #define NFS4_ACE_GENERIC_EXECUTE 0x001200A0 89 89 #define NFS4_ACE_MASK_ALL 0x001F01FF 90 90 91 + #define NFS4_MAX_UINT64 (~(u64)0) 92 + 91 93 enum nfs4_acl_whotype { 92 94 NFS4_ACL_WHO_NAMED = 0, 93 95 NFS4_ACL_WHO_OWNER,
-1
include/linux/nfsd/nfsd.h
··· 23 23 /* 24 24 * nfsd version 25 25 */ 26 - #define NFSD_VERSION "0.5" 27 26 #define NFSD_SUPPORTED_MINOR_VERSION 0 28 27 29 28 /*
+4
include/linux/nfsd/nfsfh.h
··· 68 68 * 1 - 4 byte user specified identifier 69 69 * 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED 70 70 * 3 - 4 byte device id, encoded for user-space, 4 byte inode number 71 + * 4 - 4 byte inode number and 4 byte uuid 72 + * 5 - 8 byte uuid 73 + * 6 - 16 byte uuid 74 + * 7 - 8 byte inode number and 16 byte uuid 71 75 * 72 76 * The fileid_type identified how the file within the filesystem is encoded. 73 77 * This is (will be) passed to, and set by, the underlying filesystem if it supports
+4 -1
include/linux/sunrpc/svc.h
··· 58 58 struct svc_stat * sv_stats; /* RPC statistics */ 59 59 spinlock_t sv_lock; 60 60 unsigned int sv_nrthreads; /* # of server threads */ 61 + unsigned int sv_maxconn; /* max connections allowed or 62 + * '0' causing max to be based 63 + * on number of threads. */ 64 + 61 65 unsigned int sv_max_payload; /* datagram payload size */ 62 66 unsigned int sv_max_mesg; /* max_payload + 1 page for overheads */ 63 67 unsigned int sv_xdrsize; /* XDR buffer size */ 64 - 65 68 struct list_head sv_permsocks; /* all permanent sockets */ 66 69 struct list_head sv_tempsocks; /* all temporary sockets */ 67 70 int sv_tmpcnt; /* count of temporary sockets */
+10 -10
net/sunrpc/cache.c
··· 98 98 99 99 return new; 100 100 } 101 - EXPORT_SYMBOL(sunrpc_cache_lookup); 101 + EXPORT_SYMBOL_GPL(sunrpc_cache_lookup); 102 102 103 103 104 104 static void queue_loose(struct cache_detail *detail, struct cache_head *ch); ··· 173 173 cache_put(old, detail); 174 174 return tmp; 175 175 } 176 - EXPORT_SYMBOL(sunrpc_cache_update); 176 + EXPORT_SYMBOL_GPL(sunrpc_cache_update); 177 177 178 178 static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h); 179 179 /* ··· 245 245 cache_put(h, detail); 246 246 return rv; 247 247 } 248 - EXPORT_SYMBOL(cache_check); 248 + EXPORT_SYMBOL_GPL(cache_check); 249 249 250 250 /* 251 251 * caches need to be periodically cleaned. ··· 373 373 schedule_delayed_work(&cache_cleaner, 0); 374 374 return 0; 375 375 } 376 - EXPORT_SYMBOL(cache_register); 376 + EXPORT_SYMBOL_GPL(cache_register); 377 377 378 378 void cache_unregister(struct cache_detail *cd) 379 379 { ··· 399 399 out: 400 400 printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); 401 401 } 402 - EXPORT_SYMBOL(cache_unregister); 402 + EXPORT_SYMBOL_GPL(cache_unregister); 403 403 404 404 /* clean cache tries to find something to clean 405 405 * and cleans it. ··· 514 514 while (cache_clean() != -1) 515 515 cond_resched(); 516 516 } 517 - EXPORT_SYMBOL(cache_flush); 517 + EXPORT_SYMBOL_GPL(cache_flush); 518 518 519 519 void cache_purge(struct cache_detail *detail) 520 520 { ··· 523 523 cache_flush(); 524 524 detail->flush_time = 1; 525 525 } 526 - EXPORT_SYMBOL(cache_purge); 526 + EXPORT_SYMBOL_GPL(cache_purge); 527 527 528 528 529 529 /* ··· 988 988 *bpp = bp; 989 989 *lp = len; 990 990 } 991 - EXPORT_SYMBOL(qword_add); 991 + EXPORT_SYMBOL_GPL(qword_add); 992 992 993 993 void qword_addhex(char **bpp, int *lp, char *buf, int blen) 994 994 { ··· 1017 1017 *bpp = bp; 1018 1018 *lp = len; 1019 1019 } 1020 - EXPORT_SYMBOL(qword_addhex); 1020 + EXPORT_SYMBOL_GPL(qword_addhex); 1021 1021 1022 1022 static void warn_no_listener(struct cache_detail *detail) 1023 1023 { ··· 1140 1140 *dest = '\0'; 1141 1141 return len; 1142 1142 } 1143 - EXPORT_SYMBOL(qword_get); 1143 + EXPORT_SYMBOL_GPL(qword_get); 1144 1144 1145 1145 1146 1146 /*
+3 -3
net/sunrpc/stats.c
··· 106 106 seq_putc(seq, '\n'); 107 107 } 108 108 } 109 - EXPORT_SYMBOL(svc_seq_show); 109 + EXPORT_SYMBOL_GPL(svc_seq_show); 110 110 111 111 /** 112 112 * rpc_alloc_iostats - allocate an rpc_iostats structure ··· 249 249 { 250 250 return do_register(statp->program->pg_name, statp, fops); 251 251 } 252 - EXPORT_SYMBOL(svc_proc_register); 252 + EXPORT_SYMBOL_GPL(svc_proc_register); 253 253 254 254 void 255 255 svc_proc_unregister(const char *name) 256 256 { 257 257 remove_proc_entry(name, proc_net_rpc); 258 258 } 259 - EXPORT_SYMBOL(svc_proc_unregister); 259 + EXPORT_SYMBOL_GPL(svc_proc_unregister); 260 260 261 261 void 262 262 rpc_proc_init(void)
+7 -7
net/sunrpc/svc.c
··· 431 431 { 432 432 return __svc_create(prog, bufsize, /*npools*/1, family, shutdown); 433 433 } 434 - EXPORT_SYMBOL(svc_create); 434 + EXPORT_SYMBOL_GPL(svc_create); 435 435 436 436 struct svc_serv * 437 437 svc_create_pooled(struct svc_program *prog, unsigned int bufsize, ··· 450 450 451 451 return serv; 452 452 } 453 - EXPORT_SYMBOL(svc_create_pooled); 453 + EXPORT_SYMBOL_GPL(svc_create_pooled); 454 454 455 455 /* 456 456 * Destroy an RPC service. Should be called with appropriate locking to ··· 492 492 kfree(serv->sv_pools); 493 493 kfree(serv); 494 494 } 495 - EXPORT_SYMBOL(svc_destroy); 495 + EXPORT_SYMBOL_GPL(svc_destroy); 496 496 497 497 /* 498 498 * Allocate an RPC server's buffer space. ··· 567 567 out_enomem: 568 568 return ERR_PTR(-ENOMEM); 569 569 } 570 - EXPORT_SYMBOL(svc_prepare_thread); 570 + EXPORT_SYMBOL_GPL(svc_prepare_thread); 571 571 572 572 /* 573 573 * Choose a pool in which to create a new thread, for svc_set_num_threads ··· 689 689 690 690 return error; 691 691 } 692 - EXPORT_SYMBOL(svc_set_num_threads); 692 + EXPORT_SYMBOL_GPL(svc_set_num_threads); 693 693 694 694 /* 695 695 * Called from a server thread as it's exiting. Caller must hold the BKL or ··· 717 717 if (serv) 718 718 svc_destroy(serv); 719 719 } 720 - EXPORT_SYMBOL(svc_exit_thread); 720 + EXPORT_SYMBOL_GPL(svc_exit_thread); 721 721 722 722 #ifdef CONFIG_SUNRPC_REGISTER_V4 723 723 ··· 1231 1231 svc_putnl(resv, ntohl(rpc_stat)); 1232 1232 goto sendit; 1233 1233 } 1234 - EXPORT_SYMBOL(svc_process); 1234 + EXPORT_SYMBOL_GPL(svc_process); 1235 1235 1236 1236 /* 1237 1237 * Return (transport-specific) limit on the rpc payload.
+41 -17
net/sunrpc/svc_xprt.c
··· 440 440 svc_xprt_enqueue(xprt); 441 441 } 442 442 } 443 - EXPORT_SYMBOL(svc_reserve); 443 + EXPORT_SYMBOL_GPL(svc_reserve); 444 444 445 445 static void svc_xprt_release(struct svc_rqst *rqstp) 446 446 { 447 447 struct svc_xprt *xprt = rqstp->rq_xprt; 448 448 449 449 rqstp->rq_xprt->xpt_ops->xpo_release_rqst(rqstp); 450 + 451 + kfree(rqstp->rq_deferred); 452 + rqstp->rq_deferred = NULL; 450 453 451 454 svc_free_res_pages(rqstp); 452 455 rqstp->rq_res.page_len = 0; ··· 501 498 spin_unlock_bh(&pool->sp_lock); 502 499 } 503 500 } 504 - EXPORT_SYMBOL(svc_wake_up); 501 + EXPORT_SYMBOL_GPL(svc_wake_up); 505 502 506 503 int svc_port_is_privileged(struct sockaddr *sin) 507 504 { ··· 518 515 } 519 516 520 517 /* 521 - * Make sure that we don't have too many active connections. If we 522 - * have, something must be dropped. 518 + * Make sure that we don't have too many active connections. If we have, 519 + * something must be dropped. It's not clear what will happen if we allow 520 + * "too many" connections, but when dealing with network-facing software, 521 + * we have to code defensively. Here we do that by imposing hard limits. 523 522 * 524 523 * There's no point in trying to do random drop here for DoS 525 524 * prevention. The NFS clients does 1 reconnect in 15 seconds. An ··· 530 525 * The only somewhat efficient mechanism would be if drop old 531 526 * connections from the same IP first. But right now we don't even 532 527 * record the client IP in svc_sock. 528 + * 529 + * single-threaded services that expect a lot of clients will probably 530 + * need to set sv_maxconn to override the default value which is based 531 + * on the number of threads 533 532 */ 534 533 static void svc_check_conn_limits(struct svc_serv *serv) 535 534 { 536 - if (serv->sv_tmpcnt > (serv->sv_nrthreads+3)*20) { 535 + unsigned int limit = serv->sv_maxconn ? serv->sv_maxconn : 536 + (serv->sv_nrthreads+3) * 20; 537 + 538 + if (serv->sv_tmpcnt > limit) { 537 539 struct svc_xprt *xprt = NULL; 538 540 spin_lock_bh(&serv->sv_lock); 539 541 if (!list_empty(&serv->sv_tempsocks)) { 540 542 if (net_ratelimit()) { 541 543 /* Try to help the admin */ 542 544 printk(KERN_NOTICE "%s: too many open " 543 - "connections, consider increasing the " 544 - "number of nfsd threads\n", 545 - serv->sv_name); 545 + "connections, consider increasing %s\n", 546 + serv->sv_name, serv->sv_maxconn ? 547 + "the max number of connections." : 548 + "the number of threads."); 546 549 } 547 550 /* 548 551 * Always select the oldest connection. It's not fair, ··· 743 730 serv->sv_stats->netcnt++; 744 731 return len; 745 732 } 746 - EXPORT_SYMBOL(svc_recv); 733 + EXPORT_SYMBOL_GPL(svc_recv); 747 734 748 735 /* 749 736 * Drop request ··· 753 740 dprintk("svc: xprt %p dropped request\n", rqstp->rq_xprt); 754 741 svc_xprt_release(rqstp); 755 742 } 756 - EXPORT_SYMBOL(svc_drop); 743 + EXPORT_SYMBOL_GPL(svc_drop); 757 744 758 745 /* 759 746 * Return reply to client. ··· 850 837 void svc_delete_xprt(struct svc_xprt *xprt) 851 838 { 852 839 struct svc_serv *serv = xprt->xpt_server; 840 + struct svc_deferred_req *dr; 841 + 842 + /* Only do this once */ 843 + if (test_and_set_bit(XPT_DEAD, &xprt->xpt_flags)) 844 + return; 853 845 854 846 dprintk("svc: svc_delete_xprt(%p)\n", xprt); 855 847 xprt->xpt_ops->xpo_detach(xprt); ··· 869 851 * while still attached to a queue, the queue itself 870 852 * is about to be destroyed (in svc_destroy). 871 853 */ 872 - if (!test_and_set_bit(XPT_DEAD, &xprt->xpt_flags)) { 873 - BUG_ON(atomic_read(&xprt->xpt_ref.refcount) < 2); 874 - if (test_bit(XPT_TEMP, &xprt->xpt_flags)) 875 - serv->sv_tmpcnt--; 854 + if (test_bit(XPT_TEMP, &xprt->xpt_flags)) 855 + serv->sv_tmpcnt--; 856 + 857 + for (dr = svc_deferred_dequeue(xprt); dr; 858 + dr = svc_deferred_dequeue(xprt)) { 876 859 svc_xprt_put(xprt); 860 + kfree(dr); 877 861 } 862 + 863 + svc_xprt_put(xprt); 878 864 spin_unlock_bh(&serv->sv_lock); 879 865 } 880 866 ··· 924 902 container_of(dreq, struct svc_deferred_req, handle); 925 903 struct svc_xprt *xprt = dr->xprt; 926 904 927 - if (too_many) { 905 + spin_lock(&xprt->xpt_lock); 906 + set_bit(XPT_DEFERRED, &xprt->xpt_flags); 907 + if (too_many || test_bit(XPT_DEAD, &xprt->xpt_flags)) { 908 + spin_unlock(&xprt->xpt_lock); 909 + dprintk("revisit canceled\n"); 928 910 svc_xprt_put(xprt); 929 911 kfree(dr); 930 912 return; 931 913 } 932 914 dprintk("revisit queued\n"); 933 915 dr->xprt = NULL; 934 - spin_lock(&xprt->xpt_lock); 935 916 list_add(&dr->handle.recent, &xprt->xpt_deferred); 936 917 spin_unlock(&xprt->xpt_lock); 937 - set_bit(XPT_DEFERRED, &xprt->xpt_flags); 938 918 svc_xprt_enqueue(xprt); 939 919 svc_xprt_put(xprt); 940 920 }
+7 -7
net/sunrpc/svcauth.c
··· 57 57 rqstp->rq_authop = aops; 58 58 return aops->accept(rqstp, authp); 59 59 } 60 - EXPORT_SYMBOL(svc_authenticate); 60 + EXPORT_SYMBOL_GPL(svc_authenticate); 61 61 62 62 int svc_set_client(struct svc_rqst *rqstp) 63 63 { 64 64 return rqstp->rq_authop->set_client(rqstp); 65 65 } 66 - EXPORT_SYMBOL(svc_set_client); 66 + EXPORT_SYMBOL_GPL(svc_set_client); 67 67 68 68 /* A request, which was authenticated, has now executed. 69 69 * Time to finalise the credentials and verifier ··· 95 95 spin_unlock(&authtab_lock); 96 96 return rv; 97 97 } 98 - EXPORT_SYMBOL(svc_auth_register); 98 + EXPORT_SYMBOL_GPL(svc_auth_register); 99 99 100 100 void 101 101 svc_auth_unregister(rpc_authflavor_t flavor) ··· 105 105 authtab[flavor] = NULL; 106 106 spin_unlock(&authtab_lock); 107 107 } 108 - EXPORT_SYMBOL(svc_auth_unregister); 108 + EXPORT_SYMBOL_GPL(svc_auth_unregister); 109 109 110 110 /************************************************** 111 111 * 'auth_domains' are stored in a hash table indexed by name. ··· 132 132 spin_unlock(&auth_domain_lock); 133 133 } 134 134 } 135 - EXPORT_SYMBOL(auth_domain_put); 135 + EXPORT_SYMBOL_GPL(auth_domain_put); 136 136 137 137 struct auth_domain * 138 138 auth_domain_lookup(char *name, struct auth_domain *new) ··· 157 157 spin_unlock(&auth_domain_lock); 158 158 return new; 159 159 } 160 - EXPORT_SYMBOL(auth_domain_lookup); 160 + EXPORT_SYMBOL_GPL(auth_domain_lookup); 161 161 162 162 struct auth_domain *auth_domain_find(char *name) 163 163 { 164 164 return auth_domain_lookup(name, NULL); 165 165 } 166 - EXPORT_SYMBOL(auth_domain_find); 166 + EXPORT_SYMBOL_GPL(auth_domain_find);
+6 -6
net/sunrpc/svcauth_unix.c
··· 64 64 rv = auth_domain_lookup(name, &new->h); 65 65 } 66 66 } 67 - EXPORT_SYMBOL(unix_domain_find); 67 + EXPORT_SYMBOL_GPL(unix_domain_find); 68 68 69 69 static void svcauth_unix_domain_release(struct auth_domain *dom) 70 70 { ··· 358 358 else 359 359 return -ENOMEM; 360 360 } 361 - EXPORT_SYMBOL(auth_unix_add_addr); 361 + EXPORT_SYMBOL_GPL(auth_unix_add_addr); 362 362 363 363 int auth_unix_forget_old(struct auth_domain *dom) 364 364 { ··· 370 370 udom->addr_changes++; 371 371 return 0; 372 372 } 373 - EXPORT_SYMBOL(auth_unix_forget_old); 373 + EXPORT_SYMBOL_GPL(auth_unix_forget_old); 374 374 375 375 struct auth_domain *auth_unix_lookup(struct in6_addr *addr) 376 376 { ··· 395 395 cache_put(&ipm->h, &ip_map_cache); 396 396 return rv; 397 397 } 398 - EXPORT_SYMBOL(auth_unix_lookup); 398 + EXPORT_SYMBOL_GPL(auth_unix_lookup); 399 399 400 400 void svcauth_unix_purge(void) 401 401 { 402 402 cache_purge(&ip_map_cache); 403 403 } 404 - EXPORT_SYMBOL(svcauth_unix_purge); 404 + EXPORT_SYMBOL_GPL(svcauth_unix_purge); 405 405 406 406 static inline struct ip_map * 407 407 ip_map_cached_get(struct svc_rqst *rqstp) ··· 714 714 return SVC_OK; 715 715 } 716 716 717 - EXPORT_SYMBOL(svcauth_unix_set_client); 717 + EXPORT_SYMBOL_GPL(svcauth_unix_set_client); 718 718 719 719 static int 720 720 svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
+22 -8
net/sunrpc/svcsock.c
··· 59 59 static int svc_udp_recvfrom(struct svc_rqst *); 60 60 static int svc_udp_sendto(struct svc_rqst *); 61 61 static void svc_sock_detach(struct svc_xprt *); 62 + static void svc_tcp_sock_detach(struct svc_xprt *); 62 63 static void svc_sock_free(struct svc_xprt *); 63 64 64 65 static struct svc_xprt *svc_create_socket(struct svc_serv *, int, ··· 103 102 static void svc_release_skb(struct svc_rqst *rqstp) 104 103 { 105 104 struct sk_buff *skb = rqstp->rq_xprt_ctxt; 106 - struct svc_deferred_req *dr = rqstp->rq_deferred; 107 105 108 106 if (skb) { 109 107 struct svc_sock *svsk = ··· 111 111 112 112 dprintk("svc: service %p, releasing skb %p\n", rqstp, skb); 113 113 skb_free_datagram(svsk->sk_sk, skb); 114 - } 115 - if (dr) { 116 - rqstp->rq_deferred = NULL; 117 - kfree(dr); 118 114 } 119 115 } 120 116 ··· 285 289 return -ENOENT; 286 290 return len; 287 291 } 288 - EXPORT_SYMBOL(svc_sock_names); 292 + EXPORT_SYMBOL_GPL(svc_sock_names); 289 293 290 294 /* 291 295 * Check input queue length ··· 1013 1017 .xpo_recvfrom = svc_tcp_recvfrom, 1014 1018 .xpo_sendto = svc_tcp_sendto, 1015 1019 .xpo_release_rqst = svc_release_skb, 1016 - .xpo_detach = svc_sock_detach, 1020 + .xpo_detach = svc_tcp_sock_detach, 1017 1021 .xpo_free = svc_sock_free, 1018 1022 .xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr, 1019 1023 .xpo_has_wspace = svc_tcp_has_wspace, ··· 1097 1101 } 1098 1102 spin_unlock_bh(&serv->sv_lock); 1099 1103 } 1100 - EXPORT_SYMBOL(svc_sock_update_bufs); 1104 + EXPORT_SYMBOL_GPL(svc_sock_update_bufs); 1101 1105 1102 1106 /* 1103 1107 * Initialize socket for RPC use and create svc_sock struct ··· 1283 1287 sk->sk_state_change = svsk->sk_ostate; 1284 1288 sk->sk_data_ready = svsk->sk_odata; 1285 1289 sk->sk_write_space = svsk->sk_owspace; 1290 + 1291 + if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) 1292 + wake_up_interruptible(sk->sk_sleep); 1293 + } 1294 + 1295 + /* 1296 + * Disconnect the socket, and reset the callbacks 1297 + */ 1298 + static void svc_tcp_sock_detach(struct svc_xprt *xprt) 1299 + { 1300 + struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); 1301 + 1302 + dprintk("svc: svc_tcp_sock_detach(%p)\n", svsk); 1303 + 1304 + svc_sock_detach(xprt); 1305 + 1306 + if (!test_bit(XPT_LISTENER, &xprt->xpt_flags)) 1307 + kernel_sock_shutdown(svsk->sk_sock, SHUT_RDWR); 1286 1308 } 1287 1309 1288 1310 /*