diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/Kconfig | 2 | ||||
| -rw-r--r-- | fs/lockd/host.c | 26 | ||||
| -rw-r--r-- | fs/lockd/svc.c | 39 | ||||
| -rw-r--r-- | fs/lockd/svc4proc.c | 20 | ||||
| -rw-r--r-- | fs/lockd/svclock.c | 20 | ||||
| -rw-r--r-- | fs/lockd/svcproc.c | 22 | ||||
| -rw-r--r-- | fs/lockd/svcsubs.c | 2 | ||||
| -rw-r--r-- | fs/nfs/callback.c | 4 | ||||
| -rw-r--r-- | fs/nfsd/auth.h | 22 | ||||
| -rw-r--r-- | fs/nfsd/export.c | 20 | ||||
| -rw-r--r-- | fs/nfsd/nfs2acl.c | 7 | ||||
| -rw-r--r-- | fs/nfsd/nfs3xdr.c | 21 | ||||
| -rw-r--r-- | fs/nfsd/nfs4callback.c | 92 | ||||
| -rw-r--r-- | fs/nfsd/nfs4idmap.c | 28 | ||||
| -rw-r--r-- | fs/nfsd/nfs4proc.c | 2 | ||||
| -rw-r--r-- | fs/nfsd/nfs4state.c | 257 | ||||
| -rw-r--r-- | fs/nfsd/nfs4xdr.c | 36 | ||||
| -rw-r--r-- | fs/nfsd/nfscache.c | 28 | ||||
| -rw-r--r-- | fs/nfsd/nfsctl.c | 124 | ||||
| -rw-r--r-- | fs/nfsd/nfsfh.c | 1 | ||||
| -rw-r--r-- | fs/nfsd/nfssvc.c | 8 | ||||
| -rw-r--r-- | fs/nfsd/nfsxdr.c | 9 | ||||
| -rw-r--r-- | fs/nfsd/vfs.c | 51 |
23 files changed, 466 insertions, 375 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index 219ec06a8c7e..987b5d7cb21a 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
| @@ -1674,6 +1674,8 @@ config NFSD | |||
| 1674 | select CRYPTO_MD5 if NFSD_V4 | 1674 | select CRYPTO_MD5 if NFSD_V4 |
| 1675 | select CRYPTO if NFSD_V4 | 1675 | select CRYPTO if NFSD_V4 |
| 1676 | select FS_POSIX_ACL if NFSD_V4 | 1676 | select FS_POSIX_ACL if NFSD_V4 |
| 1677 | select PROC_FS if NFSD_V4 | ||
| 1678 | select PROC_FS if SUNRPC_GSS | ||
| 1677 | help | 1679 | help |
| 1678 | If you want your Linux box to act as an NFS *server*, so that other | 1680 | If you want your Linux box to act as an NFS *server*, so that other |
| 1679 | computers on your local network which support NFS can access certain | 1681 | computers on your local network which support NFS can access certain |
diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 572601e98dcd..ca6b16fc3101 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c | |||
| @@ -34,10 +34,10 @@ static DEFINE_MUTEX(nlm_host_mutex); | |||
| 34 | 34 | ||
| 35 | static void nlm_gc_hosts(void); | 35 | static void nlm_gc_hosts(void); |
| 36 | static struct nsm_handle * __nsm_find(const struct sockaddr_in *, | 36 | static struct nsm_handle * __nsm_find(const struct sockaddr_in *, |
| 37 | const char *, int, int); | 37 | const char *, unsigned int, int); |
| 38 | static struct nsm_handle * nsm_find(const struct sockaddr_in *sin, | 38 | static struct nsm_handle * nsm_find(const struct sockaddr_in *sin, |
| 39 | const char *hostname, | 39 | const char *hostname, |
| 40 | int hostname_len); | 40 | unsigned int hostname_len); |
| 41 | 41 | ||
| 42 | /* | 42 | /* |
| 43 | * Common host lookup routine for server & client | 43 | * Common host lookup routine for server & client |
| @@ -45,7 +45,8 @@ static struct nsm_handle * nsm_find(const struct sockaddr_in *sin, | |||
| 45 | static struct nlm_host * | 45 | static struct nlm_host * |
| 46 | nlm_lookup_host(int server, const struct sockaddr_in *sin, | 46 | nlm_lookup_host(int server, const struct sockaddr_in *sin, |
| 47 | int proto, int version, const char *hostname, | 47 | int proto, int version, const char *hostname, |
| 48 | int hostname_len, const struct sockaddr_in *ssin) | 48 | unsigned int hostname_len, |
| 49 | const struct sockaddr_in *ssin) | ||
| 49 | { | 50 | { |
| 50 | struct hlist_head *chain; | 51 | struct hlist_head *chain; |
| 51 | struct hlist_node *pos; | 52 | struct hlist_node *pos; |
| @@ -176,7 +177,7 @@ nlm_destroy_host(struct nlm_host *host) | |||
| 176 | */ | 177 | */ |
| 177 | struct nlm_host * | 178 | struct nlm_host * |
| 178 | nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version, | 179 | nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version, |
| 179 | const char *hostname, int hostname_len) | 180 | const char *hostname, unsigned int hostname_len) |
| 180 | { | 181 | { |
| 181 | struct sockaddr_in ssin = {0}; | 182 | struct sockaddr_in ssin = {0}; |
| 182 | 183 | ||
| @@ -189,7 +190,7 @@ nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version, | |||
| 189 | */ | 190 | */ |
| 190 | struct nlm_host * | 191 | struct nlm_host * |
| 191 | nlmsvc_lookup_host(struct svc_rqst *rqstp, | 192 | nlmsvc_lookup_host(struct svc_rqst *rqstp, |
| 192 | const char *hostname, int hostname_len) | 193 | const char *hostname, unsigned int hostname_len) |
| 193 | { | 194 | { |
| 194 | struct sockaddr_in ssin = {0}; | 195 | struct sockaddr_in ssin = {0}; |
| 195 | 196 | ||
| @@ -307,7 +308,8 @@ void nlm_release_host(struct nlm_host *host) | |||
| 307 | * Release all resources held by that peer. | 308 | * Release all resources held by that peer. |
| 308 | */ | 309 | */ |
| 309 | void nlm_host_rebooted(const struct sockaddr_in *sin, | 310 | void nlm_host_rebooted(const struct sockaddr_in *sin, |
| 310 | const char *hostname, int hostname_len, | 311 | const char *hostname, |
| 312 | unsigned int hostname_len, | ||
| 311 | u32 new_state) | 313 | u32 new_state) |
| 312 | { | 314 | { |
| 313 | struct hlist_head *chain; | 315 | struct hlist_head *chain; |
| @@ -377,8 +379,13 @@ nlm_shutdown_hosts(void) | |||
| 377 | /* First, make all hosts eligible for gc */ | 379 | /* First, make all hosts eligible for gc */ |
| 378 | dprintk("lockd: nuking all hosts...\n"); | 380 | dprintk("lockd: nuking all hosts...\n"); |
| 379 | for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { | 381 | for (chain = nlm_hosts; chain < nlm_hosts + NLM_HOST_NRHASH; ++chain) { |
| 380 | hlist_for_each_entry(host, pos, chain, h_hash) | 382 | hlist_for_each_entry(host, pos, chain, h_hash) { |
| 381 | host->h_expires = jiffies - 1; | 383 | host->h_expires = jiffies - 1; |
| 384 | if (host->h_rpcclnt) { | ||
| 385 | rpc_shutdown_client(host->h_rpcclnt); | ||
| 386 | host->h_rpcclnt = NULL; | ||
| 387 | } | ||
| 388 | } | ||
| 382 | } | 389 | } |
| 383 | 390 | ||
| 384 | /* Then, perform a garbage collection pass */ | 391 | /* Then, perform a garbage collection pass */ |
| @@ -449,7 +456,7 @@ static DEFINE_MUTEX(nsm_mutex); | |||
| 449 | 456 | ||
| 450 | static struct nsm_handle * | 457 | static struct nsm_handle * |
| 451 | __nsm_find(const struct sockaddr_in *sin, | 458 | __nsm_find(const struct sockaddr_in *sin, |
| 452 | const char *hostname, int hostname_len, | 459 | const char *hostname, unsigned int hostname_len, |
| 453 | int create) | 460 | int create) |
| 454 | { | 461 | { |
| 455 | struct nsm_handle *nsm = NULL; | 462 | struct nsm_handle *nsm = NULL; |
| @@ -503,7 +510,8 @@ out: | |||
| 503 | } | 510 | } |
| 504 | 511 | ||
| 505 | static struct nsm_handle * | 512 | static struct nsm_handle * |
| 506 | nsm_find(const struct sockaddr_in *sin, const char *hostname, int hostname_len) | 513 | nsm_find(const struct sockaddr_in *sin, const char *hostname, |
| 514 | unsigned int hostname_len) | ||
| 507 | { | 515 | { |
| 508 | return __nsm_find(sin, hostname, hostname_len, 1); | 516 | return __nsm_find(sin, hostname, hostname_len, 1); |
| 509 | } | 517 | } |
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 82e2192a0d5c..08226464e563 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c | |||
| @@ -219,19 +219,6 @@ lockd(struct svc_rqst *rqstp) | |||
| 219 | module_put_and_exit(0); | 219 | module_put_and_exit(0); |
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | |||
| 223 | static int find_socket(struct svc_serv *serv, int proto) | ||
| 224 | { | ||
| 225 | struct svc_sock *svsk; | ||
| 226 | int found = 0; | ||
| 227 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) | ||
| 228 | if (svsk->sk_sk->sk_protocol == proto) { | ||
| 229 | found = 1; | ||
| 230 | break; | ||
| 231 | } | ||
| 232 | return found; | ||
| 233 | } | ||
| 234 | |||
| 235 | /* | 222 | /* |
| 236 | * Make any sockets that are needed but not present. | 223 | * Make any sockets that are needed but not present. |
| 237 | * If nlm_udpport or nlm_tcpport were set as module | 224 | * If nlm_udpport or nlm_tcpport were set as module |
| @@ -240,17 +227,25 @@ static int find_socket(struct svc_serv *serv, int proto) | |||
| 240 | static int make_socks(struct svc_serv *serv, int proto) | 227 | static int make_socks(struct svc_serv *serv, int proto) |
| 241 | { | 228 | { |
| 242 | static int warned; | 229 | static int warned; |
| 230 | struct svc_xprt *xprt; | ||
| 243 | int err = 0; | 231 | int err = 0; |
| 244 | 232 | ||
| 245 | if (proto == IPPROTO_UDP || nlm_udpport) | 233 | if (proto == IPPROTO_UDP || nlm_udpport) { |
| 246 | if (!find_socket(serv, IPPROTO_UDP)) | 234 | xprt = svc_find_xprt(serv, "udp", 0, 0); |
| 247 | err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport, | 235 | if (!xprt) |
| 248 | SVC_SOCK_DEFAULTS); | 236 | err = svc_create_xprt(serv, "udp", nlm_udpport, |
| 249 | if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) | 237 | SVC_SOCK_DEFAULTS); |
| 250 | if (!find_socket(serv, IPPROTO_TCP)) | 238 | else |
| 251 | err = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport, | 239 | svc_xprt_put(xprt); |
| 252 | SVC_SOCK_DEFAULTS); | 240 | } |
| 253 | 241 | if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) { | |
| 242 | xprt = svc_find_xprt(serv, "tcp", 0, 0); | ||
| 243 | if (!xprt) | ||
| 244 | err = svc_create_xprt(serv, "tcp", nlm_tcpport, | ||
| 245 | SVC_SOCK_DEFAULTS); | ||
| 246 | else | ||
| 247 | svc_xprt_put(xprt); | ||
| 248 | } | ||
| 254 | if (err >= 0) { | 249 | if (err >= 0) { |
| 255 | warned = 0; | 250 | warned = 0; |
| 256 | err = 0; | 251 | err = 0; |
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index bf27b6c6cb6b..385437e3387d 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c | |||
| @@ -84,6 +84,7 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 84 | { | 84 | { |
| 85 | struct nlm_host *host; | 85 | struct nlm_host *host; |
| 86 | struct nlm_file *file; | 86 | struct nlm_file *file; |
| 87 | int rc = rpc_success; | ||
| 87 | 88 | ||
| 88 | dprintk("lockd: TEST4 called\n"); | 89 | dprintk("lockd: TEST4 called\n"); |
| 89 | resp->cookie = argp->cookie; | 90 | resp->cookie = argp->cookie; |
| @@ -91,7 +92,7 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 91 | /* Don't accept test requests during grace period */ | 92 | /* Don't accept test requests during grace period */ |
| 92 | if (nlmsvc_grace_period) { | 93 | if (nlmsvc_grace_period) { |
| 93 | resp->status = nlm_lck_denied_grace_period; | 94 | resp->status = nlm_lck_denied_grace_period; |
| 94 | return rpc_success; | 95 | return rc; |
| 95 | } | 96 | } |
| 96 | 97 | ||
| 97 | /* Obtain client and file */ | 98 | /* Obtain client and file */ |
| @@ -101,12 +102,13 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 101 | /* Now check for conflicting locks */ | 102 | /* Now check for conflicting locks */ |
| 102 | resp->status = nlmsvc_testlock(rqstp, file, &argp->lock, &resp->lock, &resp->cookie); | 103 | resp->status = nlmsvc_testlock(rqstp, file, &argp->lock, &resp->lock, &resp->cookie); |
| 103 | if (resp->status == nlm_drop_reply) | 104 | if (resp->status == nlm_drop_reply) |
| 104 | return rpc_drop_reply; | 105 | rc = rpc_drop_reply; |
| 106 | else | ||
| 107 | dprintk("lockd: TEST4 status %d\n", ntohl(resp->status)); | ||
| 105 | 108 | ||
| 106 | dprintk("lockd: TEST4 status %d\n", ntohl(resp->status)); | ||
| 107 | nlm_release_host(host); | 109 | nlm_release_host(host); |
| 108 | nlm_release_file(file); | 110 | nlm_release_file(file); |
| 109 | return rpc_success; | 111 | return rc; |
| 110 | } | 112 | } |
| 111 | 113 | ||
| 112 | static __be32 | 114 | static __be32 |
| @@ -115,6 +117,7 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 115 | { | 117 | { |
| 116 | struct nlm_host *host; | 118 | struct nlm_host *host; |
| 117 | struct nlm_file *file; | 119 | struct nlm_file *file; |
| 120 | int rc = rpc_success; | ||
| 118 | 121 | ||
| 119 | dprintk("lockd: LOCK called\n"); | 122 | dprintk("lockd: LOCK called\n"); |
| 120 | 123 | ||
| @@ -123,7 +126,7 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 123 | /* Don't accept new lock requests during grace period */ | 126 | /* Don't accept new lock requests during grace period */ |
| 124 | if (nlmsvc_grace_period && !argp->reclaim) { | 127 | if (nlmsvc_grace_period && !argp->reclaim) { |
| 125 | resp->status = nlm_lck_denied_grace_period; | 128 | resp->status = nlm_lck_denied_grace_period; |
| 126 | return rpc_success; | 129 | return rc; |
| 127 | } | 130 | } |
| 128 | 131 | ||
| 129 | /* Obtain client and file */ | 132 | /* Obtain client and file */ |
| @@ -146,12 +149,13 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 146 | resp->status = nlmsvc_lock(rqstp, file, &argp->lock, | 149 | resp->status = nlmsvc_lock(rqstp, file, &argp->lock, |
| 147 | argp->block, &argp->cookie); | 150 | argp->block, &argp->cookie); |
| 148 | if (resp->status == nlm_drop_reply) | 151 | if (resp->status == nlm_drop_reply) |
| 149 | return rpc_drop_reply; | 152 | rc = rpc_drop_reply; |
| 153 | else | ||
| 154 | dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); | ||
| 150 | 155 | ||
| 151 | dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); | ||
| 152 | nlm_release_host(host); | 156 | nlm_release_host(host); |
| 153 | nlm_release_file(file); | 157 | nlm_release_file(file); |
| 154 | return rpc_success; | 158 | return rc; |
| 155 | } | 159 | } |
| 156 | 160 | ||
| 157 | static __be32 | 161 | static __be32 |
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index d120ec39bcb0..2f4d8fa66689 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
| @@ -501,25 +501,29 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file, | |||
| 501 | block, block->b_flags, block->b_fl); | 501 | block, block->b_flags, block->b_fl); |
| 502 | if (block->b_flags & B_TIMED_OUT) { | 502 | if (block->b_flags & B_TIMED_OUT) { |
| 503 | nlmsvc_unlink_block(block); | 503 | nlmsvc_unlink_block(block); |
| 504 | return nlm_lck_denied; | 504 | ret = nlm_lck_denied; |
| 505 | goto out; | ||
| 505 | } | 506 | } |
| 506 | if (block->b_flags & B_GOT_CALLBACK) { | 507 | if (block->b_flags & B_GOT_CALLBACK) { |
| 508 | nlmsvc_unlink_block(block); | ||
| 507 | if (block->b_fl != NULL | 509 | if (block->b_fl != NULL |
| 508 | && block->b_fl->fl_type != F_UNLCK) { | 510 | && block->b_fl->fl_type != F_UNLCK) { |
| 509 | lock->fl = *block->b_fl; | 511 | lock->fl = *block->b_fl; |
| 510 | goto conf_lock; | 512 | goto conf_lock; |
| 511 | } | 513 | } else { |
| 512 | else { | 514 | ret = nlm_granted; |
| 513 | nlmsvc_unlink_block(block); | 515 | goto out; |
| 514 | return nlm_granted; | ||
| 515 | } | 516 | } |
| 516 | } | 517 | } |
| 517 | return nlm_drop_reply; | 518 | ret = nlm_drop_reply; |
| 519 | goto out; | ||
| 518 | } | 520 | } |
| 519 | 521 | ||
| 520 | error = vfs_test_lock(file->f_file, &lock->fl); | 522 | error = vfs_test_lock(file->f_file, &lock->fl); |
| 521 | if (error == -EINPROGRESS) | 523 | if (error == -EINPROGRESS) { |
| 522 | return nlmsvc_defer_lock_rqst(rqstp, block); | 524 | ret = nlmsvc_defer_lock_rqst(rqstp, block); |
| 525 | goto out; | ||
| 526 | } | ||
| 523 | if (error) { | 527 | if (error) { |
| 524 | ret = nlm_lck_denied_nolocks; | 528 | ret = nlm_lck_denied_nolocks; |
| 525 | goto out; | 529 | goto out; |
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 9cd5c8b37593..88379cc6e0b1 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c | |||
| @@ -113,6 +113,7 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 113 | { | 113 | { |
| 114 | struct nlm_host *host; | 114 | struct nlm_host *host; |
| 115 | struct nlm_file *file; | 115 | struct nlm_file *file; |
| 116 | int rc = rpc_success; | ||
| 116 | 117 | ||
| 117 | dprintk("lockd: TEST called\n"); | 118 | dprintk("lockd: TEST called\n"); |
| 118 | resp->cookie = argp->cookie; | 119 | resp->cookie = argp->cookie; |
| @@ -120,7 +121,7 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 120 | /* Don't accept test requests during grace period */ | 121 | /* Don't accept test requests during grace period */ |
| 121 | if (nlmsvc_grace_period) { | 122 | if (nlmsvc_grace_period) { |
| 122 | resp->status = nlm_lck_denied_grace_period; | 123 | resp->status = nlm_lck_denied_grace_period; |
| 123 | return rpc_success; | 124 | return rc; |
| 124 | } | 125 | } |
| 125 | 126 | ||
| 126 | /* Obtain client and file */ | 127 | /* Obtain client and file */ |
| @@ -130,13 +131,14 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 130 | /* Now check for conflicting locks */ | 131 | /* Now check for conflicting locks */ |
| 131 | resp->status = cast_status(nlmsvc_testlock(rqstp, file, &argp->lock, &resp->lock, &resp->cookie)); | 132 | resp->status = cast_status(nlmsvc_testlock(rqstp, file, &argp->lock, &resp->lock, &resp->cookie)); |
| 132 | if (resp->status == nlm_drop_reply) | 133 | if (resp->status == nlm_drop_reply) |
| 133 | return rpc_drop_reply; | 134 | rc = rpc_drop_reply; |
| 135 | else | ||
| 136 | dprintk("lockd: TEST status %d vers %d\n", | ||
| 137 | ntohl(resp->status), rqstp->rq_vers); | ||
| 134 | 138 | ||
| 135 | dprintk("lockd: TEST status %d vers %d\n", | ||
| 136 | ntohl(resp->status), rqstp->rq_vers); | ||
| 137 | nlm_release_host(host); | 139 | nlm_release_host(host); |
| 138 | nlm_release_file(file); | 140 | nlm_release_file(file); |
| 139 | return rpc_success; | 141 | return rc; |
| 140 | } | 142 | } |
| 141 | 143 | ||
| 142 | static __be32 | 144 | static __be32 |
| @@ -145,6 +147,7 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 145 | { | 147 | { |
| 146 | struct nlm_host *host; | 148 | struct nlm_host *host; |
| 147 | struct nlm_file *file; | 149 | struct nlm_file *file; |
| 150 | int rc = rpc_success; | ||
| 148 | 151 | ||
| 149 | dprintk("lockd: LOCK called\n"); | 152 | dprintk("lockd: LOCK called\n"); |
| 150 | 153 | ||
| @@ -153,7 +156,7 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 153 | /* Don't accept new lock requests during grace period */ | 156 | /* Don't accept new lock requests during grace period */ |
| 154 | if (nlmsvc_grace_period && !argp->reclaim) { | 157 | if (nlmsvc_grace_period && !argp->reclaim) { |
| 155 | resp->status = nlm_lck_denied_grace_period; | 158 | resp->status = nlm_lck_denied_grace_period; |
| 156 | return rpc_success; | 159 | return rc; |
| 157 | } | 160 | } |
| 158 | 161 | ||
| 159 | /* Obtain client and file */ | 162 | /* Obtain client and file */ |
| @@ -176,12 +179,13 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 176 | resp->status = cast_status(nlmsvc_lock(rqstp, file, &argp->lock, | 179 | resp->status = cast_status(nlmsvc_lock(rqstp, file, &argp->lock, |
| 177 | argp->block, &argp->cookie)); | 180 | argp->block, &argp->cookie)); |
| 178 | if (resp->status == nlm_drop_reply) | 181 | if (resp->status == nlm_drop_reply) |
| 179 | return rpc_drop_reply; | 182 | rc = rpc_drop_reply; |
| 183 | else | ||
| 184 | dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); | ||
| 180 | 185 | ||
| 181 | dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); | ||
| 182 | nlm_release_host(host); | 186 | nlm_release_host(host); |
| 183 | nlm_release_file(file); | 187 | nlm_release_file(file); |
| 184 | return rpc_success; | 188 | return rc; |
| 185 | } | 189 | } |
| 186 | 190 | ||
| 187 | static __be32 | 191 | static __be32 |
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index 84ebba33b98d..dbbefbcd6712 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c | |||
| @@ -87,7 +87,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result, | |||
| 87 | unsigned int hash; | 87 | unsigned int hash; |
| 88 | __be32 nfserr; | 88 | __be32 nfserr; |
| 89 | 89 | ||
| 90 | nlm_debug_print_fh("nlm_file_lookup", f); | 90 | nlm_debug_print_fh("nlm_lookup_file", f); |
| 91 | 91 | ||
| 92 | hash = file_hash(f); | 92 | hash = file_hash(f); |
| 93 | 93 | ||
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 9b6bbf1b9787..bd185a572a23 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
| @@ -119,8 +119,8 @@ int nfs_callback_up(void) | |||
| 119 | if (!serv) | 119 | if (!serv) |
| 120 | goto out_err; | 120 | goto out_err; |
| 121 | 121 | ||
| 122 | ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport, | 122 | ret = svc_create_xprt(serv, "tcp", nfs_callback_set_tcpport, |
| 123 | SVC_SOCK_ANONYMOUS); | 123 | SVC_SOCK_ANONYMOUS); |
| 124 | if (ret <= 0) | 124 | if (ret <= 0) |
| 125 | goto out_destroy; | 125 | goto out_destroy; |
| 126 | nfs_callback_tcpport = ret; | 126 | nfs_callback_tcpport = ret; |
diff --git a/fs/nfsd/auth.h b/fs/nfsd/auth.h new file mode 100644 index 000000000000..78b3c0e93822 --- /dev/null +++ b/fs/nfsd/auth.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* | ||
| 2 | * nfsd-specific authentication stuff. | ||
| 3 | * uid/gid mapping not yet implemented. | ||
| 4 | * | ||
| 5 | * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef LINUX_NFSD_AUTH_H | ||
| 9 | #define LINUX_NFSD_AUTH_H | ||
| 10 | |||
| 11 | #define nfsd_luid(rq, uid) ((u32)(uid)) | ||
| 12 | #define nfsd_lgid(rq, gid) ((u32)(gid)) | ||
| 13 | #define nfsd_ruid(rq, uid) ((u32)(uid)) | ||
| 14 | #define nfsd_rgid(rq, gid) ((u32)(gid)) | ||
| 15 | |||
| 16 | /* | ||
| 17 | * Set the current process's fsuid/fsgid etc to those of the NFS | ||
| 18 | * client user | ||
| 19 | */ | ||
| 20 | int nfsd_setuser(struct svc_rqst *, struct svc_export *); | ||
| 21 | |||
| 22 | #endif /* LINUX_NFSD_AUTH_H */ | ||
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 66d0aeb32a47..79b4bf812960 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
| @@ -1357,8 +1357,6 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp) | |||
| 1357 | mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL); | 1357 | mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL); |
| 1358 | 1358 | ||
| 1359 | exp = rqst_exp_find(rqstp, FSID_NUM, fsidv); | 1359 | exp = rqst_exp_find(rqstp, FSID_NUM, fsidv); |
| 1360 | if (PTR_ERR(exp) == -ENOENT) | ||
| 1361 | return nfserr_perm; | ||
| 1362 | if (IS_ERR(exp)) | 1360 | if (IS_ERR(exp)) |
| 1363 | return nfserrno(PTR_ERR(exp)); | 1361 | return nfserrno(PTR_ERR(exp)); |
| 1364 | rv = fh_compose(fhp, exp, exp->ex_dentry, NULL); | 1362 | rv = fh_compose(fhp, exp, exp->ex_dentry, NULL); |
| @@ -1637,13 +1635,19 @@ exp_verify_string(char *cp, int max) | |||
| 1637 | /* | 1635 | /* |
| 1638 | * Initialize the exports module. | 1636 | * Initialize the exports module. |
| 1639 | */ | 1637 | */ |
| 1640 | void | 1638 | int |
| 1641 | nfsd_export_init(void) | 1639 | nfsd_export_init(void) |
| 1642 | { | 1640 | { |
| 1641 | int rv; | ||
| 1643 | dprintk("nfsd: initializing export module.\n"); | 1642 | dprintk("nfsd: initializing export module.\n"); |
| 1644 | 1643 | ||
| 1645 | cache_register(&svc_export_cache); | 1644 | rv = cache_register(&svc_export_cache); |
| 1646 | cache_register(&svc_expkey_cache); | 1645 | if (rv) |
| 1646 | return rv; | ||
| 1647 | rv = cache_register(&svc_expkey_cache); | ||
| 1648 | if (rv) | ||
| 1649 | cache_unregister(&svc_export_cache); | ||
| 1650 | return rv; | ||
| 1647 | 1651 | ||
| 1648 | } | 1652 | } |
| 1649 | 1653 | ||
| @@ -1670,10 +1674,8 @@ nfsd_export_shutdown(void) | |||
| 1670 | 1674 | ||
| 1671 | exp_writelock(); | 1675 | exp_writelock(); |
| 1672 | 1676 | ||
| 1673 | if (cache_unregister(&svc_expkey_cache)) | 1677 | cache_unregister(&svc_expkey_cache); |
| 1674 | printk(KERN_ERR "nfsd: failed to unregister expkey cache\n"); | 1678 | cache_unregister(&svc_export_cache); |
| 1675 | if (cache_unregister(&svc_export_cache)) | ||
| 1676 | printk(KERN_ERR "nfsd: failed to unregister export cache\n"); | ||
| 1677 | svcauth_unix_purge(); | 1679 | svcauth_unix_purge(); |
| 1678 | 1680 | ||
| 1679 | exp_writeunlock(); | 1681 | exp_writeunlock(); |
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c index 0e5fa11e6b44..1c3b7654e966 100644 --- a/fs/nfsd/nfs2acl.c +++ b/fs/nfsd/nfs2acl.c | |||
| @@ -221,12 +221,17 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p, | |||
| 221 | struct nfsd3_getaclres *resp) | 221 | struct nfsd3_getaclres *resp) |
| 222 | { | 222 | { |
| 223 | struct dentry *dentry = resp->fh.fh_dentry; | 223 | struct dentry *dentry = resp->fh.fh_dentry; |
| 224 | struct inode *inode = dentry->d_inode; | 224 | struct inode *inode; |
| 225 | struct kvec *head = rqstp->rq_res.head; | 225 | struct kvec *head = rqstp->rq_res.head; |
| 226 | unsigned int base; | 226 | unsigned int base; |
| 227 | int n; | 227 | int n; |
| 228 | int w; | 228 | int w; |
| 229 | 229 | ||
| 230 | /* | ||
| 231 | * Since this is version 2, the check for nfserr in | ||
| 232 | * nfsd_dispatch actually ensures the following cannot happen. | ||
| 233 | * However, it seems fragile to depend on that. | ||
| 234 | */ | ||
| 230 | if (dentry == NULL || dentry->d_inode == NULL) | 235 | if (dentry == NULL || dentry->d_inode == NULL) |
| 231 | return 0; | 236 | return 0; |
| 232 | inode = dentry->d_inode; | 237 | inode = dentry->d_inode; |
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index f917fd25858a..d7647f70e02b 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/sunrpc/svc.h> | 21 | #include <linux/sunrpc/svc.h> |
| 22 | #include <linux/nfsd/nfsd.h> | 22 | #include <linux/nfsd/nfsd.h> |
| 23 | #include <linux/nfsd/xdr3.h> | 23 | #include <linux/nfsd/xdr3.h> |
| 24 | #include "auth.h" | ||
| 24 | 25 | ||
| 25 | #define NFSDDBG_FACILITY NFSDDBG_XDR | 26 | #define NFSDDBG_FACILITY NFSDDBG_XDR |
| 26 | 27 | ||
| @@ -88,10 +89,10 @@ encode_fh(__be32 *p, struct svc_fh *fhp) | |||
| 88 | * no slashes or null bytes. | 89 | * no slashes or null bytes. |
| 89 | */ | 90 | */ |
| 90 | static __be32 * | 91 | static __be32 * |
| 91 | decode_filename(__be32 *p, char **namp, int *lenp) | 92 | decode_filename(__be32 *p, char **namp, unsigned int *lenp) |
| 92 | { | 93 | { |
| 93 | char *name; | 94 | char *name; |
| 94 | int i; | 95 | unsigned int i; |
| 95 | 96 | ||
| 96 | if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS3_MAXNAMLEN)) != NULL) { | 97 | if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS3_MAXNAMLEN)) != NULL) { |
| 97 | for (i = 0, name = *namp; i < *lenp; i++, name++) { | 98 | for (i = 0, name = *namp; i < *lenp; i++, name++) { |
| @@ -452,8 +453,7 @@ int | |||
| 452 | nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p, | 453 | nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p, |
| 453 | struct nfsd3_symlinkargs *args) | 454 | struct nfsd3_symlinkargs *args) |
| 454 | { | 455 | { |
| 455 | unsigned int len; | 456 | unsigned int len, avail; |
| 456 | int avail; | ||
| 457 | char *old, *new; | 457 | char *old, *new; |
| 458 | struct kvec *vec; | 458 | struct kvec *vec; |
| 459 | 459 | ||
| @@ -486,7 +486,8 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p, | |||
| 486 | /* now copy next page if there is one */ | 486 | /* now copy next page if there is one */ |
| 487 | if (len && !avail && rqstp->rq_arg.page_len) { | 487 | if (len && !avail && rqstp->rq_arg.page_len) { |
| 488 | avail = rqstp->rq_arg.page_len; | 488 | avail = rqstp->rq_arg.page_len; |
| 489 | if (avail > PAGE_SIZE) avail = PAGE_SIZE; | 489 | if (avail > PAGE_SIZE) |
| 490 | avail = PAGE_SIZE; | ||
| 490 | old = page_address(rqstp->rq_arg.pages[0]); | 491 | old = page_address(rqstp->rq_arg.pages[0]); |
| 491 | } | 492 | } |
| 492 | while (len && avail && *old) { | 493 | while (len && avail && *old) { |
| @@ -816,11 +817,11 @@ static __be32 * | |||
| 816 | encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, | 817 | encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, |
| 817 | struct svc_fh *fhp) | 818 | struct svc_fh *fhp) |
| 818 | { | 819 | { |
| 819 | p = encode_post_op_attr(cd->rqstp, p, fhp); | 820 | p = encode_post_op_attr(cd->rqstp, p, fhp); |
| 820 | *p++ = xdr_one; /* yes, a file handle follows */ | 821 | *p++ = xdr_one; /* yes, a file handle follows */ |
| 821 | p = encode_fh(p, fhp); | 822 | p = encode_fh(p, fhp); |
| 822 | fh_put(fhp); | 823 | fh_put(fhp); |
| 823 | return p; | 824 | return p; |
| 824 | } | 825 | } |
| 825 | 826 | ||
| 826 | static int | 827 | static int |
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 9d536a8cb379..aae2b29ae2c9 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
| @@ -350,30 +350,6 @@ static struct rpc_version * nfs_cb_version[] = { | |||
| 350 | static int do_probe_callback(void *data) | 350 | static int do_probe_callback(void *data) |
| 351 | { | 351 | { |
| 352 | struct nfs4_client *clp = data; | 352 | struct nfs4_client *clp = data; |
| 353 | struct nfs4_callback *cb = &clp->cl_callback; | ||
| 354 | struct rpc_message msg = { | ||
| 355 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], | ||
| 356 | .rpc_argp = clp, | ||
| 357 | }; | ||
| 358 | int status; | ||
| 359 | |||
| 360 | status = rpc_call_sync(cb->cb_client, &msg, RPC_TASK_SOFT); | ||
| 361 | |||
| 362 | if (status) { | ||
| 363 | rpc_shutdown_client(cb->cb_client); | ||
| 364 | cb->cb_client = NULL; | ||
| 365 | } else | ||
| 366 | atomic_set(&cb->cb_set, 1); | ||
| 367 | put_nfs4_client(clp); | ||
| 368 | return 0; | ||
| 369 | } | ||
| 370 | |||
| 371 | /* | ||
| 372 | * Set up the callback client and put a NFSPROC4_CB_NULL on the wire... | ||
| 373 | */ | ||
| 374 | void | ||
| 375 | nfsd4_probe_callback(struct nfs4_client *clp) | ||
| 376 | { | ||
| 377 | struct sockaddr_in addr; | 353 | struct sockaddr_in addr; |
| 378 | struct nfs4_callback *cb = &clp->cl_callback; | 354 | struct nfs4_callback *cb = &clp->cl_callback; |
| 379 | struct rpc_timeout timeparms = { | 355 | struct rpc_timeout timeparms = { |
| @@ -390,13 +366,15 @@ nfsd4_probe_callback(struct nfs4_client *clp) | |||
| 390 | .timeout = &timeparms, | 366 | .timeout = &timeparms, |
| 391 | .program = program, | 367 | .program = program, |
| 392 | .version = nfs_cb_version[1]->number, | 368 | .version = nfs_cb_version[1]->number, |
| 393 | .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ | 369 | .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ |
| 394 | .flags = (RPC_CLNT_CREATE_NOPING), | 370 | .flags = (RPC_CLNT_CREATE_NOPING), |
| 395 | }; | 371 | }; |
| 396 | struct task_struct *t; | 372 | struct rpc_message msg = { |
| 397 | 373 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], | |
| 398 | if (atomic_read(&cb->cb_set)) | 374 | .rpc_argp = clp, |
| 399 | return; | 375 | }; |
| 376 | struct rpc_clnt *client; | ||
| 377 | int status; | ||
| 400 | 378 | ||
| 401 | /* Initialize address */ | 379 | /* Initialize address */ |
| 402 | memset(&addr, 0, sizeof(addr)); | 380 | memset(&addr, 0, sizeof(addr)); |
| @@ -416,29 +394,50 @@ nfsd4_probe_callback(struct nfs4_client *clp) | |||
| 416 | program->stats->program = program; | 394 | program->stats->program = program; |
| 417 | 395 | ||
| 418 | /* Create RPC client */ | 396 | /* Create RPC client */ |
| 419 | cb->cb_client = rpc_create(&args); | 397 | client = rpc_create(&args); |
| 420 | if (IS_ERR(cb->cb_client)) { | 398 | if (IS_ERR(client)) { |
| 421 | dprintk("NFSD: couldn't create callback client\n"); | 399 | dprintk("NFSD: couldn't create callback client\n"); |
| 400 | status = PTR_ERR(client); | ||
| 422 | goto out_err; | 401 | goto out_err; |
| 423 | } | 402 | } |
| 424 | 403 | ||
| 404 | status = rpc_call_sync(client, &msg, RPC_TASK_SOFT); | ||
| 405 | |||
| 406 | if (status) | ||
| 407 | goto out_release_client; | ||
| 408 | |||
| 409 | cb->cb_client = client; | ||
| 410 | atomic_set(&cb->cb_set, 1); | ||
| 411 | put_nfs4_client(clp); | ||
| 412 | return 0; | ||
| 413 | out_release_client: | ||
| 414 | rpc_shutdown_client(client); | ||
| 415 | out_err: | ||
| 416 | put_nfs4_client(clp); | ||
| 417 | dprintk("NFSD: warning: no callback path to client %.*s\n", | ||
| 418 | (int)clp->cl_name.len, clp->cl_name.data); | ||
| 419 | return status; | ||
| 420 | } | ||
| 421 | |||
| 422 | /* | ||
| 423 | * Set up the callback client and put a NFSPROC4_CB_NULL on the wire... | ||
| 424 | */ | ||
| 425 | void | ||
| 426 | nfsd4_probe_callback(struct nfs4_client *clp) | ||
| 427 | { | ||
| 428 | struct task_struct *t; | ||
| 429 | |||
| 430 | BUG_ON(atomic_read(&clp->cl_callback.cb_set)); | ||
| 431 | |||
| 425 | /* the task holds a reference to the nfs4_client struct */ | 432 | /* the task holds a reference to the nfs4_client struct */ |
| 426 | atomic_inc(&clp->cl_count); | 433 | atomic_inc(&clp->cl_count); |
| 427 | 434 | ||
| 428 | t = kthread_run(do_probe_callback, clp, "nfs4_cb_probe"); | 435 | t = kthread_run(do_probe_callback, clp, "nfs4_cb_probe"); |
| 429 | 436 | ||
| 430 | if (IS_ERR(t)) | 437 | if (IS_ERR(t)) |
| 431 | goto out_release_clp; | 438 | atomic_dec(&clp->cl_count); |
| 432 | 439 | ||
| 433 | return; | 440 | return; |
| 434 | |||
| 435 | out_release_clp: | ||
| 436 | atomic_dec(&clp->cl_count); | ||
| 437 | rpc_shutdown_client(cb->cb_client); | ||
| 438 | out_err: | ||
| 439 | cb->cb_client = NULL; | ||
| 440 | dprintk("NFSD: warning: no callback path to client %.*s\n", | ||
| 441 | (int)clp->cl_name.len, clp->cl_name.data); | ||
| 442 | } | 441 | } |
| 443 | 442 | ||
| 444 | /* | 443 | /* |
| @@ -458,9 +457,6 @@ nfsd4_cb_recall(struct nfs4_delegation *dp) | |||
| 458 | int retries = 1; | 457 | int retries = 1; |
| 459 | int status = 0; | 458 | int status = 0; |
| 460 | 459 | ||
| 461 | if ((!atomic_read(&clp->cl_callback.cb_set)) || !clnt) | ||
| 462 | return; | ||
| 463 | |||
| 464 | cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */ | 460 | cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */ |
| 465 | cbr->cbr_dp = dp; | 461 | cbr->cbr_dp = dp; |
| 466 | 462 | ||
| @@ -469,6 +465,7 @@ nfsd4_cb_recall(struct nfs4_delegation *dp) | |||
| 469 | switch (status) { | 465 | switch (status) { |
| 470 | case -EIO: | 466 | case -EIO: |
| 471 | /* Network partition? */ | 467 | /* Network partition? */ |
| 468 | atomic_set(&clp->cl_callback.cb_set, 0); | ||
| 472 | case -EBADHANDLE: | 469 | case -EBADHANDLE: |
| 473 | case -NFS4ERR_BAD_STATEID: | 470 | case -NFS4ERR_BAD_STATEID: |
| 474 | /* Race: client probably got cb_recall | 471 | /* Race: client probably got cb_recall |
| @@ -481,11 +478,10 @@ nfsd4_cb_recall(struct nfs4_delegation *dp) | |||
| 481 | status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT); | 478 | status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT); |
| 482 | } | 479 | } |
| 483 | out_put_cred: | 480 | out_put_cred: |
| 484 | if (status == -EIO) | 481 | /* |
| 485 | atomic_set(&clp->cl_callback.cb_set, 0); | 482 | * Success or failure, now we're either waiting for lease expiration |
| 486 | /* Success or failure, now we're either waiting for lease expiration | 483 | * or deleg_return. |
| 487 | * or deleg_return. */ | 484 | */ |
| 488 | dprintk("NFSD: nfs4_cb_recall: dp %p dl_flock %p dl_count %d\n",dp, dp->dl_flock, atomic_read(&dp->dl_count)); | ||
| 489 | put_nfs4_client(clp); | 485 | put_nfs4_client(clp); |
| 490 | nfs4_put_delegation(dp); | 486 | nfs4_put_delegation(dp); |
| 491 | return; | 487 | return; |
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 4c0c683ce07a..996bd88b75ba 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c | |||
| @@ -255,13 +255,10 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) | |||
| 255 | goto out; | 255 | goto out; |
| 256 | if (len == 0) | 256 | if (len == 0) |
| 257 | set_bit(CACHE_NEGATIVE, &ent.h.flags); | 257 | set_bit(CACHE_NEGATIVE, &ent.h.flags); |
| 258 | else { | 258 | else if (len >= IDMAP_NAMESZ) |
| 259 | if (error >= IDMAP_NAMESZ) { | 259 | goto out; |
| 260 | error = -EINVAL; | 260 | else |
| 261 | goto out; | ||
| 262 | } | ||
| 263 | memcpy(ent.name, buf1, sizeof(ent.name)); | 261 | memcpy(ent.name, buf1, sizeof(ent.name)); |
| 264 | } | ||
| 265 | error = -ENOMEM; | 262 | error = -ENOMEM; |
| 266 | res = idtoname_update(&ent, res); | 263 | res = idtoname_update(&ent, res); |
| 267 | if (res == NULL) | 264 | if (res == NULL) |
| @@ -467,20 +464,25 @@ nametoid_update(struct ent *new, struct ent *old) | |||
| 467 | * Exported API | 464 | * Exported API |
| 468 | */ | 465 | */ |
| 469 | 466 | ||
| 470 | void | 467 | int |
| 471 | nfsd_idmap_init(void) | 468 | nfsd_idmap_init(void) |
| 472 | { | 469 | { |
| 473 | cache_register(&idtoname_cache); | 470 | int rv; |
| 474 | cache_register(&nametoid_cache); | 471 | |
| 472 | rv = cache_register(&idtoname_cache); | ||
| 473 | if (rv) | ||
| 474 | return rv; | ||
| 475 | rv = cache_register(&nametoid_cache); | ||
| 476 | if (rv) | ||
| 477 | cache_unregister(&idtoname_cache); | ||
| 478 | return rv; | ||
| 475 | } | 479 | } |
| 476 | 480 | ||
| 477 | void | 481 | void |
| 478 | nfsd_idmap_shutdown(void) | 482 | nfsd_idmap_shutdown(void) |
| 479 | { | 483 | { |
| 480 | if (cache_unregister(&idtoname_cache)) | 484 | cache_unregister(&idtoname_cache); |
| 481 | printk(KERN_ERR "nfsd: failed to unregister idtoname cache\n"); | 485 | cache_unregister(&nametoid_cache); |
| 482 | if (cache_unregister(&nametoid_cache)) | ||
| 483 | printk(KERN_ERR "nfsd: failed to unregister nametoid cache\n"); | ||
| 484 | } | 486 | } |
| 485 | 487 | ||
| 486 | /* | 488 | /* |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 18ead1790bb3..c593db047d8b 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
| @@ -750,7 +750,7 @@ _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 750 | cstate->current_fh.fh_export, | 750 | cstate->current_fh.fh_export, |
| 751 | cstate->current_fh.fh_dentry, buf, | 751 | cstate->current_fh.fh_dentry, buf, |
| 752 | &count, verify->ve_bmval, | 752 | &count, verify->ve_bmval, |
| 753 | rqstp); | 753 | rqstp, 0); |
| 754 | 754 | ||
| 755 | /* this means that nfsd4_encode_fattr() ran out of space */ | 755 | /* this means that nfsd4_encode_fattr() ran out of space */ |
| 756 | if (status == nfserr_resource && count == 0) | 756 | if (status == nfserr_resource && count == 0) |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 31673cd251c3..f6744bc03dae 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
| @@ -61,7 +61,6 @@ static time_t lease_time = 90; /* default lease time */ | |||
| 61 | static time_t user_lease_time = 90; | 61 | static time_t user_lease_time = 90; |
| 62 | static time_t boot_time; | 62 | static time_t boot_time; |
| 63 | static int in_grace = 1; | 63 | static int in_grace = 1; |
| 64 | static u32 current_clientid = 1; | ||
| 65 | static u32 current_ownerid = 1; | 64 | static u32 current_ownerid = 1; |
| 66 | static u32 current_fileid = 1; | 65 | static u32 current_fileid = 1; |
| 67 | static u32 current_delegid = 1; | 66 | static u32 current_delegid = 1; |
| @@ -340,21 +339,20 @@ STALE_CLIENTID(clientid_t *clid) | |||
| 340 | * This type of memory management is somewhat inefficient, but we use it | 339 | * This type of memory management is somewhat inefficient, but we use it |
| 341 | * anyway since SETCLIENTID is not a common operation. | 340 | * anyway since SETCLIENTID is not a common operation. |
| 342 | */ | 341 | */ |
| 343 | static inline struct nfs4_client * | 342 | static struct nfs4_client *alloc_client(struct xdr_netobj name) |
| 344 | alloc_client(struct xdr_netobj name) | ||
| 345 | { | 343 | { |
| 346 | struct nfs4_client *clp; | 344 | struct nfs4_client *clp; |
| 347 | 345 | ||
| 348 | if ((clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) { | 346 | clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL); |
| 349 | if ((clp->cl_name.data = kmalloc(name.len, GFP_KERNEL)) != NULL) { | 347 | if (clp == NULL) |
| 350 | memcpy(clp->cl_name.data, name.data, name.len); | 348 | return NULL; |
| 351 | clp->cl_name.len = name.len; | 349 | clp->cl_name.data = kmalloc(name.len, GFP_KERNEL); |
| 352 | } | 350 | if (clp->cl_name.data == NULL) { |
| 353 | else { | 351 | kfree(clp); |
| 354 | kfree(clp); | 352 | return NULL; |
| 355 | clp = NULL; | ||
| 356 | } | ||
| 357 | } | 353 | } |
| 354 | memcpy(clp->cl_name.data, name.data, name.len); | ||
| 355 | clp->cl_name.len = name.len; | ||
| 358 | return clp; | 356 | return clp; |
| 359 | } | 357 | } |
| 360 | 358 | ||
| @@ -363,8 +361,11 @@ shutdown_callback_client(struct nfs4_client *clp) | |||
| 363 | { | 361 | { |
| 364 | struct rpc_clnt *clnt = clp->cl_callback.cb_client; | 362 | struct rpc_clnt *clnt = clp->cl_callback.cb_client; |
| 365 | 363 | ||
| 366 | /* shutdown rpc client, ending any outstanding recall rpcs */ | ||
| 367 | if (clnt) { | 364 | if (clnt) { |
| 365 | /* | ||
| 366 | * Callback threads take a reference on the client, so there | ||
| 367 | * should be no outstanding callbacks at this point. | ||
| 368 | */ | ||
| 368 | clp->cl_callback.cb_client = NULL; | 369 | clp->cl_callback.cb_client = NULL; |
| 369 | rpc_shutdown_client(clnt); | 370 | rpc_shutdown_client(clnt); |
| 370 | } | 371 | } |
| @@ -422,12 +423,13 @@ expire_client(struct nfs4_client *clp) | |||
| 422 | put_nfs4_client(clp); | 423 | put_nfs4_client(clp); |
| 423 | } | 424 | } |
| 424 | 425 | ||
| 425 | static struct nfs4_client * | 426 | static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir) |
| 426 | create_client(struct xdr_netobj name, char *recdir) { | 427 | { |
| 427 | struct nfs4_client *clp; | 428 | struct nfs4_client *clp; |
| 428 | 429 | ||
| 429 | if (!(clp = alloc_client(name))) | 430 | clp = alloc_client(name); |
| 430 | goto out; | 431 | if (clp == NULL) |
| 432 | return NULL; | ||
| 431 | memcpy(clp->cl_recdir, recdir, HEXDIR_LEN); | 433 | memcpy(clp->cl_recdir, recdir, HEXDIR_LEN); |
| 432 | atomic_set(&clp->cl_count, 1); | 434 | atomic_set(&clp->cl_count, 1); |
| 433 | atomic_set(&clp->cl_callback.cb_set, 0); | 435 | atomic_set(&clp->cl_callback.cb_set, 0); |
| @@ -436,32 +438,30 @@ create_client(struct xdr_netobj name, char *recdir) { | |||
| 436 | INIT_LIST_HEAD(&clp->cl_openowners); | 438 | INIT_LIST_HEAD(&clp->cl_openowners); |
| 437 | INIT_LIST_HEAD(&clp->cl_delegations); | 439 | INIT_LIST_HEAD(&clp->cl_delegations); |
| 438 | INIT_LIST_HEAD(&clp->cl_lru); | 440 | INIT_LIST_HEAD(&clp->cl_lru); |
| 439 | out: | ||
| 440 | return clp; | 441 | return clp; |
| 441 | } | 442 | } |
| 442 | 443 | ||
| 443 | static void | 444 | static void copy_verf(struct nfs4_client *target, nfs4_verifier *source) |
| 444 | copy_verf(struct nfs4_client *target, nfs4_verifier *source) { | 445 | { |
| 445 | memcpy(target->cl_verifier.data, source->data, sizeof(target->cl_verifier.data)); | 446 | memcpy(target->cl_verifier.data, source->data, |
| 447 | sizeof(target->cl_verifier.data)); | ||
| 446 | } | 448 | } |
| 447 | 449 | ||
| 448 | static void | 450 | static void copy_clid(struct nfs4_client *target, struct nfs4_client *source) |
| 449 | copy_clid(struct nfs4_client *target, struct nfs4_client *source) { | 451 | { |
| 450 | target->cl_clientid.cl_boot = source->cl_clientid.cl_boot; | 452 | target->cl_clientid.cl_boot = source->cl_clientid.cl_boot; |
| 451 | target->cl_clientid.cl_id = source->cl_clientid.cl_id; | 453 | target->cl_clientid.cl_id = source->cl_clientid.cl_id; |
| 452 | } | 454 | } |
| 453 | 455 | ||
| 454 | static void | 456 | static void copy_cred(struct svc_cred *target, struct svc_cred *source) |
| 455 | copy_cred(struct svc_cred *target, struct svc_cred *source) { | 457 | { |
| 456 | |||
| 457 | target->cr_uid = source->cr_uid; | 458 | target->cr_uid = source->cr_uid; |
| 458 | target->cr_gid = source->cr_gid; | 459 | target->cr_gid = source->cr_gid; |
| 459 | target->cr_group_info = source->cr_group_info; | 460 | target->cr_group_info = source->cr_group_info; |
| 460 | get_group_info(target->cr_group_info); | 461 | get_group_info(target->cr_group_info); |
| 461 | } | 462 | } |
| 462 | 463 | ||
| 463 | static inline int | 464 | static int same_name(const char *n1, const char *n2) |
| 464 | same_name(const char *n1, const char *n2) | ||
| 465 | { | 465 | { |
| 466 | return 0 == memcmp(n1, n2, HEXDIR_LEN); | 466 | return 0 == memcmp(n1, n2, HEXDIR_LEN); |
| 467 | } | 467 | } |
| @@ -485,26 +485,26 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2) | |||
| 485 | return cr1->cr_uid == cr2->cr_uid; | 485 | return cr1->cr_uid == cr2->cr_uid; |
| 486 | } | 486 | } |
| 487 | 487 | ||
| 488 | static void | 488 | static void gen_clid(struct nfs4_client *clp) |
| 489 | gen_clid(struct nfs4_client *clp) { | 489 | { |
| 490 | static u32 current_clientid = 1; | ||
| 491 | |||
| 490 | clp->cl_clientid.cl_boot = boot_time; | 492 | clp->cl_clientid.cl_boot = boot_time; |
| 491 | clp->cl_clientid.cl_id = current_clientid++; | 493 | clp->cl_clientid.cl_id = current_clientid++; |
| 492 | } | 494 | } |
| 493 | 495 | ||
| 494 | static void | 496 | static void gen_confirm(struct nfs4_client *clp) |
| 495 | gen_confirm(struct nfs4_client *clp) { | 497 | { |
| 496 | struct timespec tv; | 498 | static u32 i; |
| 497 | u32 * p; | 499 | u32 *p; |
| 498 | 500 | ||
| 499 | tv = CURRENT_TIME; | ||
| 500 | p = (u32 *)clp->cl_confirm.data; | 501 | p = (u32 *)clp->cl_confirm.data; |
| 501 | *p++ = tv.tv_sec; | 502 | *p++ = get_seconds(); |
| 502 | *p++ = tv.tv_nsec; | 503 | *p++ = i++; |
| 503 | } | 504 | } |
| 504 | 505 | ||
| 505 | static int | 506 | static int check_name(struct xdr_netobj name) |
| 506 | check_name(struct xdr_netobj name) { | 507 | { |
| 507 | |||
| 508 | if (name.len == 0) | 508 | if (name.len == 0) |
| 509 | return 0; | 509 | return 0; |
| 510 | if (name.len > NFS4_OPAQUE_LIMIT) { | 510 | if (name.len > NFS4_OPAQUE_LIMIT) { |
| @@ -683,39 +683,6 @@ out_err: | |||
| 683 | return; | 683 | return; |
| 684 | } | 684 | } |
| 685 | 685 | ||
| 686 | /* | ||
| 687 | * RFC 3010 has a complex implmentation description of processing a | ||
| 688 | * SETCLIENTID request consisting of 5 bullets, labeled as | ||
| 689 | * CASE0 - CASE4 below. | ||
| 690 | * | ||
| 691 | * NOTES: | ||
| 692 | * callback information will be processed in a future patch | ||
| 693 | * | ||
| 694 | * an unconfirmed record is added when: | ||
| 695 | * NORMAL (part of CASE 4): there is no confirmed nor unconfirmed record. | ||
| 696 | * CASE 1: confirmed record found with matching name, principal, | ||
| 697 | * verifier, and clientid. | ||
| 698 | * CASE 2: confirmed record found with matching name, principal, | ||
| 699 | * and there is no unconfirmed record with matching | ||
| 700 | * name and principal | ||
| 701 | * | ||
| 702 | * an unconfirmed record is replaced when: | ||
| 703 | * CASE 3: confirmed record found with matching name, principal, | ||
| 704 | * and an unconfirmed record is found with matching | ||
| 705 | * name, principal, and with clientid and | ||
| 706 | * confirm that does not match the confirmed record. | ||
| 707 | * CASE 4: there is no confirmed record with matching name and | ||
| 708 | * principal. there is an unconfirmed record with | ||
| 709 | * matching name, principal. | ||
| 710 | * | ||
| 711 | * an unconfirmed record is deleted when: | ||
| 712 | * CASE 1: an unconfirmed record that matches input name, verifier, | ||
| 713 | * and confirmed clientid. | ||
| 714 | * CASE 4: any unconfirmed records with matching name and principal | ||
| 715 | * that exist after an unconfirmed record has been replaced | ||
| 716 | * as described above. | ||
| 717 | * | ||
| 718 | */ | ||
| 719 | __be32 | 686 | __be32 |
| 720 | nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | 687 | nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
| 721 | struct nfsd4_setclientid *setclid) | 688 | struct nfsd4_setclientid *setclid) |
| @@ -748,11 +715,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 748 | nfs4_lock_state(); | 715 | nfs4_lock_state(); |
| 749 | conf = find_confirmed_client_by_str(dname, strhashval); | 716 | conf = find_confirmed_client_by_str(dname, strhashval); |
| 750 | if (conf) { | 717 | if (conf) { |
| 751 | /* | 718 | /* RFC 3530 14.2.33 CASE 0: */ |
| 752 | * CASE 0: | ||
| 753 | * clname match, confirmed, different principal | ||
| 754 | * or different ip_address | ||
| 755 | */ | ||
| 756 | status = nfserr_clid_inuse; | 719 | status = nfserr_clid_inuse; |
| 757 | if (!same_creds(&conf->cl_cred, &rqstp->rq_cred) | 720 | if (!same_creds(&conf->cl_cred, &rqstp->rq_cred) |
| 758 | || conf->cl_addr != sin->sin_addr.s_addr) { | 721 | || conf->cl_addr != sin->sin_addr.s_addr) { |
| @@ -761,12 +724,17 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 761 | goto out; | 724 | goto out; |
| 762 | } | 725 | } |
| 763 | } | 726 | } |
| 727 | /* | ||
| 728 | * section 14.2.33 of RFC 3530 (under the heading "IMPLEMENTATION") | ||
| 729 | * has a description of SETCLIENTID request processing consisting | ||
| 730 | * of 5 bullet points, labeled as CASE0 - CASE4 below. | ||
| 731 | */ | ||
| 764 | unconf = find_unconfirmed_client_by_str(dname, strhashval); | 732 | unconf = find_unconfirmed_client_by_str(dname, strhashval); |
| 765 | status = nfserr_resource; | 733 | status = nfserr_resource; |
| 766 | if (!conf) { | 734 | if (!conf) { |
| 767 | /* | 735 | /* |
| 768 | * CASE 4: | 736 | * RFC 3530 14.2.33 CASE 4: |
| 769 | * placed first, because it is the normal case. | 737 | * placed first, because it is the normal case |
| 770 | */ | 738 | */ |
| 771 | if (unconf) | 739 | if (unconf) |
| 772 | expire_client(unconf); | 740 | expire_client(unconf); |
| @@ -776,17 +744,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 776 | gen_clid(new); | 744 | gen_clid(new); |
| 777 | } else if (same_verf(&conf->cl_verifier, &clverifier)) { | 745 | } else if (same_verf(&conf->cl_verifier, &clverifier)) { |
| 778 | /* | 746 | /* |
| 779 | * CASE 1: | 747 | * RFC 3530 14.2.33 CASE 1: |
| 780 | * cl_name match, confirmed, principal match | 748 | * probable callback update |
| 781 | * verifier match: probable callback update | ||
| 782 | * | ||
| 783 | * remove any unconfirmed nfs4_client with | ||
| 784 | * matching cl_name, cl_verifier, and cl_clientid | ||
| 785 | * | ||
| 786 | * create and insert an unconfirmed nfs4_client with same | ||
| 787 | * cl_name, cl_verifier, and cl_clientid as existing | ||
| 788 | * nfs4_client, but with the new callback info and a | ||
| 789 | * new cl_confirm | ||
| 790 | */ | 749 | */ |
| 791 | if (unconf) { | 750 | if (unconf) { |
| 792 | /* Note this is removing unconfirmed {*x***}, | 751 | /* Note this is removing unconfirmed {*x***}, |
| @@ -802,43 +761,25 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 802 | copy_clid(new, conf); | 761 | copy_clid(new, conf); |
| 803 | } else if (!unconf) { | 762 | } else if (!unconf) { |
| 804 | /* | 763 | /* |
| 805 | * CASE 2: | 764 | * RFC 3530 14.2.33 CASE 2: |
| 806 | * clname match, confirmed, principal match | 765 | * probable client reboot; state will be removed if |
| 807 | * verfier does not match | 766 | * confirmed. |
| 808 | * no unconfirmed. create a new unconfirmed nfs4_client | ||
| 809 | * using input clverifier, clname, and callback info | ||
| 810 | * and generate a new cl_clientid and cl_confirm. | ||
| 811 | */ | 767 | */ |
| 812 | new = create_client(clname, dname); | 768 | new = create_client(clname, dname); |
| 813 | if (new == NULL) | 769 | if (new == NULL) |
| 814 | goto out; | 770 | goto out; |
| 815 | gen_clid(new); | 771 | gen_clid(new); |
| 816 | } else if (!same_verf(&conf->cl_confirm, &unconf->cl_confirm)) { | 772 | } else { |
| 817 | /* | 773 | /* |
| 818 | * CASE3: | 774 | * RFC 3530 14.2.33 CASE 3: |
| 819 | * confirmed found (name, principal match) | 775 | * probable client reboot; state will be removed if |
| 820 | * confirmed verifier does not match input clverifier | 776 | * confirmed. |
| 821 | * | ||
| 822 | * unconfirmed found (name match) | ||
| 823 | * confirmed->cl_confirm != unconfirmed->cl_confirm | ||
| 824 | * | ||
| 825 | * remove unconfirmed. | ||
| 826 | * | ||
| 827 | * create an unconfirmed nfs4_client | ||
| 828 | * with same cl_name as existing confirmed nfs4_client, | ||
| 829 | * but with new callback info, new cl_clientid, | ||
| 830 | * new cl_verifier and a new cl_confirm | ||
| 831 | */ | 777 | */ |
| 832 | expire_client(unconf); | 778 | expire_client(unconf); |
| 833 | new = create_client(clname, dname); | 779 | new = create_client(clname, dname); |
| 834 | if (new == NULL) | 780 | if (new == NULL) |
| 835 | goto out; | 781 | goto out; |
| 836 | gen_clid(new); | 782 | gen_clid(new); |
| 837 | } else { | ||
| 838 | /* No cases hit !!! */ | ||
| 839 | status = nfserr_inval; | ||
| 840 | goto out; | ||
| 841 | |||
| 842 | } | 783 | } |
| 843 | copy_verf(new, &clverifier); | 784 | copy_verf(new, &clverifier); |
| 844 | new->cl_addr = sin->sin_addr.s_addr; | 785 | new->cl_addr = sin->sin_addr.s_addr; |
| @@ -857,11 +798,9 @@ out: | |||
| 857 | 798 | ||
| 858 | 799 | ||
| 859 | /* | 800 | /* |
| 860 | * RFC 3010 has a complex implmentation description of processing a | 801 | * Section 14.2.34 of RFC 3530 (under the heading "IMPLEMENTATION") has |
| 861 | * SETCLIENTID_CONFIRM request consisting of 4 bullets describing | 802 | * a description of SETCLIENTID_CONFIRM request processing consisting of 4 |
| 862 | * processing on a DRC miss, labeled as CASE1 - CASE4 below. | 803 | * bullets, labeled as CASE1 - CASE4 below. |
| 863 | * | ||
| 864 | * NOTE: callback information will be processed here in a future patch | ||
| 865 | */ | 804 | */ |
| 866 | __be32 | 805 | __be32 |
| 867 | nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | 806 | nfsd4_setclientid_confirm(struct svc_rqst *rqstp, |
| @@ -892,16 +831,16 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
| 892 | if (unconf && unconf->cl_addr != sin->sin_addr.s_addr) | 831 | if (unconf && unconf->cl_addr != sin->sin_addr.s_addr) |
| 893 | goto out; | 832 | goto out; |
| 894 | 833 | ||
| 895 | if ((conf && unconf) && | 834 | /* |
| 896 | (same_verf(&unconf->cl_confirm, &confirm)) && | 835 | * section 14.2.34 of RFC 3530 has a description of |
| 897 | (same_verf(&conf->cl_verifier, &unconf->cl_verifier)) && | 836 | * SETCLIENTID_CONFIRM request processing consisting |
| 898 | (same_name(conf->cl_recdir,unconf->cl_recdir)) && | 837 | * of 4 bullet points, labeled as CASE1 - CASE4 below. |
| 899 | (!same_verf(&conf->cl_confirm, &unconf->cl_confirm))) { | 838 | */ |
| 900 | /* CASE 1: | 839 | if (conf && unconf && same_verf(&confirm, &unconf->cl_confirm)) { |
| 901 | * unconf record that matches input clientid and input confirm. | 840 | /* |
| 902 | * conf record that matches input clientid. | 841 | * RFC 3530 14.2.34 CASE 1: |
| 903 | * conf and unconf records match names, verifiers | 842 | * callback update |
| 904 | */ | 843 | */ |
| 905 | if (!same_creds(&conf->cl_cred, &unconf->cl_cred)) | 844 | if (!same_creds(&conf->cl_cred, &unconf->cl_cred)) |
| 906 | status = nfserr_clid_inuse; | 845 | status = nfserr_clid_inuse; |
| 907 | else { | 846 | else { |
| @@ -914,15 +853,11 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
| 914 | status = nfs_ok; | 853 | status = nfs_ok; |
| 915 | 854 | ||
| 916 | } | 855 | } |
| 917 | } else if ((conf && !unconf) || | 856 | } else if (conf && !unconf) { |
| 918 | ((conf && unconf) && | 857 | /* |
| 919 | (!same_verf(&conf->cl_verifier, &unconf->cl_verifier) || | 858 | * RFC 3530 14.2.34 CASE 2: |
| 920 | !same_name(conf->cl_recdir, unconf->cl_recdir)))) { | 859 | * probable retransmitted request; play it safe and |
| 921 | /* CASE 2: | 860 | * do nothing. |
| 922 | * conf record that matches input clientid. | ||
| 923 | * if unconf record matches input clientid, then | ||
| 924 | * unconf->cl_name or unconf->cl_verifier don't match the | ||
| 925 | * conf record. | ||
| 926 | */ | 861 | */ |
| 927 | if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) | 862 | if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) |
| 928 | status = nfserr_clid_inuse; | 863 | status = nfserr_clid_inuse; |
| @@ -930,10 +865,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
| 930 | status = nfs_ok; | 865 | status = nfs_ok; |
| 931 | } else if (!conf && unconf | 866 | } else if (!conf && unconf |
| 932 | && same_verf(&unconf->cl_confirm, &confirm)) { | 867 | && same_verf(&unconf->cl_confirm, &confirm)) { |
| 933 | /* CASE 3: | 868 | /* |
| 934 | * conf record not found. | 869 | * RFC 3530 14.2.34 CASE 3: |
| 935 | * unconf record found. | 870 | * Normal case; new or rebooted client: |
| 936 | * unconf->cl_confirm matches input confirm | ||
| 937 | */ | 871 | */ |
| 938 | if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred)) { | 872 | if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred)) { |
| 939 | status = nfserr_clid_inuse; | 873 | status = nfserr_clid_inuse; |
| @@ -948,16 +882,15 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
| 948 | } | 882 | } |
| 949 | move_to_confirmed(unconf); | 883 | move_to_confirmed(unconf); |
| 950 | conf = unconf; | 884 | conf = unconf; |
| 885 | nfsd4_probe_callback(conf); | ||
| 951 | status = nfs_ok; | 886 | status = nfs_ok; |
| 952 | } | 887 | } |
| 953 | } else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm))) | 888 | } else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm))) |
| 954 | && (!unconf || (unconf && !same_verf(&unconf->cl_confirm, | 889 | && (!unconf || (unconf && !same_verf(&unconf->cl_confirm, |
| 955 | &confirm)))) { | 890 | &confirm)))) { |
| 956 | /* CASE 4: | 891 | /* |
| 957 | * conf record not found, or if conf, conf->cl_confirm does not | 892 | * RFC 3530 14.2.34 CASE 4: |
| 958 | * match input confirm. | 893 | * Client probably hasn't noticed that we rebooted yet. |
| 959 | * unconf record not found, or if unconf, unconf->cl_confirm | ||
| 960 | * does not match input confirm. | ||
| 961 | */ | 894 | */ |
| 962 | status = nfserr_stale_clientid; | 895 | status = nfserr_stale_clientid; |
| 963 | } else { | 896 | } else { |
| @@ -965,8 +898,6 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
| 965 | status = nfserr_clid_inuse; | 898 | status = nfserr_clid_inuse; |
| 966 | } | 899 | } |
| 967 | out: | 900 | out: |
| 968 | if (!status) | ||
| 969 | nfsd4_probe_callback(conf); | ||
| 970 | nfs4_unlock_state(); | 901 | nfs4_unlock_state(); |
| 971 | return status; | 902 | return status; |
| 972 | } | 903 | } |
| @@ -1226,14 +1157,19 @@ find_file(struct inode *ino) | |||
| 1226 | return NULL; | 1157 | return NULL; |
| 1227 | } | 1158 | } |
| 1228 | 1159 | ||
| 1229 | static int access_valid(u32 x) | 1160 | static inline int access_valid(u32 x) |
| 1230 | { | 1161 | { |
| 1231 | return (x > 0 && x < 4); | 1162 | if (x < NFS4_SHARE_ACCESS_READ) |
| 1163 | return 0; | ||
| 1164 | if (x > NFS4_SHARE_ACCESS_BOTH) | ||
| 1165 | return 0; | ||
| 1166 | return 1; | ||
| 1232 | } | 1167 | } |
| 1233 | 1168 | ||
| 1234 | static int deny_valid(u32 x) | 1169 | static inline int deny_valid(u32 x) |
| 1235 | { | 1170 | { |
| 1236 | return (x >= 0 && x < 5); | 1171 | /* Note: unlike access bits, deny bits may be zero. */ |
| 1172 | return x <= NFS4_SHARE_DENY_BOTH; | ||
| 1237 | } | 1173 | } |
| 1238 | 1174 | ||
| 1239 | static void | 1175 | static void |
| @@ -2162,8 +2098,10 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei | |||
| 2162 | goto check_replay; | 2098 | goto check_replay; |
| 2163 | } | 2099 | } |
| 2164 | 2100 | ||
| 2101 | *stpp = stp; | ||
| 2102 | *sopp = sop = stp->st_stateowner; | ||
| 2103 | |||
| 2165 | if (lock) { | 2104 | if (lock) { |
| 2166 | struct nfs4_stateowner *sop = stp->st_stateowner; | ||
| 2167 | clientid_t *lockclid = &lock->v.new.clientid; | 2105 | clientid_t *lockclid = &lock->v.new.clientid; |
| 2168 | struct nfs4_client *clp = sop->so_client; | 2106 | struct nfs4_client *clp = sop->so_client; |
| 2169 | int lkflg = 0; | 2107 | int lkflg = 0; |
| @@ -2193,9 +2131,6 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei | |||
| 2193 | return nfserr_bad_stateid; | 2131 | return nfserr_bad_stateid; |
| 2194 | } | 2132 | } |
| 2195 | 2133 | ||
| 2196 | *stpp = stp; | ||
| 2197 | *sopp = sop = stp->st_stateowner; | ||
| 2198 | |||
| 2199 | /* | 2134 | /* |
| 2200 | * We now validate the seqid and stateid generation numbers. | 2135 | * We now validate the seqid and stateid generation numbers. |
| 2201 | * For the moment, we ignore the possibility of | 2136 | * For the moment, we ignore the possibility of |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 57333944af7f..b0592e7c378d 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
| @@ -148,12 +148,12 @@ xdr_error: \ | |||
| 148 | } \ | 148 | } \ |
| 149 | } while (0) | 149 | } while (0) |
| 150 | 150 | ||
| 151 | static __be32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes) | 151 | static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) |
| 152 | { | 152 | { |
| 153 | /* We want more bytes than seem to be available. | 153 | /* We want more bytes than seem to be available. |
| 154 | * Maybe we need a new page, maybe we have just run out | 154 | * Maybe we need a new page, maybe we have just run out |
| 155 | */ | 155 | */ |
| 156 | int avail = (char*)argp->end - (char*)argp->p; | 156 | unsigned int avail = (char *)argp->end - (char *)argp->p; |
| 157 | __be32 *p; | 157 | __be32 *p; |
| 158 | if (avail + argp->pagelen < nbytes) | 158 | if (avail + argp->pagelen < nbytes) |
| 159 | return NULL; | 159 | return NULL; |
| @@ -169,6 +169,11 @@ static __be32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes) | |||
| 169 | return NULL; | 169 | return NULL; |
| 170 | 170 | ||
| 171 | } | 171 | } |
| 172 | /* | ||
| 173 | * The following memcpy is safe because read_buf is always | ||
| 174 | * called with nbytes > avail, and the two cases above both | ||
| 175 | * guarantee p points to at least nbytes bytes. | ||
| 176 | */ | ||
| 172 | memcpy(p, argp->p, avail); | 177 | memcpy(p, argp->p, avail); |
| 173 | /* step to next page */ | 178 | /* step to next page */ |
| 174 | argp->p = page_address(argp->pagelist[0]); | 179 | argp->p = page_address(argp->pagelist[0]); |
| @@ -1448,7 +1453,7 @@ static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err) | |||
| 1448 | __be32 | 1453 | __be32 |
| 1449 | nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | 1454 | nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, |
| 1450 | struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval, | 1455 | struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval, |
| 1451 | struct svc_rqst *rqstp) | 1456 | struct svc_rqst *rqstp, int ignore_crossmnt) |
| 1452 | { | 1457 | { |
| 1453 | u32 bmval0 = bmval[0]; | 1458 | u32 bmval0 = bmval[0]; |
| 1454 | u32 bmval1 = bmval[1]; | 1459 | u32 bmval1 = bmval[1]; |
| @@ -1828,7 +1833,12 @@ out_acl: | |||
| 1828 | if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { | 1833 | if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { |
| 1829 | if ((buflen -= 8) < 0) | 1834 | if ((buflen -= 8) < 0) |
| 1830 | goto out_resource; | 1835 | goto out_resource; |
| 1831 | if (exp->ex_mnt->mnt_root->d_inode == dentry->d_inode) { | 1836 | /* |
| 1837 | * Get parent's attributes if not ignoring crossmount | ||
| 1838 | * and this is the root of a cross-mounted filesystem. | ||
| 1839 | */ | ||
| 1840 | if (ignore_crossmnt == 0 && | ||
| 1841 | exp->ex_mnt->mnt_root->d_inode == dentry->d_inode) { | ||
| 1832 | err = vfs_getattr(exp->ex_mnt->mnt_parent, | 1842 | err = vfs_getattr(exp->ex_mnt->mnt_parent, |
| 1833 | exp->ex_mnt->mnt_mountpoint, &stat); | 1843 | exp->ex_mnt->mnt_mountpoint, &stat); |
| 1834 | if (err) | 1844 | if (err) |
| @@ -1864,13 +1874,25 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, | |||
| 1864 | struct svc_export *exp = cd->rd_fhp->fh_export; | 1874 | struct svc_export *exp = cd->rd_fhp->fh_export; |
| 1865 | struct dentry *dentry; | 1875 | struct dentry *dentry; |
| 1866 | __be32 nfserr; | 1876 | __be32 nfserr; |
| 1877 | int ignore_crossmnt = 0; | ||
| 1867 | 1878 | ||
| 1868 | dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen); | 1879 | dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen); |
| 1869 | if (IS_ERR(dentry)) | 1880 | if (IS_ERR(dentry)) |
| 1870 | return nfserrno(PTR_ERR(dentry)); | 1881 | return nfserrno(PTR_ERR(dentry)); |
| 1871 | 1882 | ||
| 1872 | exp_get(exp); | 1883 | exp_get(exp); |
| 1873 | if (d_mountpoint(dentry)) { | 1884 | /* |
| 1885 | * In the case of a mountpoint, the client may be asking for | ||
| 1886 | * attributes that are only properties of the underlying filesystem | ||
| 1887 | * as opposed to the cross-mounted file system. In such a case, | ||
| 1888 | * we will not follow the cross mount and will fill the attribtutes | ||
| 1889 | * directly from the mountpoint dentry. | ||
| 1890 | */ | ||
| 1891 | if (d_mountpoint(dentry) && | ||
| 1892 | (cd->rd_bmval[0] & ~FATTR4_WORD0_RDATTR_ERROR) == 0 && | ||
| 1893 | (cd->rd_bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID) == 0) | ||
| 1894 | ignore_crossmnt = 1; | ||
| 1895 | else if (d_mountpoint(dentry)) { | ||
| 1874 | int err; | 1896 | int err; |
| 1875 | 1897 | ||
| 1876 | /* | 1898 | /* |
| @@ -1889,7 +1911,7 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, | |||
| 1889 | 1911 | ||
| 1890 | } | 1912 | } |
| 1891 | nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval, | 1913 | nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval, |
| 1892 | cd->rd_rqstp); | 1914 | cd->rd_rqstp, ignore_crossmnt); |
| 1893 | out_put: | 1915 | out_put: |
| 1894 | dput(dentry); | 1916 | dput(dentry); |
| 1895 | exp_put(exp); | 1917 | exp_put(exp); |
| @@ -2043,7 +2065,7 @@ nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4 | |||
| 2043 | buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2); | 2065 | buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2); |
| 2044 | nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry, | 2066 | nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry, |
| 2045 | resp->p, &buflen, getattr->ga_bmval, | 2067 | resp->p, &buflen, getattr->ga_bmval, |
| 2046 | resp->rqstp); | 2068 | resp->rqstp, 0); |
| 2047 | if (!nfserr) | 2069 | if (!nfserr) |
| 2048 | resp->p += buflen; | 2070 | resp->p += buflen; |
| 2049 | return nfserr; | 2071 | return nfserr; |
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index 578f2c9d56be..5bfc2ac60d54 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c | |||
| @@ -44,17 +44,17 @@ static int nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec); | |||
| 44 | */ | 44 | */ |
| 45 | static DEFINE_SPINLOCK(cache_lock); | 45 | static DEFINE_SPINLOCK(cache_lock); |
| 46 | 46 | ||
| 47 | void | 47 | int nfsd_reply_cache_init(void) |
| 48 | nfsd_cache_init(void) | ||
| 49 | { | 48 | { |
| 50 | struct svc_cacherep *rp; | 49 | struct svc_cacherep *rp; |
| 51 | int i; | 50 | int i; |
| 52 | 51 | ||
| 53 | INIT_LIST_HEAD(&lru_head); | 52 | INIT_LIST_HEAD(&lru_head); |
| 54 | i = CACHESIZE; | 53 | i = CACHESIZE; |
| 55 | while(i) { | 54 | while (i) { |
| 56 | rp = kmalloc(sizeof(*rp), GFP_KERNEL); | 55 | rp = kmalloc(sizeof(*rp), GFP_KERNEL); |
| 57 | if (!rp) break; | 56 | if (!rp) |
| 57 | goto out_nomem; | ||
| 58 | list_add(&rp->c_lru, &lru_head); | 58 | list_add(&rp->c_lru, &lru_head); |
| 59 | rp->c_state = RC_UNUSED; | 59 | rp->c_state = RC_UNUSED; |
| 60 | rp->c_type = RC_NOCACHE; | 60 | rp->c_type = RC_NOCACHE; |
| @@ -62,23 +62,19 @@ nfsd_cache_init(void) | |||
| 62 | i--; | 62 | i--; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | if (i) | ||
| 66 | printk (KERN_ERR "nfsd: cannot allocate all %d cache entries, only got %d\n", | ||
| 67 | CACHESIZE, CACHESIZE-i); | ||
| 68 | |||
| 69 | hash_list = kcalloc (HASHSIZE, sizeof(struct hlist_head), GFP_KERNEL); | 65 | hash_list = kcalloc (HASHSIZE, sizeof(struct hlist_head), GFP_KERNEL); |
| 70 | if (!hash_list) { | 66 | if (!hash_list) |
| 71 | nfsd_cache_shutdown(); | 67 | goto out_nomem; |
| 72 | printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for hash list\n", | ||
| 73 | HASHSIZE * sizeof(struct hlist_head)); | ||
| 74 | return; | ||
| 75 | } | ||
| 76 | 68 | ||
| 77 | cache_disabled = 0; | 69 | cache_disabled = 0; |
| 70 | return 0; | ||
| 71 | out_nomem: | ||
| 72 | printk(KERN_ERR "nfsd: failed to allocate reply cache\n"); | ||
| 73 | nfsd_reply_cache_shutdown(); | ||
| 74 | return -ENOMEM; | ||
| 78 | } | 75 | } |
| 79 | 76 | ||
| 80 | void | 77 | void nfsd_reply_cache_shutdown(void) |
| 81 | nfsd_cache_shutdown(void) | ||
| 82 | { | 78 | { |
| 83 | struct svc_cacherep *rp; | 79 | struct svc_cacherep *rp; |
| 84 | 80 | ||
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 77dc9893b7ba..8516137cdbb0 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
| @@ -304,6 +304,9 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size) | |||
| 304 | struct auth_domain *dom; | 304 | struct auth_domain *dom; |
| 305 | struct knfsd_fh fh; | 305 | struct knfsd_fh fh; |
| 306 | 306 | ||
| 307 | if (size == 0) | ||
| 308 | return -EINVAL; | ||
| 309 | |||
| 307 | if (buf[size-1] != '\n') | 310 | if (buf[size-1] != '\n') |
| 308 | return -EINVAL; | 311 | return -EINVAL; |
| 309 | buf[size-1] = 0; | 312 | buf[size-1] = 0; |
| @@ -503,7 +506,7 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size) | |||
| 503 | int len = 0; | 506 | int len = 0; |
| 504 | lock_kernel(); | 507 | lock_kernel(); |
| 505 | if (nfsd_serv) | 508 | if (nfsd_serv) |
| 506 | len = svc_sock_names(buf, nfsd_serv, NULL); | 509 | len = svc_xprt_names(nfsd_serv, buf, 0); |
| 507 | unlock_kernel(); | 510 | unlock_kernel(); |
| 508 | return len; | 511 | return len; |
| 509 | } | 512 | } |
| @@ -540,7 +543,7 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size) | |||
| 540 | } | 543 | } |
| 541 | return err < 0 ? err : 0; | 544 | return err < 0 ? err : 0; |
| 542 | } | 545 | } |
| 543 | if (buf[0] == '-') { | 546 | if (buf[0] == '-' && isdigit(buf[1])) { |
| 544 | char *toclose = kstrdup(buf+1, GFP_KERNEL); | 547 | char *toclose = kstrdup(buf+1, GFP_KERNEL); |
| 545 | int len = 0; | 548 | int len = 0; |
| 546 | if (!toclose) | 549 | if (!toclose) |
| @@ -554,6 +557,53 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size) | |||
| 554 | kfree(toclose); | 557 | kfree(toclose); |
| 555 | return len; | 558 | return len; |
| 556 | } | 559 | } |
| 560 | /* | ||
| 561 | * Add a transport listener by writing it's transport name | ||
| 562 | */ | ||
| 563 | if (isalpha(buf[0])) { | ||
| 564 | int err; | ||
| 565 | char transport[16]; | ||
| 566 | int port; | ||
| 567 | if (sscanf(buf, "%15s %4d", transport, &port) == 2) { | ||
| 568 | err = nfsd_create_serv(); | ||
| 569 | if (!err) { | ||
| 570 | err = svc_create_xprt(nfsd_serv, | ||
| 571 | transport, port, | ||
| 572 | SVC_SOCK_ANONYMOUS); | ||
| 573 | if (err == -ENOENT) | ||
| 574 | /* Give a reasonable perror msg for | ||
| 575 | * bad transport string */ | ||
| 576 | err = -EPROTONOSUPPORT; | ||
| 577 | } | ||
| 578 | return err < 0 ? err : 0; | ||
| 579 | } | ||
| 580 | } | ||
| 581 | /* | ||
| 582 | * Remove a transport by writing it's transport name and port number | ||
| 583 | */ | ||
| 584 | if (buf[0] == '-' && isalpha(buf[1])) { | ||
| 585 | struct svc_xprt *xprt; | ||
| 586 | int err = -EINVAL; | ||
| 587 | char transport[16]; | ||
| 588 | int port; | ||
| 589 | if (sscanf(&buf[1], "%15s %4d", transport, &port) == 2) { | ||
| 590 | if (port == 0) | ||
| 591 | return -EINVAL; | ||
| 592 | lock_kernel(); | ||
| 593 | if (nfsd_serv) { | ||
| 594 | xprt = svc_find_xprt(nfsd_serv, transport, | ||
| 595 | AF_UNSPEC, port); | ||
| 596 | if (xprt) { | ||
| 597 | svc_close_xprt(xprt); | ||
| 598 | svc_xprt_put(xprt); | ||
| 599 | err = 0; | ||
| 600 | } else | ||
| 601 | err = -ENOTCONN; | ||
| 602 | } | ||
| 603 | unlock_kernel(); | ||
| 604 | return err < 0 ? err : 0; | ||
| 605 | } | ||
| 606 | } | ||
| 557 | return -EINVAL; | 607 | return -EINVAL; |
| 558 | } | 608 | } |
| 559 | 609 | ||
| @@ -616,7 +666,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) | |||
| 616 | char *recdir; | 666 | char *recdir; |
| 617 | int len, status; | 667 | int len, status; |
| 618 | 668 | ||
| 619 | if (size > PATH_MAX || buf[size-1] != '\n') | 669 | if (size == 0 || size > PATH_MAX || buf[size-1] != '\n') |
| 620 | return -EINVAL; | 670 | return -EINVAL; |
| 621 | buf[size-1] = 0; | 671 | buf[size-1] = 0; |
| 622 | 672 | ||
| @@ -674,6 +724,27 @@ static struct file_system_type nfsd_fs_type = { | |||
| 674 | .kill_sb = kill_litter_super, | 724 | .kill_sb = kill_litter_super, |
| 675 | }; | 725 | }; |
| 676 | 726 | ||
| 727 | #ifdef CONFIG_PROC_FS | ||
| 728 | static int create_proc_exports_entry(void) | ||
| 729 | { | ||
| 730 | struct proc_dir_entry *entry; | ||
| 731 | |||
| 732 | entry = proc_mkdir("fs/nfs", NULL); | ||
| 733 | if (!entry) | ||
| 734 | return -ENOMEM; | ||
| 735 | entry = create_proc_entry("fs/nfs/exports", 0, NULL); | ||
| 736 | if (!entry) | ||
| 737 | return -ENOMEM; | ||
| 738 | entry->proc_fops = &exports_operations; | ||
| 739 | return 0; | ||
| 740 | } | ||
| 741 | #else /* CONFIG_PROC_FS */ | ||
| 742 | static int create_proc_exports_entry(void) | ||
| 743 | { | ||
| 744 | return 0; | ||
| 745 | } | ||
| 746 | #endif | ||
| 747 | |||
| 677 | static int __init init_nfsd(void) | 748 | static int __init init_nfsd(void) |
| 678 | { | 749 | { |
| 679 | int retval; | 750 | int retval; |
| @@ -683,32 +754,43 @@ static int __init init_nfsd(void) | |||
| 683 | if (retval) | 754 | if (retval) |
| 684 | return retval; | 755 | return retval; |
| 685 | nfsd_stat_init(); /* Statistics */ | 756 | nfsd_stat_init(); /* Statistics */ |
| 686 | nfsd_cache_init(); /* RPC reply cache */ | 757 | retval = nfsd_reply_cache_init(); |
| 687 | nfsd_export_init(); /* Exports table */ | 758 | if (retval) |
| 759 | goto out_free_stat; | ||
| 760 | retval = nfsd_export_init(); | ||
| 761 | if (retval) | ||
| 762 | goto out_free_cache; | ||
| 688 | nfsd_lockd_init(); /* lockd->nfsd callbacks */ | 763 | nfsd_lockd_init(); /* lockd->nfsd callbacks */ |
| 689 | nfsd_idmap_init(); /* Name to ID mapping */ | 764 | retval = nfsd_idmap_init(); |
| 690 | if (proc_mkdir("fs/nfs", NULL)) { | 765 | if (retval) |
| 691 | struct proc_dir_entry *entry; | 766 | goto out_free_lockd; |
| 692 | entry = create_proc_entry("fs/nfs/exports", 0, NULL); | 767 | retval = create_proc_exports_entry(); |
| 693 | if (entry) | 768 | if (retval) |
| 694 | entry->proc_fops = &exports_operations; | 769 | goto out_free_idmap; |
| 695 | } | ||
| 696 | retval = register_filesystem(&nfsd_fs_type); | 770 | retval = register_filesystem(&nfsd_fs_type); |
| 697 | if (retval) { | 771 | if (retval) |
| 698 | nfsd_export_shutdown(); | 772 | goto out_free_all; |
| 699 | nfsd_cache_shutdown(); | 773 | return 0; |
| 700 | remove_proc_entry("fs/nfs/exports", NULL); | 774 | out_free_all: |
| 701 | remove_proc_entry("fs/nfs", NULL); | 775 | remove_proc_entry("fs/nfs/exports", NULL); |
| 702 | nfsd_stat_shutdown(); | 776 | remove_proc_entry("fs/nfs", NULL); |
| 703 | nfsd_lockd_shutdown(); | 777 | out_free_idmap: |
| 704 | } | 778 | nfsd_idmap_shutdown(); |
| 779 | out_free_lockd: | ||
| 780 | nfsd_lockd_shutdown(); | ||
| 781 | nfsd_export_shutdown(); | ||
| 782 | out_free_cache: | ||
| 783 | nfsd_reply_cache_shutdown(); | ||
| 784 | out_free_stat: | ||
| 785 | nfsd_stat_shutdown(); | ||
| 786 | nfsd4_free_slabs(); | ||
| 705 | return retval; | 787 | return retval; |
| 706 | } | 788 | } |
| 707 | 789 | ||
| 708 | static void __exit exit_nfsd(void) | 790 | static void __exit exit_nfsd(void) |
| 709 | { | 791 | { |
| 710 | nfsd_export_shutdown(); | 792 | nfsd_export_shutdown(); |
| 711 | nfsd_cache_shutdown(); | 793 | nfsd_reply_cache_shutdown(); |
| 712 | remove_proc_entry("fs/nfs/exports", NULL); | 794 | remove_proc_entry("fs/nfs/exports", NULL); |
| 713 | remove_proc_entry("fs/nfs", NULL); | 795 | remove_proc_entry("fs/nfs", NULL); |
| 714 | nfsd_stat_shutdown(); | 796 | nfsd_stat_shutdown(); |
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 468f17a78441..8fbd2dc08a92 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/sunrpc/svc.h> | 22 | #include <linux/sunrpc/svc.h> |
| 23 | #include <linux/sunrpc/svcauth_gss.h> | 23 | #include <linux/sunrpc/svcauth_gss.h> |
| 24 | #include <linux/nfsd/nfsd.h> | 24 | #include <linux/nfsd/nfsd.h> |
| 25 | #include "auth.h" | ||
| 25 | 26 | ||
| 26 | #define NFSDDBG_FACILITY NFSDDBG_FH | 27 | #define NFSDDBG_FACILITY NFSDDBG_FH |
| 27 | 28 | ||
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 1190aeaa92be..9647b0f7bc0c 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
| @@ -155,8 +155,8 @@ static int killsig; /* signal that was used to kill last nfsd */ | |||
| 155 | static void nfsd_last_thread(struct svc_serv *serv) | 155 | static void nfsd_last_thread(struct svc_serv *serv) |
| 156 | { | 156 | { |
| 157 | /* When last nfsd thread exits we need to do some clean-up */ | 157 | /* When last nfsd thread exits we need to do some clean-up */ |
| 158 | struct svc_sock *svsk; | 158 | struct svc_xprt *xprt; |
| 159 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) | 159 | list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) |
| 160 | lockd_down(); | 160 | lockd_down(); |
| 161 | nfsd_serv = NULL; | 161 | nfsd_serv = NULL; |
| 162 | nfsd_racache_shutdown(); | 162 | nfsd_racache_shutdown(); |
| @@ -236,7 +236,7 @@ static int nfsd_init_socks(int port) | |||
| 236 | 236 | ||
| 237 | error = lockd_up(IPPROTO_UDP); | 237 | error = lockd_up(IPPROTO_UDP); |
| 238 | if (error >= 0) { | 238 | if (error >= 0) { |
| 239 | error = svc_makesock(nfsd_serv, IPPROTO_UDP, port, | 239 | error = svc_create_xprt(nfsd_serv, "udp", port, |
| 240 | SVC_SOCK_DEFAULTS); | 240 | SVC_SOCK_DEFAULTS); |
| 241 | if (error < 0) | 241 | if (error < 0) |
| 242 | lockd_down(); | 242 | lockd_down(); |
| @@ -247,7 +247,7 @@ static int nfsd_init_socks(int port) | |||
| 247 | #ifdef CONFIG_NFSD_TCP | 247 | #ifdef CONFIG_NFSD_TCP |
| 248 | error = lockd_up(IPPROTO_TCP); | 248 | error = lockd_up(IPPROTO_TCP); |
| 249 | if (error >= 0) { | 249 | if (error >= 0) { |
| 250 | error = svc_makesock(nfsd_serv, IPPROTO_TCP, port, | 250 | error = svc_create_xprt(nfsd_serv, "tcp", port, |
| 251 | SVC_SOCK_DEFAULTS); | 251 | SVC_SOCK_DEFAULTS); |
| 252 | if (error < 0) | 252 | if (error < 0) |
| 253 | lockd_down(); | 253 | lockd_down(); |
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index b86e3658a0af..61ad61743d94 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/nfsd/nfsd.h> | 15 | #include <linux/nfsd/nfsd.h> |
| 16 | #include <linux/nfsd/xdr.h> | 16 | #include <linux/nfsd/xdr.h> |
| 17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
| 18 | #include "auth.h" | ||
| 18 | 19 | ||
| 19 | #define NFSDDBG_FACILITY NFSDDBG_XDR | 20 | #define NFSDDBG_FACILITY NFSDDBG_XDR |
| 20 | 21 | ||
| @@ -62,10 +63,10 @@ encode_fh(__be32 *p, struct svc_fh *fhp) | |||
| 62 | * no slashes or null bytes. | 63 | * no slashes or null bytes. |
| 63 | */ | 64 | */ |
| 64 | static __be32 * | 65 | static __be32 * |
| 65 | decode_filename(__be32 *p, char **namp, int *lenp) | 66 | decode_filename(__be32 *p, char **namp, unsigned int *lenp) |
| 66 | { | 67 | { |
| 67 | char *name; | 68 | char *name; |
| 68 | int i; | 69 | unsigned int i; |
| 69 | 70 | ||
| 70 | if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXNAMLEN)) != NULL) { | 71 | if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXNAMLEN)) != NULL) { |
| 71 | for (i = 0, name = *namp; i < *lenp; i++, name++) { | 72 | for (i = 0, name = *namp; i < *lenp; i++, name++) { |
| @@ -78,10 +79,10 @@ decode_filename(__be32 *p, char **namp, int *lenp) | |||
| 78 | } | 79 | } |
| 79 | 80 | ||
| 80 | static __be32 * | 81 | static __be32 * |
| 81 | decode_pathname(__be32 *p, char **namp, int *lenp) | 82 | decode_pathname(__be32 *p, char **namp, unsigned int *lenp) |
| 82 | { | 83 | { |
| 83 | char *name; | 84 | char *name; |
| 84 | int i; | 85 | unsigned int i; |
| 85 | 86 | ||
| 86 | if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXPATHLEN)) != NULL) { | 87 | if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXPATHLEN)) != NULL) { |
| 87 | for (i = 0, name = *namp; i < *lenp; i++, name++) { | 88 | for (i = 0, name = *namp; i < *lenp; i++, name++) { |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index d0199189924c..cc75e4fcd02b 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -132,7 +132,7 @@ out: | |||
| 132 | 132 | ||
| 133 | __be32 | 133 | __be32 |
| 134 | nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, | 134 | nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, |
| 135 | const char *name, int len, | 135 | const char *name, unsigned int len, |
| 136 | struct svc_export **exp_ret, struct dentry **dentry_ret) | 136 | struct svc_export **exp_ret, struct dentry **dentry_ret) |
| 137 | { | 137 | { |
| 138 | struct svc_export *exp; | 138 | struct svc_export *exp; |
| @@ -226,7 +226,7 @@ out_nfserr: | |||
| 226 | */ | 226 | */ |
| 227 | __be32 | 227 | __be32 |
| 228 | nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, | 228 | nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, |
| 229 | int len, struct svc_fh *resfh) | 229 | unsigned int len, struct svc_fh *resfh) |
| 230 | { | 230 | { |
| 231 | struct svc_export *exp; | 231 | struct svc_export *exp; |
| 232 | struct dentry *dentry; | 232 | struct dentry *dentry; |
| @@ -1151,6 +1151,26 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1151 | } | 1151 | } |
| 1152 | #endif /* CONFIG_NFSD_V3 */ | 1152 | #endif /* CONFIG_NFSD_V3 */ |
| 1153 | 1153 | ||
| 1154 | __be32 | ||
| 1155 | nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *resfhp, | ||
| 1156 | struct iattr *iap) | ||
| 1157 | { | ||
| 1158 | /* | ||
| 1159 | * Mode has already been set earlier in create: | ||
| 1160 | */ | ||
| 1161 | iap->ia_valid &= ~ATTR_MODE; | ||
| 1162 | /* | ||
| 1163 | * Setting uid/gid works only for root. Irix appears to | ||
| 1164 | * send along the gid on create when it tries to implement | ||
| 1165 | * setgid directories via NFS: | ||
| 1166 | */ | ||
| 1167 | if (current->fsuid != 0) | ||
| 1168 | iap->ia_valid &= ~(ATTR_UID|ATTR_GID); | ||
| 1169 | if (iap->ia_valid) | ||
| 1170 | return nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); | ||
| 1171 | return 0; | ||
| 1172 | } | ||
| 1173 | |||
| 1154 | /* | 1174 | /* |
| 1155 | * Create a file (regular, directory, device, fifo); UNIX sockets | 1175 | * Create a file (regular, directory, device, fifo); UNIX sockets |
| 1156 | * not yet implemented. | 1176 | * not yet implemented. |
| @@ -1167,6 +1187,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1167 | struct dentry *dentry, *dchild = NULL; | 1187 | struct dentry *dentry, *dchild = NULL; |
| 1168 | struct inode *dirp; | 1188 | struct inode *dirp; |
| 1169 | __be32 err; | 1189 | __be32 err; |
| 1190 | __be32 err2; | ||
| 1170 | int host_err; | 1191 | int host_err; |
| 1171 | 1192 | ||
| 1172 | err = nfserr_perm; | 1193 | err = nfserr_perm; |
| @@ -1257,16 +1278,9 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1257 | } | 1278 | } |
| 1258 | 1279 | ||
| 1259 | 1280 | ||
| 1260 | /* Set file attributes. Mode has already been set and | 1281 | err2 = nfsd_create_setattr(rqstp, resfhp, iap); |
| 1261 | * setting uid/gid works only for root. Irix appears to | 1282 | if (err2) |
| 1262 | * send along the gid when it tries to implement setgid | 1283 | err = err2; |
| 1263 | * directories via NFS. | ||
| 1264 | */ | ||
| 1265 | if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) { | ||
| 1266 | __be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); | ||
| 1267 | if (err2) | ||
| 1268 | err = err2; | ||
| 1269 | } | ||
| 1270 | /* | 1284 | /* |
| 1271 | * Update the file handle to get the new inode info. | 1285 | * Update the file handle to get the new inode info. |
| 1272 | */ | 1286 | */ |
| @@ -1295,6 +1309,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1295 | struct dentry *dentry, *dchild = NULL; | 1309 | struct dentry *dentry, *dchild = NULL; |
| 1296 | struct inode *dirp; | 1310 | struct inode *dirp; |
| 1297 | __be32 err; | 1311 | __be32 err; |
| 1312 | __be32 err2; | ||
| 1298 | int host_err; | 1313 | int host_err; |
| 1299 | __u32 v_mtime=0, v_atime=0; | 1314 | __u32 v_mtime=0, v_atime=0; |
| 1300 | 1315 | ||
| @@ -1399,16 +1414,10 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1399 | iap->ia_atime.tv_nsec = 0; | 1414 | iap->ia_atime.tv_nsec = 0; |
| 1400 | } | 1415 | } |
| 1401 | 1416 | ||
| 1402 | /* Set file attributes. | ||
| 1403 | * Irix appears to send along the gid when it tries to | ||
| 1404 | * implement setgid directories via NFS. Clear out all that cruft. | ||
| 1405 | */ | ||
| 1406 | set_attr: | 1417 | set_attr: |
| 1407 | if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) { | 1418 | err2 = nfsd_create_setattr(rqstp, resfhp, iap); |
| 1408 | __be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); | 1419 | if (err2) |
| 1409 | if (err2) | 1420 | err = err2; |
| 1410 | err = err2; | ||
| 1411 | } | ||
| 1412 | 1421 | ||
| 1413 | /* | 1422 | /* |
| 1414 | * Update the filehandle to get the new inode info. | 1423 | * Update the filehandle to get the new inode info. |
