diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-15 11:16:53 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-15 11:16:53 -0400 |
| commit | 37ca506adc395a028cd12760eca419dd0dc14b5c (patch) | |
| tree | bab6f2644ef6bda4df1518f7063852012b69f458 | |
| parent | b9090071a57185707c27b9d61b81bf941dbdf122 (diff) | |
| parent | a16e92edcd0a2846455a30823e1bac964e743baa (diff) | |
Merge branch 'nfs-server-stable' of git://linux-nfs.org/~bfields/linux
* 'nfs-server-stable' of git://linux-nfs.org/~bfields/linux:
knfsd: query filesystem for NFSv4 getattr of FATTR4_MAXNAME
knfsd: nfsv4 delegation recall should take reference on client
knfsd: don't shutdown callbacks until nfsv4 client is freed
knfsd: let nfsd manage timing out its own leases
knfsd: Add source address to sunrpc svc errors
knfsd: 64 bit ino support for NFS server
svcgss: move init code into separate function
knfsd: remove code duplication in nfsd4_setclientid()
nfsd warning fix
knfsd: fix callback rpc cred
knfsd: move nfsv4 slab creation/destruction to module init/exit
knfsd: spawn kernel thread to probe callback channel
knfsd: nfs4 name->id mapping not correctly parsing negative downcall
knfsd: demote some printk()s to dprintk()s
knfsd: cleanup of nfsd4 cmp_* functions
knfsd: delete code made redundant by map_new_errors
nfsd: fix horrible indentation in nfsd_setattr
nfsd: remove unused cache_for_each macro
nfsd: tone down inaccurate dprintk
| -rw-r--r-- | fs/nfsd/nfs3xdr.c | 59 | ||||
| -rw-r--r-- | fs/nfsd/nfs4callback.c | 89 | ||||
| -rw-r--r-- | fs/nfsd/nfs4idmap.c | 8 | ||||
| -rw-r--r-- | fs/nfsd/nfs4proc.c | 4 | ||||
| -rw-r--r-- | fs/nfsd/nfs4state.c | 200 | ||||
| -rw-r--r-- | fs/nfsd/nfs4xdr.c | 22 | ||||
| -rw-r--r-- | fs/nfsd/nfsctl.c | 7 | ||||
| -rw-r--r-- | fs/nfsd/nfssvc.c | 8 | ||||
| -rw-r--r-- | fs/nfsd/nfsxdr.c | 4 | ||||
| -rw-r--r-- | fs/nfsd/vfs.c | 43 | ||||
| -rw-r--r-- | include/linux/nfsd/nfsd.h | 18 | ||||
| -rw-r--r-- | include/linux/nfsd/nfsfh.h | 42 | ||||
| -rw-r--r-- | include/linux/nfsd/xdr4.h | 4 | ||||
| -rw-r--r-- | include/linux/sunrpc/cache.h | 10 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 144 | ||||
| -rw-r--r-- | net/sunrpc/svc.c | 40 |
16 files changed, 326 insertions, 376 deletions
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 10f6e7dcf633..2d116d2298f8 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c | |||
| @@ -174,9 +174,6 @@ static __be32 * | |||
| 174 | encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, | 174 | encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, |
| 175 | struct kstat *stat) | 175 | struct kstat *stat) |
| 176 | { | 176 | { |
| 177 | struct dentry *dentry = fhp->fh_dentry; | ||
| 178 | struct timespec time; | ||
| 179 | |||
| 180 | *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); | 177 | *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); |
| 181 | *p++ = htonl((u32) stat->mode); | 178 | *p++ = htonl((u32) stat->mode); |
| 182 | *p++ = htonl((u32) stat->nlink); | 179 | *p++ = htonl((u32) stat->nlink); |
| @@ -191,10 +188,9 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, | |||
| 191 | *p++ = htonl((u32) MAJOR(stat->rdev)); | 188 | *p++ = htonl((u32) MAJOR(stat->rdev)); |
| 192 | *p++ = htonl((u32) MINOR(stat->rdev)); | 189 | *p++ = htonl((u32) MINOR(stat->rdev)); |
| 193 | p = encode_fsid(p, fhp); | 190 | p = encode_fsid(p, fhp); |
| 194 | p = xdr_encode_hyper(p, (u64) stat->ino); | 191 | p = xdr_encode_hyper(p, stat->ino); |
| 195 | p = encode_time3(p, &stat->atime); | 192 | p = encode_time3(p, &stat->atime); |
| 196 | lease_get_mtime(dentry->d_inode, &time); | 193 | p = encode_time3(p, &stat->mtime); |
| 197 | p = encode_time3(p, &time); | ||
| 198 | p = encode_time3(p, &stat->ctime); | 194 | p = encode_time3(p, &stat->ctime); |
| 199 | 195 | ||
| 200 | return p; | 196 | return p; |
| @@ -203,31 +199,9 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, | |||
| 203 | static __be32 * | 199 | static __be32 * |
| 204 | encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) | 200 | encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) |
| 205 | { | 201 | { |
| 206 | struct inode *inode = fhp->fh_dentry->d_inode; | ||
| 207 | |||
| 208 | /* Attributes to follow */ | 202 | /* Attributes to follow */ |
| 209 | *p++ = xdr_one; | 203 | *p++ = xdr_one; |
| 210 | 204 | return encode_fattr3(rqstp, p, fhp, &fhp->fh_post_attr); | |
| 211 | *p++ = htonl(nfs3_ftypes[(fhp->fh_post_mode & S_IFMT) >> 12]); | ||
| 212 | *p++ = htonl((u32) fhp->fh_post_mode); | ||
| 213 | *p++ = htonl((u32) fhp->fh_post_nlink); | ||
| 214 | *p++ = htonl((u32) nfsd_ruid(rqstp, fhp->fh_post_uid)); | ||
| 215 | *p++ = htonl((u32) nfsd_rgid(rqstp, fhp->fh_post_gid)); | ||
| 216 | if (S_ISLNK(fhp->fh_post_mode) && fhp->fh_post_size > NFS3_MAXPATHLEN) { | ||
| 217 | p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN); | ||
| 218 | } else { | ||
| 219 | p = xdr_encode_hyper(p, (u64) fhp->fh_post_size); | ||
| 220 | } | ||
| 221 | p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9); | ||
| 222 | *p++ = fhp->fh_post_rdev[0]; | ||
| 223 | *p++ = fhp->fh_post_rdev[1]; | ||
| 224 | p = encode_fsid(p, fhp); | ||
| 225 | p = xdr_encode_hyper(p, (u64) inode->i_ino); | ||
| 226 | p = encode_time3(p, &fhp->fh_post_atime); | ||
| 227 | p = encode_time3(p, &fhp->fh_post_mtime); | ||
| 228 | p = encode_time3(p, &fhp->fh_post_ctime); | ||
| 229 | |||
| 230 | return p; | ||
| 231 | } | 205 | } |
| 232 | 206 | ||
| 233 | /* | 207 | /* |
| @@ -246,6 +220,7 @@ encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) | |||
| 246 | err = vfs_getattr(fhp->fh_export->ex_mnt, dentry, &stat); | 220 | err = vfs_getattr(fhp->fh_export->ex_mnt, dentry, &stat); |
| 247 | if (!err) { | 221 | if (!err) { |
| 248 | *p++ = xdr_one; /* attributes follow */ | 222 | *p++ = xdr_one; /* attributes follow */ |
| 223 | lease_get_mtime(dentry->d_inode, &stat.mtime); | ||
| 249 | return encode_fattr3(rqstp, p, fhp, &stat); | 224 | return encode_fattr3(rqstp, p, fhp, &stat); |
| 250 | } | 225 | } |
| 251 | } | 226 | } |
| @@ -284,6 +259,23 @@ encode_wcc_data(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) | |||
| 284 | return encode_post_op_attr(rqstp, p, fhp); | 259 | return encode_post_op_attr(rqstp, p, fhp); |
| 285 | } | 260 | } |
| 286 | 261 | ||
| 262 | /* | ||
| 263 | * Fill in the post_op attr for the wcc data | ||
| 264 | */ | ||
| 265 | void fill_post_wcc(struct svc_fh *fhp) | ||
| 266 | { | ||
| 267 | int err; | ||
| 268 | |||
| 269 | if (fhp->fh_post_saved) | ||
| 270 | printk("nfsd: inode locked twice during operation.\n"); | ||
| 271 | |||
| 272 | err = vfs_getattr(fhp->fh_export->ex_mnt, fhp->fh_dentry, | ||
| 273 | &fhp->fh_post_attr); | ||
| 274 | if (err) | ||
| 275 | fhp->fh_post_saved = 0; | ||
| 276 | else | ||
| 277 | fhp->fh_post_saved = 1; | ||
| 278 | } | ||
| 287 | 279 | ||
| 288 | /* | 280 | /* |
| 289 | * XDR decode functions | 281 | * XDR decode functions |
| @@ -643,8 +635,11 @@ int | |||
| 643 | nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p, | 635 | nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p, |
| 644 | struct nfsd3_attrstat *resp) | 636 | struct nfsd3_attrstat *resp) |
| 645 | { | 637 | { |
| 646 | if (resp->status == 0) | 638 | if (resp->status == 0) { |
| 639 | lease_get_mtime(resp->fh.fh_dentry->d_inode, | ||
| 640 | &resp->stat.mtime); | ||
| 647 | p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat); | 641 | p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat); |
| 642 | } | ||
| 648 | return xdr_ressize_check(rqstp, p); | 643 | return xdr_ressize_check(rqstp, p); |
| 649 | } | 644 | } |
| 650 | 645 | ||
| @@ -802,7 +797,7 @@ nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p, | |||
| 802 | 797 | ||
| 803 | static __be32 * | 798 | static __be32 * |
| 804 | encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, | 799 | encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, |
| 805 | int namlen, ino_t ino) | 800 | int namlen, u64 ino) |
| 806 | { | 801 | { |
| 807 | *p++ = xdr_one; /* mark entry present */ | 802 | *p++ = xdr_one; /* mark entry present */ |
| 808 | p = xdr_encode_hyper(p, ino); /* file id */ | 803 | p = xdr_encode_hyper(p, ino); /* file id */ |
| @@ -873,7 +868,7 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, | |||
| 873 | #define NFS3_ENTRYPLUS_BAGGAGE (1 + 21 + 1 + (NFS3_FHSIZE >> 2)) | 868 | #define NFS3_ENTRYPLUS_BAGGAGE (1 + 21 + 1 + (NFS3_FHSIZE >> 2)) |
| 874 | static int | 869 | static int |
| 875 | encode_entry(struct readdir_cd *ccd, const char *name, int namlen, | 870 | encode_entry(struct readdir_cd *ccd, const char *name, int namlen, |
| 876 | loff_t offset, ino_t ino, unsigned int d_type, int plus) | 871 | loff_t offset, u64 ino, unsigned int d_type, int plus) |
| 877 | { | 872 | { |
| 878 | struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres, | 873 | struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres, |
| 879 | common); | 874 | common); |
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 31d6633c7fe4..9d536a8cb379 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <linux/errno.h> | 39 | #include <linux/errno.h> |
| 40 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
| 41 | #include <linux/sched.h> | 41 | #include <linux/sched.h> |
| 42 | #include <linux/kthread.h> | ||
| 42 | #include <linux/sunrpc/xdr.h> | 43 | #include <linux/sunrpc/xdr.h> |
| 43 | #include <linux/sunrpc/svc.h> | 44 | #include <linux/sunrpc/svc.h> |
| 44 | #include <linux/sunrpc/clnt.h> | 45 | #include <linux/sunrpc/clnt.h> |
| @@ -343,26 +344,28 @@ static struct rpc_version * nfs_cb_version[] = { | |||
| 343 | &nfs_cb_version4, | 344 | &nfs_cb_version4, |
| 344 | }; | 345 | }; |
| 345 | 346 | ||
| 346 | /* | 347 | /* Reference counting, callback cleanup, etc., all look racy as heck. |
| 347 | * Use the SETCLIENTID credential | 348 | * And why is cb_set an atomic? */ |
| 348 | */ | 349 | |
| 349 | static struct rpc_cred * | 350 | static int do_probe_callback(void *data) |
| 350 | nfsd4_lookupcred(struct nfs4_client *clp, int taskflags) | ||
| 351 | { | 351 | { |
| 352 | struct auth_cred acred; | 352 | struct nfs4_client *clp = data; |
| 353 | struct rpc_clnt *clnt = clp->cl_callback.cb_client; | 353 | struct nfs4_callback *cb = &clp->cl_callback; |
| 354 | struct rpc_cred *ret; | 354 | struct rpc_message msg = { |
| 355 | 355 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], | |
| 356 | get_group_info(clp->cl_cred.cr_group_info); | 356 | .rpc_argp = clp, |
| 357 | acred.uid = clp->cl_cred.cr_uid; | 357 | }; |
| 358 | acred.gid = clp->cl_cred.cr_gid; | 358 | int status; |
| 359 | acred.group_info = clp->cl_cred.cr_group_info; | 359 | |
| 360 | 360 | status = rpc_call_sync(cb->cb_client, &msg, RPC_TASK_SOFT); | |
| 361 | dprintk("NFSD: looking up %s cred\n", | 361 | |
| 362 | clnt->cl_auth->au_ops->au_name); | 362 | if (status) { |
| 363 | ret = rpcauth_lookup_credcache(clnt->cl_auth, &acred, taskflags); | 363 | rpc_shutdown_client(cb->cb_client); |
| 364 | put_group_info(clp->cl_cred.cr_group_info); | 364 | cb->cb_client = NULL; |
| 365 | return ret; | 365 | } else |
| 366 | atomic_set(&cb->cb_set, 1); | ||
| 367 | put_nfs4_client(clp); | ||
| 368 | return 0; | ||
| 366 | } | 369 | } |
| 367 | 370 | ||
| 368 | /* | 371 | /* |
| @@ -390,11 +393,7 @@ nfsd4_probe_callback(struct nfs4_client *clp) | |||
| 390 | .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ | 393 | .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ |
| 391 | .flags = (RPC_CLNT_CREATE_NOPING), | 394 | .flags = (RPC_CLNT_CREATE_NOPING), |
| 392 | }; | 395 | }; |
| 393 | struct rpc_message msg = { | 396 | struct task_struct *t; |
| 394 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], | ||
| 395 | .rpc_argp = clp, | ||
| 396 | }; | ||
| 397 | int status; | ||
| 398 | 397 | ||
| 399 | if (atomic_read(&cb->cb_set)) | 398 | if (atomic_read(&cb->cb_set)) |
| 400 | return; | 399 | return; |
| @@ -426,16 +425,11 @@ nfsd4_probe_callback(struct nfs4_client *clp) | |||
| 426 | /* the task holds a reference to the nfs4_client struct */ | 425 | /* the task holds a reference to the nfs4_client struct */ |
| 427 | atomic_inc(&clp->cl_count); | 426 | atomic_inc(&clp->cl_count); |
| 428 | 427 | ||
| 429 | msg.rpc_cred = nfsd4_lookupcred(clp,0); | 428 | t = kthread_run(do_probe_callback, clp, "nfs4_cb_probe"); |
| 430 | if (IS_ERR(msg.rpc_cred)) | ||
| 431 | goto out_release_clp; | ||
| 432 | status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL); | ||
| 433 | put_rpccred(msg.rpc_cred); | ||
| 434 | 429 | ||
| 435 | if (status != 0) { | 430 | if (IS_ERR(t)) |
| 436 | dprintk("NFSD: asynchronous NFSPROC4_CB_NULL failed!\n"); | ||
| 437 | goto out_release_clp; | 431 | goto out_release_clp; |
| 438 | } | 432 | |
| 439 | return; | 433 | return; |
| 440 | 434 | ||
| 441 | out_release_clp: | 435 | out_release_clp: |
| @@ -447,30 +441,6 @@ out_err: | |||
| 447 | (int)clp->cl_name.len, clp->cl_name.data); | 441 | (int)clp->cl_name.len, clp->cl_name.data); |
| 448 | } | 442 | } |
| 449 | 443 | ||
| 450 | static void | ||
| 451 | nfs4_cb_null(struct rpc_task *task, void *dummy) | ||
| 452 | { | ||
| 453 | struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp; | ||
| 454 | struct nfs4_callback *cb = &clp->cl_callback; | ||
| 455 | __be32 addr = htonl(cb->cb_addr); | ||
| 456 | |||
| 457 | dprintk("NFSD: nfs4_cb_null task->tk_status %d\n", task->tk_status); | ||
| 458 | |||
| 459 | if (task->tk_status < 0) { | ||
| 460 | dprintk("NFSD: callback establishment to client %.*s failed\n", | ||
| 461 | (int)clp->cl_name.len, clp->cl_name.data); | ||
| 462 | goto out; | ||
| 463 | } | ||
| 464 | atomic_set(&cb->cb_set, 1); | ||
| 465 | dprintk("NFSD: callback set to client %u.%u.%u.%u\n", NIPQUAD(addr)); | ||
| 466 | out: | ||
| 467 | put_nfs4_client(clp); | ||
| 468 | } | ||
| 469 | |||
| 470 | static const struct rpc_call_ops nfs4_cb_null_ops = { | ||
| 471 | .rpc_call_done = nfs4_cb_null, | ||
| 472 | }; | ||
| 473 | |||
| 474 | /* | 444 | /* |
| 475 | * called with dp->dl_count inc'ed. | 445 | * called with dp->dl_count inc'ed. |
| 476 | * nfs4_lock_state() may or may not have been called. | 446 | * nfs4_lock_state() may or may not have been called. |
| @@ -491,10 +461,6 @@ nfsd4_cb_recall(struct nfs4_delegation *dp) | |||
| 491 | if ((!atomic_read(&clp->cl_callback.cb_set)) || !clnt) | 461 | if ((!atomic_read(&clp->cl_callback.cb_set)) || !clnt) |
| 492 | return; | 462 | return; |
| 493 | 463 | ||
| 494 | msg.rpc_cred = nfsd4_lookupcred(clp, 0); | ||
| 495 | if (IS_ERR(msg.rpc_cred)) | ||
| 496 | goto out; | ||
| 497 | |||
| 498 | cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */ | 464 | cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */ |
| 499 | cbr->cbr_dp = dp; | 465 | cbr->cbr_dp = dp; |
| 500 | 466 | ||
| @@ -515,13 +481,12 @@ nfsd4_cb_recall(struct nfs4_delegation *dp) | |||
| 515 | status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT); | 481 | status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT); |
| 516 | } | 482 | } |
| 517 | out_put_cred: | 483 | out_put_cred: |
| 518 | put_rpccred(msg.rpc_cred); | ||
| 519 | out: | ||
| 520 | if (status == -EIO) | 484 | if (status == -EIO) |
| 521 | atomic_set(&clp->cl_callback.cb_set, 0); | 485 | atomic_set(&clp->cl_callback.cb_set, 0); |
| 522 | /* Success or failure, now we're either waiting for lease expiration | 486 | /* Success or failure, now we're either waiting for lease expiration |
| 523 | * or deleg_return. */ | 487 | * or deleg_return. */ |
| 524 | dprintk("NFSD: nfs4_cb_recall: dp %p dl_flock %p dl_count %d\n",dp, dp->dl_flock, atomic_read(&dp->dl_count)); | 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); | ||
| 525 | nfs4_put_delegation(dp); | 490 | nfs4_put_delegation(dp); |
| 526 | return; | 491 | return; |
| 527 | } | 492 | } |
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 2ccffde81b84..4c0c683ce07a 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c | |||
| @@ -207,6 +207,7 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) | |||
| 207 | { | 207 | { |
| 208 | struct ent ent, *res; | 208 | struct ent ent, *res; |
| 209 | char *buf1, *bp; | 209 | char *buf1, *bp; |
| 210 | int len; | ||
| 210 | int error = -EINVAL; | 211 | int error = -EINVAL; |
| 211 | 212 | ||
| 212 | if (buf[buflen - 1] != '\n') | 213 | if (buf[buflen - 1] != '\n') |
| @@ -248,10 +249,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) | |||
| 248 | goto out; | 249 | goto out; |
| 249 | 250 | ||
| 250 | /* Name */ | 251 | /* Name */ |
| 251 | error = qword_get(&buf, buf1, PAGE_SIZE); | 252 | error = -EINVAL; |
| 252 | if (error == -EINVAL) | 253 | len = qword_get(&buf, buf1, PAGE_SIZE); |
| 254 | if (len < 0) | ||
| 253 | goto out; | 255 | goto out; |
| 254 | if (error == -ENOENT) | 256 | if (len == 0) |
| 255 | set_bit(CACHE_NEGATIVE, &ent.h.flags); | 257 | set_bit(CACHE_NEGATIVE, &ent.h.flags); |
| 256 | else { | 258 | else { |
| 257 | if (error >= IDMAP_NAMESZ) { | 259 | if (error >= IDMAP_NAMESZ) { |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 29b7e63cb32c..18ead1790bb3 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
| @@ -238,12 +238,12 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 238 | break; | 238 | break; |
| 239 | case NFS4_OPEN_CLAIM_DELEGATE_PREV: | 239 | case NFS4_OPEN_CLAIM_DELEGATE_PREV: |
| 240 | open->op_stateowner->so_confirmed = 1; | 240 | open->op_stateowner->so_confirmed = 1; |
| 241 | printk("NFSD: unsupported OPEN claim type %d\n", | 241 | dprintk("NFSD: unsupported OPEN claim type %d\n", |
| 242 | open->op_claim_type); | 242 | open->op_claim_type); |
| 243 | status = nfserr_notsupp; | 243 | status = nfserr_notsupp; |
| 244 | goto out; | 244 | goto out; |
| 245 | default: | 245 | default: |
| 246 | printk("NFSD: Invalid OPEN claim type %d\n", | 246 | dprintk("NFSD: Invalid OPEN claim type %d\n", |
| 247 | open->op_claim_type); | 247 | open->op_claim_type); |
| 248 | status = nfserr_inval; | 248 | status = nfserr_inval; |
| 249 | goto out; | 249 | goto out; |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 3f559700788f..6f182d25793d 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
| @@ -358,9 +358,22 @@ alloc_client(struct xdr_netobj name) | |||
| 358 | return clp; | 358 | return clp; |
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | static void | ||
| 362 | shutdown_callback_client(struct nfs4_client *clp) | ||
| 363 | { | ||
| 364 | struct rpc_clnt *clnt = clp->cl_callback.cb_client; | ||
| 365 | |||
| 366 | /* shutdown rpc client, ending any outstanding recall rpcs */ | ||
| 367 | if (clnt) { | ||
| 368 | clp->cl_callback.cb_client = NULL; | ||
| 369 | rpc_shutdown_client(clnt); | ||
| 370 | } | ||
| 371 | } | ||
| 372 | |||
| 361 | static inline void | 373 | static inline void |
| 362 | free_client(struct nfs4_client *clp) | 374 | free_client(struct nfs4_client *clp) |
| 363 | { | 375 | { |
| 376 | shutdown_callback_client(clp); | ||
| 364 | if (clp->cl_cred.cr_group_info) | 377 | if (clp->cl_cred.cr_group_info) |
| 365 | put_group_info(clp->cl_cred.cr_group_info); | 378 | put_group_info(clp->cl_cred.cr_group_info); |
| 366 | kfree(clp->cl_name.data); | 379 | kfree(clp->cl_name.data); |
| @@ -375,18 +388,6 @@ put_nfs4_client(struct nfs4_client *clp) | |||
| 375 | } | 388 | } |
| 376 | 389 | ||
| 377 | static void | 390 | static void |
| 378 | shutdown_callback_client(struct nfs4_client *clp) | ||
| 379 | { | ||
| 380 | struct rpc_clnt *clnt = clp->cl_callback.cb_client; | ||
| 381 | |||
| 382 | /* shutdown rpc client, ending any outstanding recall rpcs */ | ||
| 383 | if (clnt) { | ||
| 384 | clp->cl_callback.cb_client = NULL; | ||
| 385 | rpc_shutdown_client(clnt); | ||
| 386 | } | ||
| 387 | } | ||
| 388 | |||
| 389 | static void | ||
| 390 | expire_client(struct nfs4_client *clp) | 391 | expire_client(struct nfs4_client *clp) |
| 391 | { | 392 | { |
| 392 | struct nfs4_stateowner *sop; | 393 | struct nfs4_stateowner *sop; |
| @@ -396,8 +397,6 @@ expire_client(struct nfs4_client *clp) | |||
| 396 | dprintk("NFSD: expire_client cl_count %d\n", | 397 | dprintk("NFSD: expire_client cl_count %d\n", |
| 397 | atomic_read(&clp->cl_count)); | 398 | atomic_read(&clp->cl_count)); |
| 398 | 399 | ||
| 399 | shutdown_callback_client(clp); | ||
| 400 | |||
| 401 | INIT_LIST_HEAD(&reaplist); | 400 | INIT_LIST_HEAD(&reaplist); |
| 402 | spin_lock(&recall_lock); | 401 | spin_lock(&recall_lock); |
| 403 | while (!list_empty(&clp->cl_delegations)) { | 402 | while (!list_empty(&clp->cl_delegations)) { |
| @@ -462,26 +461,28 @@ copy_cred(struct svc_cred *target, struct svc_cred *source) { | |||
| 462 | } | 461 | } |
| 463 | 462 | ||
| 464 | static inline int | 463 | static inline int |
| 465 | same_name(const char *n1, const char *n2) { | 464 | same_name(const char *n1, const char *n2) |
| 465 | { | ||
| 466 | return 0 == memcmp(n1, n2, HEXDIR_LEN); | 466 | return 0 == memcmp(n1, n2, HEXDIR_LEN); |
| 467 | } | 467 | } |
| 468 | 468 | ||
| 469 | static int | 469 | static int |
| 470 | cmp_verf(nfs4_verifier *v1, nfs4_verifier *v2) { | 470 | same_verf(nfs4_verifier *v1, nfs4_verifier *v2) |
| 471 | return(!memcmp(v1->data,v2->data,sizeof(v1->data))); | 471 | { |
| 472 | return 0 == memcmp(v1->data, v2->data, sizeof(v1->data)); | ||
| 472 | } | 473 | } |
| 473 | 474 | ||
| 474 | static int | 475 | static int |
| 475 | cmp_clid(clientid_t * cl1, clientid_t * cl2) { | 476 | same_clid(clientid_t *cl1, clientid_t *cl2) |
| 476 | return((cl1->cl_boot == cl2->cl_boot) && | 477 | { |
| 477 | (cl1->cl_id == cl2->cl_id)); | 478 | return (cl1->cl_boot == cl2->cl_boot) && (cl1->cl_id == cl2->cl_id); |
| 478 | } | 479 | } |
| 479 | 480 | ||
| 480 | /* XXX what about NGROUP */ | 481 | /* XXX what about NGROUP */ |
| 481 | static int | 482 | static int |
| 482 | cmp_creds(struct svc_cred *cr1, struct svc_cred *cr2){ | 483 | same_creds(struct svc_cred *cr1, struct svc_cred *cr2) |
| 483 | return(cr1->cr_uid == cr2->cr_uid); | 484 | { |
| 484 | 485 | return cr1->cr_uid == cr2->cr_uid; | |
| 485 | } | 486 | } |
| 486 | 487 | ||
| 487 | static void | 488 | static void |
| @@ -507,7 +508,7 @@ check_name(struct xdr_netobj name) { | |||
| 507 | if (name.len == 0) | 508 | if (name.len == 0) |
| 508 | return 0; | 509 | return 0; |
| 509 | if (name.len > NFS4_OPAQUE_LIMIT) { | 510 | if (name.len > NFS4_OPAQUE_LIMIT) { |
| 510 | printk("NFSD: check_name: name too long(%d)!\n", name.len); | 511 | dprintk("NFSD: check_name: name too long(%d)!\n", name.len); |
| 511 | return 0; | 512 | return 0; |
| 512 | } | 513 | } |
| 513 | return 1; | 514 | return 1; |
| @@ -546,7 +547,7 @@ find_confirmed_client(clientid_t *clid) | |||
| 546 | unsigned int idhashval = clientid_hashval(clid->cl_id); | 547 | unsigned int idhashval = clientid_hashval(clid->cl_id); |
| 547 | 548 | ||
| 548 | list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) { | 549 | list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) { |
| 549 | if (cmp_clid(&clp->cl_clientid, clid)) | 550 | if (same_clid(&clp->cl_clientid, clid)) |
| 550 | return clp; | 551 | return clp; |
| 551 | } | 552 | } |
| 552 | return NULL; | 553 | return NULL; |
| @@ -559,7 +560,7 @@ find_unconfirmed_client(clientid_t *clid) | |||
| 559 | unsigned int idhashval = clientid_hashval(clid->cl_id); | 560 | unsigned int idhashval = clientid_hashval(clid->cl_id); |
| 560 | 561 | ||
| 561 | list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) { | 562 | list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) { |
| 562 | if (cmp_clid(&clp->cl_clientid, clid)) | 563 | if (same_clid(&clp->cl_clientid, clid)) |
| 563 | return clp; | 564 | return clp; |
| 564 | } | 565 | } |
| 565 | return NULL; | 566 | return NULL; |
| @@ -753,7 +754,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 753 | * or different ip_address | 754 | * or different ip_address |
| 754 | */ | 755 | */ |
| 755 | status = nfserr_clid_inuse; | 756 | status = nfserr_clid_inuse; |
| 756 | if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred) | 757 | if (!same_creds(&conf->cl_cred, &rqstp->rq_cred) |
| 757 | || conf->cl_addr != sin->sin_addr.s_addr) { | 758 | || conf->cl_addr != sin->sin_addr.s_addr) { |
| 758 | dprintk("NFSD: setclientid: string in use by client" | 759 | dprintk("NFSD: setclientid: string in use by client" |
| 759 | "at %u.%u.%u.%u\n", NIPQUAD(conf->cl_addr)); | 760 | "at %u.%u.%u.%u\n", NIPQUAD(conf->cl_addr)); |
| @@ -772,14 +773,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 772 | new = create_client(clname, dname); | 773 | new = create_client(clname, dname); |
| 773 | if (new == NULL) | 774 | if (new == NULL) |
| 774 | goto out; | 775 | goto out; |
| 775 | copy_verf(new, &clverifier); | ||
| 776 | new->cl_addr = sin->sin_addr.s_addr; | ||
| 777 | copy_cred(&new->cl_cred,&rqstp->rq_cred); | ||
| 778 | gen_clid(new); | 776 | gen_clid(new); |
| 779 | gen_confirm(new); | 777 | } else if (same_verf(&conf->cl_verifier, &clverifier)) { |
| 780 | gen_callback(new, setclid); | ||
| 781 | add_to_unconfirmed(new, strhashval); | ||
| 782 | } else if (cmp_verf(&conf->cl_verifier, &clverifier)) { | ||
| 783 | /* | 778 | /* |
| 784 | * CASE 1: | 779 | * CASE 1: |
| 785 | * cl_name match, confirmed, principal match | 780 | * cl_name match, confirmed, principal match |
| @@ -804,13 +799,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 804 | new = create_client(clname, dname); | 799 | new = create_client(clname, dname); |
| 805 | if (new == NULL) | 800 | if (new == NULL) |
| 806 | goto out; | 801 | goto out; |
| 807 | copy_verf(new,&conf->cl_verifier); | ||
| 808 | new->cl_addr = sin->sin_addr.s_addr; | ||
| 809 | copy_cred(&new->cl_cred,&rqstp->rq_cred); | ||
| 810 | copy_clid(new, conf); | 802 | copy_clid(new, conf); |
| 811 | gen_confirm(new); | ||
| 812 | gen_callback(new, setclid); | ||
| 813 | add_to_unconfirmed(new,strhashval); | ||
| 814 | } else if (!unconf) { | 803 | } else if (!unconf) { |
| 815 | /* | 804 | /* |
| 816 | * CASE 2: | 805 | * CASE 2: |
| @@ -823,14 +812,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 823 | new = create_client(clname, dname); | 812 | new = create_client(clname, dname); |
| 824 | if (new == NULL) | 813 | if (new == NULL) |
| 825 | goto out; | 814 | goto out; |
| 826 | copy_verf(new,&clverifier); | ||
| 827 | new->cl_addr = sin->sin_addr.s_addr; | ||
| 828 | copy_cred(&new->cl_cred,&rqstp->rq_cred); | ||
| 829 | gen_clid(new); | 815 | gen_clid(new); |
| 830 | gen_confirm(new); | 816 | } else if (!same_verf(&conf->cl_confirm, &unconf->cl_confirm)) { |
| 831 | gen_callback(new, setclid); | ||
| 832 | add_to_unconfirmed(new, strhashval); | ||
| 833 | } else if (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm)) { | ||
| 834 | /* | 817 | /* |
| 835 | * CASE3: | 818 | * CASE3: |
| 836 | * confirmed found (name, principal match) | 819 | * confirmed found (name, principal match) |
| @@ -850,19 +833,19 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 850 | new = create_client(clname, dname); | 833 | new = create_client(clname, dname); |
| 851 | if (new == NULL) | 834 | if (new == NULL) |
| 852 | goto out; | 835 | goto out; |
| 853 | copy_verf(new,&clverifier); | ||
| 854 | new->cl_addr = sin->sin_addr.s_addr; | ||
| 855 | copy_cred(&new->cl_cred,&rqstp->rq_cred); | ||
| 856 | gen_clid(new); | 836 | gen_clid(new); |
| 857 | gen_confirm(new); | ||
| 858 | gen_callback(new, setclid); | ||
| 859 | add_to_unconfirmed(new, strhashval); | ||
| 860 | } else { | 837 | } else { |
| 861 | /* No cases hit !!! */ | 838 | /* No cases hit !!! */ |
| 862 | status = nfserr_inval; | 839 | status = nfserr_inval; |
| 863 | goto out; | 840 | goto out; |
| 864 | 841 | ||
| 865 | } | 842 | } |
| 843 | copy_verf(new, &clverifier); | ||
| 844 | new->cl_addr = sin->sin_addr.s_addr; | ||
| 845 | copy_cred(&new->cl_cred, &rqstp->rq_cred); | ||
| 846 | gen_confirm(new); | ||
| 847 | gen_callback(new, setclid); | ||
| 848 | add_to_unconfirmed(new, strhashval); | ||
| 866 | setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot; | 849 | setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot; |
| 867 | setclid->se_clientid.cl_id = new->cl_clientid.cl_id; | 850 | setclid->se_clientid.cl_id = new->cl_clientid.cl_id; |
| 868 | memcpy(setclid->se_confirm.data, new->cl_confirm.data, sizeof(setclid->se_confirm.data)); | 851 | memcpy(setclid->se_confirm.data, new->cl_confirm.data, sizeof(setclid->se_confirm.data)); |
| @@ -910,16 +893,16 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
| 910 | goto out; | 893 | goto out; |
| 911 | 894 | ||
| 912 | if ((conf && unconf) && | 895 | if ((conf && unconf) && |
| 913 | (cmp_verf(&unconf->cl_confirm, &confirm)) && | 896 | (same_verf(&unconf->cl_confirm, &confirm)) && |
| 914 | (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) && | 897 | (same_verf(&conf->cl_verifier, &unconf->cl_verifier)) && |
| 915 | (same_name(conf->cl_recdir,unconf->cl_recdir)) && | 898 | (same_name(conf->cl_recdir,unconf->cl_recdir)) && |
| 916 | (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) { | 899 | (!same_verf(&conf->cl_confirm, &unconf->cl_confirm))) { |
| 917 | /* CASE 1: | 900 | /* CASE 1: |
| 918 | * unconf record that matches input clientid and input confirm. | 901 | * unconf record that matches input clientid and input confirm. |
| 919 | * conf record that matches input clientid. | 902 | * conf record that matches input clientid. |
| 920 | * conf and unconf records match names, verifiers | 903 | * conf and unconf records match names, verifiers |
| 921 | */ | 904 | */ |
| 922 | if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred)) | 905 | if (!same_creds(&conf->cl_cred, &unconf->cl_cred)) |
| 923 | status = nfserr_clid_inuse; | 906 | status = nfserr_clid_inuse; |
| 924 | else { | 907 | else { |
| 925 | /* XXX: We just turn off callbacks until we can handle | 908 | /* XXX: We just turn off callbacks until we can handle |
| @@ -933,7 +916,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
| 933 | } | 916 | } |
| 934 | } else if ((conf && !unconf) || | 917 | } else if ((conf && !unconf) || |
| 935 | ((conf && unconf) && | 918 | ((conf && unconf) && |
| 936 | (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) || | 919 | (!same_verf(&conf->cl_verifier, &unconf->cl_verifier) || |
| 937 | !same_name(conf->cl_recdir, unconf->cl_recdir)))) { | 920 | !same_name(conf->cl_recdir, unconf->cl_recdir)))) { |
| 938 | /* CASE 2: | 921 | /* CASE 2: |
| 939 | * conf record that matches input clientid. | 922 | * conf record that matches input clientid. |
| @@ -941,18 +924,18 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
| 941 | * unconf->cl_name or unconf->cl_verifier don't match the | 924 | * unconf->cl_name or unconf->cl_verifier don't match the |
| 942 | * conf record. | 925 | * conf record. |
| 943 | */ | 926 | */ |
| 944 | if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) | 927 | if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) |
| 945 | status = nfserr_clid_inuse; | 928 | status = nfserr_clid_inuse; |
| 946 | else | 929 | else |
| 947 | status = nfs_ok; | 930 | status = nfs_ok; |
| 948 | } else if (!conf && unconf | 931 | } else if (!conf && unconf |
| 949 | && cmp_verf(&unconf->cl_confirm, &confirm)) { | 932 | && same_verf(&unconf->cl_confirm, &confirm)) { |
| 950 | /* CASE 3: | 933 | /* CASE 3: |
| 951 | * conf record not found. | 934 | * conf record not found. |
| 952 | * unconf record found. | 935 | * unconf record found. |
| 953 | * unconf->cl_confirm matches input confirm | 936 | * unconf->cl_confirm matches input confirm |
| 954 | */ | 937 | */ |
| 955 | if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) { | 938 | if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred)) { |
| 956 | status = nfserr_clid_inuse; | 939 | status = nfserr_clid_inuse; |
| 957 | } else { | 940 | } else { |
| 958 | unsigned int hash = | 941 | unsigned int hash = |
| @@ -967,8 +950,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
| 967 | conf = unconf; | 950 | conf = unconf; |
| 968 | status = nfs_ok; | 951 | status = nfs_ok; |
| 969 | } | 952 | } |
| 970 | } else if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm))) | 953 | } else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm))) |
| 971 | && (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm, | 954 | && (!unconf || (unconf && !same_verf(&unconf->cl_confirm, |
| 972 | &confirm)))) { | 955 | &confirm)))) { |
| 973 | /* CASE 4: | 956 | /* CASE 4: |
| 974 | * conf record not found, or if conf, conf->cl_confirm does not | 957 | * conf record not found, or if conf, conf->cl_confirm does not |
| @@ -1019,7 +1002,7 @@ nfsd4_free_slab(struct kmem_cache **slab) | |||
| 1019 | *slab = NULL; | 1002 | *slab = NULL; |
| 1020 | } | 1003 | } |
| 1021 | 1004 | ||
| 1022 | static void | 1005 | void |
| 1023 | nfsd4_free_slabs(void) | 1006 | nfsd4_free_slabs(void) |
| 1024 | { | 1007 | { |
| 1025 | nfsd4_free_slab(&stateowner_slab); | 1008 | nfsd4_free_slab(&stateowner_slab); |
| @@ -1207,10 +1190,12 @@ move_to_close_lru(struct nfs4_stateowner *sop) | |||
| 1207 | } | 1190 | } |
| 1208 | 1191 | ||
| 1209 | static int | 1192 | static int |
| 1210 | cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) { | 1193 | same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, |
| 1211 | return ((sop->so_owner.len == owner->len) && | 1194 | clientid_t *clid) |
| 1212 | !memcmp(sop->so_owner.data, owner->data, owner->len) && | 1195 | { |
| 1213 | (sop->so_client->cl_clientid.cl_id == clid->cl_id)); | 1196 | return (sop->so_owner.len == owner->len) && |
| 1197 | 0 == memcmp(sop->so_owner.data, owner->data, owner->len) && | ||
| 1198 | (sop->so_client->cl_clientid.cl_id == clid->cl_id); | ||
| 1214 | } | 1199 | } |
| 1215 | 1200 | ||
| 1216 | static struct nfs4_stateowner * | 1201 | static struct nfs4_stateowner * |
| @@ -1219,7 +1204,7 @@ find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open) | |||
| 1219 | struct nfs4_stateowner *so = NULL; | 1204 | struct nfs4_stateowner *so = NULL; |
| 1220 | 1205 | ||
| 1221 | list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) { | 1206 | list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) { |
| 1222 | if (cmp_owner_str(so, &open->op_owner, &open->op_clientid)) | 1207 | if (same_owner_str(so, &open->op_owner, &open->op_clientid)) |
| 1223 | return so; | 1208 | return so; |
| 1224 | } | 1209 | } |
| 1225 | return NULL; | 1210 | return NULL; |
| @@ -1360,6 +1345,7 @@ void nfsd_break_deleg_cb(struct file_lock *fl) | |||
| 1360 | * lock) we know the server hasn't removed the lease yet, we know | 1345 | * lock) we know the server hasn't removed the lease yet, we know |
| 1361 | * it's safe to take a reference: */ | 1346 | * it's safe to take a reference: */ |
| 1362 | atomic_inc(&dp->dl_count); | 1347 | atomic_inc(&dp->dl_count); |
| 1348 | atomic_inc(&dp->dl_client->cl_count); | ||
| 1363 | 1349 | ||
| 1364 | spin_lock(&recall_lock); | 1350 | spin_lock(&recall_lock); |
| 1365 | list_add_tail(&dp->dl_recall_lru, &del_recall_lru); | 1351 | list_add_tail(&dp->dl_recall_lru, &del_recall_lru); |
| @@ -1368,8 +1354,12 @@ void nfsd_break_deleg_cb(struct file_lock *fl) | |||
| 1368 | /* only place dl_time is set. protected by lock_kernel*/ | 1354 | /* only place dl_time is set. protected by lock_kernel*/ |
| 1369 | dp->dl_time = get_seconds(); | 1355 | dp->dl_time = get_seconds(); |
| 1370 | 1356 | ||
| 1371 | /* XXX need to merge NFSD_LEASE_TIME with fs/locks.c:lease_break_time */ | 1357 | /* |
| 1372 | fl->fl_break_time = jiffies + NFSD_LEASE_TIME * HZ; | 1358 | * We don't want the locks code to timeout the lease for us; |
| 1359 | * we'll remove it ourself if the delegation isn't returned | ||
| 1360 | * in time. | ||
| 1361 | */ | ||
| 1362 | fl->fl_break_time = 0; | ||
| 1373 | 1363 | ||
| 1374 | t = kthread_run(do_recall, dp, "%s", "nfs4_cb_recall"); | 1364 | t = kthread_run(do_recall, dp, "%s", "nfs4_cb_recall"); |
| 1375 | if (IS_ERR(t)) { | 1365 | if (IS_ERR(t)) { |
| @@ -1378,6 +1368,7 @@ void nfsd_break_deleg_cb(struct file_lock *fl) | |||
| 1378 | printk(KERN_INFO "NFSD: Callback thread failed for " | 1368 | printk(KERN_INFO "NFSD: Callback thread failed for " |
| 1379 | "for client (clientid %08x/%08x)\n", | 1369 | "for client (clientid %08x/%08x)\n", |
| 1380 | clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); | 1370 | clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); |
| 1371 | put_nfs4_client(dp->dl_client); | ||
| 1381 | nfs4_put_delegation(dp); | 1372 | nfs4_put_delegation(dp); |
| 1382 | } | 1373 | } |
| 1383 | } | 1374 | } |
| @@ -1738,7 +1729,7 @@ out: | |||
| 1738 | if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS | 1729 | if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS |
| 1739 | && flag == NFS4_OPEN_DELEGATE_NONE | 1730 | && flag == NFS4_OPEN_DELEGATE_NONE |
| 1740 | && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) | 1731 | && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) |
| 1741 | printk("NFSD: WARNING: refusing delegation reclaim\n"); | 1732 | dprintk("NFSD: WARNING: refusing delegation reclaim\n"); |
| 1742 | open->op_delegate_type = flag; | 1733 | open->op_delegate_type = flag; |
| 1743 | } | 1734 | } |
| 1744 | 1735 | ||
| @@ -2147,7 +2138,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei | |||
| 2147 | *sopp = NULL; | 2138 | *sopp = NULL; |
| 2148 | 2139 | ||
| 2149 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) { | 2140 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) { |
| 2150 | printk("NFSD: preprocess_seqid_op: magic stateid!\n"); | 2141 | dprintk("NFSD: preprocess_seqid_op: magic stateid!\n"); |
| 2151 | return nfserr_bad_stateid; | 2142 | return nfserr_bad_stateid; |
| 2152 | } | 2143 | } |
| 2153 | 2144 | ||
| @@ -2181,25 +2172,24 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei | |||
| 2181 | lkflg = setlkflg(lock->lk_type); | 2172 | lkflg = setlkflg(lock->lk_type); |
| 2182 | 2173 | ||
| 2183 | if (lock->lk_is_new) { | 2174 | if (lock->lk_is_new) { |
| 2184 | if (!sop->so_is_open_owner) | 2175 | if (!sop->so_is_open_owner) |
| 2185 | return nfserr_bad_stateid; | 2176 | return nfserr_bad_stateid; |
| 2186 | if (!cmp_clid(&clp->cl_clientid, lockclid)) | 2177 | if (!same_clid(&clp->cl_clientid, lockclid)) |
| 2187 | return nfserr_bad_stateid; | 2178 | return nfserr_bad_stateid; |
| 2188 | /* stp is the open stateid */ | 2179 | /* stp is the open stateid */ |
| 2189 | status = nfs4_check_openmode(stp, lkflg); | 2180 | status = nfs4_check_openmode(stp, lkflg); |
| 2190 | if (status) | 2181 | if (status) |
| 2191 | return status; | 2182 | return status; |
| 2192 | } else { | 2183 | } else { |
| 2193 | /* stp is the lock stateid */ | 2184 | /* stp is the lock stateid */ |
| 2194 | status = nfs4_check_openmode(stp->st_openstp, lkflg); | 2185 | status = nfs4_check_openmode(stp->st_openstp, lkflg); |
| 2195 | if (status) | 2186 | if (status) |
| 2196 | return status; | 2187 | return status; |
| 2197 | } | 2188 | } |
| 2198 | |||
| 2199 | } | 2189 | } |
| 2200 | 2190 | ||
| 2201 | if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) { | 2191 | if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) { |
| 2202 | printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n"); | 2192 | dprintk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n"); |
| 2203 | return nfserr_bad_stateid; | 2193 | return nfserr_bad_stateid; |
| 2204 | } | 2194 | } |
| 2205 | 2195 | ||
| @@ -2215,22 +2205,22 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei | |||
| 2215 | goto check_replay; | 2205 | goto check_replay; |
| 2216 | 2206 | ||
| 2217 | if (sop->so_confirmed && flags & CONFIRM) { | 2207 | if (sop->so_confirmed && flags & CONFIRM) { |
| 2218 | printk("NFSD: preprocess_seqid_op: expected" | 2208 | dprintk("NFSD: preprocess_seqid_op: expected" |
| 2219 | " unconfirmed stateowner!\n"); | 2209 | " unconfirmed stateowner!\n"); |
| 2220 | return nfserr_bad_stateid; | 2210 | return nfserr_bad_stateid; |
| 2221 | } | 2211 | } |
| 2222 | if (!sop->so_confirmed && !(flags & CONFIRM)) { | 2212 | if (!sop->so_confirmed && !(flags & CONFIRM)) { |
| 2223 | printk("NFSD: preprocess_seqid_op: stateowner not" | 2213 | dprintk("NFSD: preprocess_seqid_op: stateowner not" |
| 2224 | " confirmed yet!\n"); | 2214 | " confirmed yet!\n"); |
| 2225 | return nfserr_bad_stateid; | 2215 | return nfserr_bad_stateid; |
| 2226 | } | 2216 | } |
| 2227 | if (stateid->si_generation > stp->st_stateid.si_generation) { | 2217 | if (stateid->si_generation > stp->st_stateid.si_generation) { |
| 2228 | printk("NFSD: preprocess_seqid_op: future stateid?!\n"); | 2218 | dprintk("NFSD: preprocess_seqid_op: future stateid?!\n"); |
| 2229 | return nfserr_bad_stateid; | 2219 | return nfserr_bad_stateid; |
| 2230 | } | 2220 | } |
| 2231 | 2221 | ||
| 2232 | if (stateid->si_generation < stp->st_stateid.si_generation) { | 2222 | if (stateid->si_generation < stp->st_stateid.si_generation) { |
| 2233 | printk("NFSD: preprocess_seqid_op: old stateid!\n"); | 2223 | dprintk("NFSD: preprocess_seqid_op: old stateid!\n"); |
| 2234 | return nfserr_old_stateid; | 2224 | return nfserr_old_stateid; |
| 2235 | } | 2225 | } |
| 2236 | renew_client(sop->so_client); | 2226 | renew_client(sop->so_client); |
| @@ -2242,7 +2232,7 @@ check_replay: | |||
| 2242 | /* indicate replay to calling function */ | 2232 | /* indicate replay to calling function */ |
| 2243 | return nfserr_replay_me; | 2233 | return nfserr_replay_me; |
| 2244 | } | 2234 | } |
| 2245 | printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d)\n", | 2235 | dprintk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d)\n", |
| 2246 | sop->so_seqid, seqid); | 2236 | sop->so_seqid, seqid); |
| 2247 | *sopp = NULL; | 2237 | *sopp = NULL; |
| 2248 | return nfserr_bad_seqid; | 2238 | return nfserr_bad_seqid; |
| @@ -2561,7 +2551,7 @@ find_lockstateowner_str(struct inode *inode, clientid_t *clid, | |||
| 2561 | struct nfs4_stateowner *op; | 2551 | struct nfs4_stateowner *op; |
| 2562 | 2552 | ||
| 2563 | list_for_each_entry(op, &lock_ownerstr_hashtbl[hashval], so_strhash) { | 2553 | list_for_each_entry(op, &lock_ownerstr_hashtbl[hashval], so_strhash) { |
| 2564 | if (cmp_owner_str(op, owner, clid)) | 2554 | if (same_owner_str(op, owner, clid)) |
| 2565 | return op; | 2555 | return op; |
| 2566 | } | 2556 | } |
| 2567 | return NULL; | 2557 | return NULL; |
| @@ -2855,7 +2845,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 2855 | file_lock.fl_type = F_WRLCK; | 2845 | file_lock.fl_type = F_WRLCK; |
| 2856 | break; | 2846 | break; |
| 2857 | default: | 2847 | default: |
| 2858 | printk("NFSD: nfs4_lockt: bad lock type!\n"); | 2848 | dprintk("NFSD: nfs4_lockt: bad lock type!\n"); |
| 2859 | status = nfserr_inval; | 2849 | status = nfserr_inval; |
| 2860 | goto out; | 2850 | goto out; |
| 2861 | } | 2851 | } |
| @@ -3025,7 +3015,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, | |||
| 3025 | INIT_LIST_HEAD(&matches); | 3015 | INIT_LIST_HEAD(&matches); |
| 3026 | for (i = 0; i < LOCK_HASH_SIZE; i++) { | 3016 | for (i = 0; i < LOCK_HASH_SIZE; i++) { |
| 3027 | list_for_each_entry(sop, &lock_ownerid_hashtbl[i], so_idhash) { | 3017 | list_for_each_entry(sop, &lock_ownerid_hashtbl[i], so_idhash) { |
| 3028 | if (!cmp_owner_str(sop, owner, clid)) | 3018 | if (!same_owner_str(sop, owner, clid)) |
| 3029 | continue; | 3019 | continue; |
| 3030 | list_for_each_entry(stp, &sop->so_stateids, | 3020 | list_for_each_entry(stp, &sop->so_stateids, |
| 3031 | st_perstateowner) { | 3021 | st_perstateowner) { |
| @@ -3149,11 +3139,14 @@ nfs4_check_open_reclaim(clientid_t *clid) | |||
| 3149 | 3139 | ||
| 3150 | /* initialization to perform at module load time: */ | 3140 | /* initialization to perform at module load time: */ |
| 3151 | 3141 | ||
| 3152 | void | 3142 | int |
| 3153 | nfs4_state_init(void) | 3143 | nfs4_state_init(void) |
| 3154 | { | 3144 | { |
| 3155 | int i; | 3145 | int i, status; |
| 3156 | 3146 | ||
| 3147 | status = nfsd4_init_slabs(); | ||
| 3148 | if (status) | ||
| 3149 | return status; | ||
| 3157 | for (i = 0; i < CLIENT_HASH_SIZE; i++) { | 3150 | for (i = 0; i < CLIENT_HASH_SIZE; i++) { |
| 3158 | INIT_LIST_HEAD(&conf_id_hashtbl[i]); | 3151 | INIT_LIST_HEAD(&conf_id_hashtbl[i]); |
| 3159 | INIT_LIST_HEAD(&conf_str_hashtbl[i]); | 3152 | INIT_LIST_HEAD(&conf_str_hashtbl[i]); |
| @@ -3182,6 +3175,7 @@ nfs4_state_init(void) | |||
| 3182 | for (i = 0; i < CLIENT_HASH_SIZE; i++) | 3175 | for (i = 0; i < CLIENT_HASH_SIZE; i++) |
| 3183 | INIT_LIST_HEAD(&reclaim_str_hashtbl[i]); | 3176 | INIT_LIST_HEAD(&reclaim_str_hashtbl[i]); |
| 3184 | reclaim_str_hashtbl_size = 0; | 3177 | reclaim_str_hashtbl_size = 0; |
| 3178 | return 0; | ||
| 3185 | } | 3179 | } |
| 3186 | 3180 | ||
| 3187 | static void | 3181 | static void |
| @@ -3242,20 +3236,15 @@ __nfs4_state_start(void) | |||
| 3242 | set_max_delegations(); | 3236 | set_max_delegations(); |
| 3243 | } | 3237 | } |
| 3244 | 3238 | ||
| 3245 | int | 3239 | void |
| 3246 | nfs4_state_start(void) | 3240 | nfs4_state_start(void) |
| 3247 | { | 3241 | { |
| 3248 | int status; | ||
| 3249 | |||
| 3250 | if (nfs4_init) | 3242 | if (nfs4_init) |
| 3251 | return 0; | 3243 | return; |
| 3252 | status = nfsd4_init_slabs(); | ||
| 3253 | if (status) | ||
| 3254 | return status; | ||
| 3255 | nfsd4_load_reboot_recovery_data(); | 3244 | nfsd4_load_reboot_recovery_data(); |
| 3256 | __nfs4_state_start(); | 3245 | __nfs4_state_start(); |
| 3257 | nfs4_init = 1; | 3246 | nfs4_init = 1; |
| 3258 | return 0; | 3247 | return; |
| 3259 | } | 3248 | } |
| 3260 | 3249 | ||
| 3261 | int | 3250 | int |
| @@ -3313,7 +3302,6 @@ nfs4_state_shutdown(void) | |||
| 3313 | nfs4_lock_state(); | 3302 | nfs4_lock_state(); |
| 3314 | nfs4_release_reclaim(); | 3303 | nfs4_release_reclaim(); |
| 3315 | __nfs4_state_shutdown(); | 3304 | __nfs4_state_shutdown(); |
| 3316 | nfsd4_free_slabs(); | ||
| 3317 | nfs4_unlock_state(); | 3305 | nfs4_unlock_state(); |
| 3318 | } | 3306 | } |
| 3319 | 3307 | ||
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 8ef0964179bc..e15f2cf8ac15 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
| @@ -1475,7 +1475,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
| 1475 | err = vfs_getattr(exp->ex_mnt, dentry, &stat); | 1475 | err = vfs_getattr(exp->ex_mnt, dentry, &stat); |
| 1476 | if (err) | 1476 | if (err) |
| 1477 | goto out_nfserr; | 1477 | goto out_nfserr; |
| 1478 | if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) || | 1478 | if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL | |
| 1479 | FATTR4_WORD0_MAXNAME)) || | ||
| 1479 | (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | | 1480 | (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | |
| 1480 | FATTR4_WORD1_SPACE_TOTAL))) { | 1481 | FATTR4_WORD1_SPACE_TOTAL))) { |
| 1481 | err = vfs_statfs(dentry, &statfs); | 1482 | err = vfs_statfs(dentry, &statfs); |
| @@ -1679,7 +1680,7 @@ out_acl: | |||
| 1679 | if (bmval0 & FATTR4_WORD0_FILEID) { | 1680 | if (bmval0 & FATTR4_WORD0_FILEID) { |
| 1680 | if ((buflen -= 8) < 0) | 1681 | if ((buflen -= 8) < 0) |
| 1681 | goto out_resource; | 1682 | goto out_resource; |
| 1682 | WRITE64((u64) stat.ino); | 1683 | WRITE64(stat.ino); |
| 1683 | } | 1684 | } |
| 1684 | if (bmval0 & FATTR4_WORD0_FILES_AVAIL) { | 1685 | if (bmval0 & FATTR4_WORD0_FILES_AVAIL) { |
| 1685 | if ((buflen -= 8) < 0) | 1686 | if ((buflen -= 8) < 0) |
| @@ -1721,7 +1722,7 @@ out_acl: | |||
| 1721 | if (bmval0 & FATTR4_WORD0_MAXNAME) { | 1722 | if (bmval0 & FATTR4_WORD0_MAXNAME) { |
| 1722 | if ((buflen -= 4) < 0) | 1723 | if ((buflen -= 4) < 0) |
| 1723 | goto out_resource; | 1724 | goto out_resource; |
| 1724 | WRITE32(~(u32) 0); | 1725 | WRITE32(statfs.f_namelen); |
| 1725 | } | 1726 | } |
| 1726 | if (bmval0 & FATTR4_WORD0_MAXREAD) { | 1727 | if (bmval0 & FATTR4_WORD0_MAXREAD) { |
| 1727 | if ((buflen -= 8) < 0) | 1728 | if ((buflen -= 8) < 0) |
| @@ -1821,16 +1822,15 @@ out_acl: | |||
| 1821 | WRITE32(stat.mtime.tv_nsec); | 1822 | WRITE32(stat.mtime.tv_nsec); |
| 1822 | } | 1823 | } |
| 1823 | if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { | 1824 | if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { |
| 1824 | struct dentry *mnt_pnt, *mnt_root; | ||
| 1825 | |||
| 1826 | if ((buflen -= 8) < 0) | 1825 | if ((buflen -= 8) < 0) |
| 1827 | goto out_resource; | 1826 | goto out_resource; |
| 1828 | mnt_root = exp->ex_mnt->mnt_root; | 1827 | if (exp->ex_mnt->mnt_root->d_inode == dentry->d_inode) { |
| 1829 | if (mnt_root->d_inode == dentry->d_inode) { | 1828 | err = vfs_getattr(exp->ex_mnt->mnt_parent, |
| 1830 | mnt_pnt = exp->ex_mnt->mnt_mountpoint; | 1829 | exp->ex_mnt->mnt_mountpoint, &stat); |
| 1831 | WRITE64((u64) mnt_pnt->d_inode->i_ino); | 1830 | if (err) |
| 1832 | } else | 1831 | goto out_nfserr; |
| 1833 | WRITE64((u64) stat.ino); | 1832 | } |
| 1833 | WRITE64(stat.ino); | ||
| 1834 | } | 1834 | } |
| 1835 | *attrlenp = htonl((char *)p - (char *)attrlenp - 4); | 1835 | *attrlenp = htonl((char *)p - (char *)attrlenp - 4); |
| 1836 | *countp = p - buffer; | 1836 | *countp = p - buffer; |
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index baac89d917ca..77dc9893b7ba 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
| @@ -298,7 +298,7 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size) | |||
| 298 | * qword quoting is used, so filehandle will be \x.... | 298 | * qword quoting is used, so filehandle will be \x.... |
| 299 | */ | 299 | */ |
| 300 | char *dname, *path; | 300 | char *dname, *path; |
| 301 | int maxsize; | 301 | int uninitialized_var(maxsize); |
| 302 | char *mesg = buf; | 302 | char *mesg = buf; |
| 303 | int len; | 303 | int len; |
| 304 | struct auth_domain *dom; | 304 | struct auth_domain *dom; |
| @@ -679,11 +679,13 @@ static int __init init_nfsd(void) | |||
| 679 | int retval; | 679 | int retval; |
| 680 | printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n"); | 680 | printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n"); |
| 681 | 681 | ||
| 682 | retval = nfs4_state_init(); /* nfs4 locking state */ | ||
| 683 | if (retval) | ||
| 684 | return retval; | ||
| 682 | nfsd_stat_init(); /* Statistics */ | 685 | nfsd_stat_init(); /* Statistics */ |
| 683 | nfsd_cache_init(); /* RPC reply cache */ | 686 | nfsd_cache_init(); /* RPC reply cache */ |
| 684 | nfsd_export_init(); /* Exports table */ | 687 | nfsd_export_init(); /* Exports table */ |
| 685 | nfsd_lockd_init(); /* lockd->nfsd callbacks */ | 688 | nfsd_lockd_init(); /* lockd->nfsd callbacks */ |
| 686 | nfs4_state_init(); /* NFSv4 locking state */ | ||
| 687 | nfsd_idmap_init(); /* Name to ID mapping */ | 689 | nfsd_idmap_init(); /* Name to ID mapping */ |
| 688 | if (proc_mkdir("fs/nfs", NULL)) { | 690 | if (proc_mkdir("fs/nfs", NULL)) { |
| 689 | struct proc_dir_entry *entry; | 691 | struct proc_dir_entry *entry; |
| @@ -712,6 +714,7 @@ static void __exit exit_nfsd(void) | |||
| 712 | nfsd_stat_shutdown(); | 714 | nfsd_stat_shutdown(); |
| 713 | nfsd_lockd_shutdown(); | 715 | nfsd_lockd_shutdown(); |
| 714 | nfsd_idmap_shutdown(); | 716 | nfsd_idmap_shutdown(); |
| 717 | nfsd4_free_slabs(); | ||
| 715 | unregister_filesystem(&nfsd_fs_type); | 718 | unregister_filesystem(&nfsd_fs_type); |
| 716 | } | 719 | } |
| 717 | 720 | ||
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index a8c89ae4c743..1190aeaa92be 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
| @@ -349,9 +349,7 @@ nfsd_svc(unsigned short port, int nrservs) | |||
| 349 | error = nfsd_racache_init(2*nrservs); | 349 | error = nfsd_racache_init(2*nrservs); |
| 350 | if (error<0) | 350 | if (error<0) |
| 351 | goto out; | 351 | goto out; |
| 352 | error = nfs4_state_start(); | 352 | nfs4_state_start(); |
| 353 | if (error<0) | ||
| 354 | goto out; | ||
| 355 | 353 | ||
| 356 | nfsd_reset_versions(); | 354 | nfsd_reset_versions(); |
| 357 | 355 | ||
| @@ -546,10 +544,8 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) | |||
| 546 | /* Now call the procedure handler, and encode NFS status. */ | 544 | /* Now call the procedure handler, and encode NFS status. */ |
| 547 | nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); | 545 | nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); |
| 548 | nfserr = map_new_errors(rqstp->rq_vers, nfserr); | 546 | nfserr = map_new_errors(rqstp->rq_vers, nfserr); |
| 549 | if (nfserr == nfserr_jukebox && rqstp->rq_vers == 2) | ||
| 550 | nfserr = nfserr_dropit; | ||
| 551 | if (nfserr == nfserr_dropit) { | 547 | if (nfserr == nfserr_dropit) { |
| 552 | dprintk("nfsd: Dropping request due to malloc failure!\n"); | 548 | dprintk("nfsd: Dropping request; may be revisited later\n"); |
| 553 | nfsd_cache_update(rqstp, RC_NOCACHE, NULL); | 549 | nfsd_cache_update(rqstp, RC_NOCACHE, NULL); |
| 554 | return 0; | 550 | return 0; |
| 555 | } | 551 | } |
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index cb3e7fadb772..986f9b32083c 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c | |||
| @@ -523,6 +523,10 @@ nfssvc_encode_entry(void *ccdv, const char *name, | |||
| 523 | cd->common.err = nfserr_toosmall; | 523 | cd->common.err = nfserr_toosmall; |
| 524 | return -EINVAL; | 524 | return -EINVAL; |
| 525 | } | 525 | } |
| 526 | if (ino > ~((u32) 0)) { | ||
| 527 | cd->common.err = nfserr_fbig; | ||
| 528 | return -EINVAL; | ||
| 529 | } | ||
| 526 | *p++ = xdr_one; /* mark entry present */ | 530 | *p++ = xdr_one; /* mark entry present */ |
| 527 | *p++ = htonl((u32) ino); /* file id */ | 531 | *p++ = htonl((u32) ino); /* file id */ |
| 528 | p = xdr_encode_array(p, name, namlen);/* name length & name */ | 532 | p = xdr_encode_array(p, name, namlen);/* name length & name */ |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 7867151ebb83..cec78c82b1f9 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -295,7 +295,8 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | |||
| 295 | if (!iap->ia_valid) | 295 | if (!iap->ia_valid) |
| 296 | goto out; | 296 | goto out; |
| 297 | 297 | ||
| 298 | /* NFSv2 does not differentiate between "set-[ac]time-to-now" | 298 | /* |
| 299 | * NFSv2 does not differentiate between "set-[ac]time-to-now" | ||
| 299 | * which only requires access, and "set-[ac]time-to-X" which | 300 | * which only requires access, and "set-[ac]time-to-X" which |
| 300 | * requires ownership. | 301 | * requires ownership. |
| 301 | * So if it looks like it might be "set both to the same time which | 302 | * So if it looks like it might be "set both to the same time which |
| @@ -308,25 +309,33 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | |||
| 308 | */ | 309 | */ |
| 309 | #define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET) | 310 | #define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET) |
| 310 | #define MAX_TOUCH_TIME_ERROR (30*60) | 311 | #define MAX_TOUCH_TIME_ERROR (30*60) |
| 311 | if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET | 312 | if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET && |
| 312 | && iap->ia_mtime.tv_sec == iap->ia_atime.tv_sec | 313 | iap->ia_mtime.tv_sec == iap->ia_atime.tv_sec) { |
| 313 | ) { | 314 | /* |
| 314 | /* Looks probable. Now just make sure time is in the right ballpark. | 315 | * Looks probable. |
| 315 | * Solaris, at least, doesn't seem to care what the time request is. | 316 | * |
| 316 | * We require it be within 30 minutes of now. | 317 | * Now just make sure time is in the right ballpark. |
| 317 | */ | 318 | * Solaris, at least, doesn't seem to care what the time |
| 318 | time_t delta = iap->ia_atime.tv_sec - get_seconds(); | 319 | * request is. We require it be within 30 minutes of now. |
| 319 | if (delta<0) delta = -delta; | ||
| 320 | if (delta < MAX_TOUCH_TIME_ERROR && | ||
| 321 | inode_change_ok(inode, iap) != 0) { | ||
| 322 | /* turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME | ||
| 323 | * this will cause notify_change to set these times to "now" | ||
| 324 | */ | 320 | */ |
| 325 | iap->ia_valid &= ~BOTH_TIME_SET; | 321 | time_t delta = iap->ia_atime.tv_sec - get_seconds(); |
| 326 | } | 322 | if (delta < 0) |
| 323 | delta = -delta; | ||
| 324 | if (delta < MAX_TOUCH_TIME_ERROR && | ||
| 325 | inode_change_ok(inode, iap) != 0) { | ||
| 326 | /* | ||
| 327 | * Turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME. | ||
| 328 | * This will cause notify_change to set these times | ||
| 329 | * to "now" | ||
| 330 | */ | ||
| 331 | iap->ia_valid &= ~BOTH_TIME_SET; | ||
| 332 | } | ||
| 327 | } | 333 | } |
| 328 | 334 | ||
| 329 | /* The size case is special. It changes the file as well as the attributes. */ | 335 | /* |
| 336 | * The size case is special. | ||
| 337 | * It changes the file as well as the attributes. | ||
| 338 | */ | ||
| 330 | if (iap->ia_valid & ATTR_SIZE) { | 339 | if (iap->ia_valid & ATTR_SIZE) { |
| 331 | if (iap->ia_size < inode->i_size) { | 340 | if (iap->ia_size < inode->i_size) { |
| 332 | err = nfsd_permission(rqstp, fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE); | 341 | err = nfsd_permission(rqstp, fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE); |
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index e452256d3f72..604a0d786bc6 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h | |||
| @@ -153,19 +153,21 @@ extern int nfsd_max_blksize; | |||
| 153 | */ | 153 | */ |
| 154 | #ifdef CONFIG_NFSD_V4 | 154 | #ifdef CONFIG_NFSD_V4 |
| 155 | extern unsigned int max_delegations; | 155 | extern unsigned int max_delegations; |
| 156 | void nfs4_state_init(void); | 156 | int nfs4_state_init(void); |
| 157 | int nfs4_state_start(void); | 157 | void nfsd4_free_slabs(void); |
| 158 | void nfs4_state_start(void); | ||
| 158 | void nfs4_state_shutdown(void); | 159 | void nfs4_state_shutdown(void); |
| 159 | time_t nfs4_lease_time(void); | 160 | time_t nfs4_lease_time(void); |
| 160 | void nfs4_reset_lease(time_t leasetime); | 161 | void nfs4_reset_lease(time_t leasetime); |
| 161 | int nfs4_reset_recoverydir(char *recdir); | 162 | int nfs4_reset_recoverydir(char *recdir); |
| 162 | #else | 163 | #else |
| 163 | static inline void nfs4_state_init(void){}; | 164 | static inline int nfs4_state_init(void) { return 0; } |
| 164 | static inline int nfs4_state_start(void){return 0;} | 165 | static inline void nfsd4_free_slabs(void) { } |
| 165 | static inline void nfs4_state_shutdown(void){} | 166 | static inline void nfs4_state_start(void) { } |
| 166 | static inline time_t nfs4_lease_time(void){return 0;} | 167 | static inline void nfs4_state_shutdown(void) { } |
| 167 | static inline void nfs4_reset_lease(time_t leasetime){} | 168 | static inline time_t nfs4_lease_time(void) { return 0; } |
| 168 | static inline int nfs4_reset_recoverydir(char *recdir) {return 0;} | 169 | static inline void nfs4_reset_lease(time_t leasetime) { } |
| 170 | static inline int nfs4_reset_recoverydir(char *recdir) { return 0; } | ||
| 169 | #endif | 171 | #endif |
| 170 | 172 | ||
| 171 | /* | 173 | /* |
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h index 11e568ee0eeb..d1941cb965e9 100644 --- a/include/linux/nfsd/nfsfh.h +++ b/include/linux/nfsd/nfsfh.h | |||
| @@ -150,17 +150,7 @@ typedef struct svc_fh { | |||
| 150 | struct timespec fh_pre_ctime; /* ctime before oper */ | 150 | struct timespec fh_pre_ctime; /* ctime before oper */ |
| 151 | 151 | ||
| 152 | /* Post-op attributes saved in fh_unlock */ | 152 | /* Post-op attributes saved in fh_unlock */ |
| 153 | umode_t fh_post_mode; /* i_mode */ | 153 | struct kstat fh_post_attr; /* full attrs after operation */ |
| 154 | nlink_t fh_post_nlink; /* i_nlink */ | ||
| 155 | uid_t fh_post_uid; /* i_uid */ | ||
| 156 | gid_t fh_post_gid; /* i_gid */ | ||
| 157 | __u64 fh_post_size; /* i_size */ | ||
| 158 | unsigned long fh_post_blocks; /* i_blocks */ | ||
| 159 | unsigned long fh_post_blksize;/* i_blksize */ | ||
| 160 | __be32 fh_post_rdev[2];/* i_rdev */ | ||
| 161 | struct timespec fh_post_atime; /* i_atime */ | ||
| 162 | struct timespec fh_post_mtime; /* i_mtime */ | ||
| 163 | struct timespec fh_post_ctime; /* i_ctime */ | ||
| 164 | #endif /* CONFIG_NFSD_V3 */ | 154 | #endif /* CONFIG_NFSD_V3 */ |
| 165 | 155 | ||
| 166 | } svc_fh; | 156 | } svc_fh; |
| @@ -297,36 +287,12 @@ fill_pre_wcc(struct svc_fh *fhp) | |||
| 297 | if (!fhp->fh_pre_saved) { | 287 | if (!fhp->fh_pre_saved) { |
| 298 | fhp->fh_pre_mtime = inode->i_mtime; | 288 | fhp->fh_pre_mtime = inode->i_mtime; |
| 299 | fhp->fh_pre_ctime = inode->i_ctime; | 289 | fhp->fh_pre_ctime = inode->i_ctime; |
| 300 | fhp->fh_pre_size = inode->i_size; | 290 | fhp->fh_pre_size = inode->i_size; |
| 301 | fhp->fh_pre_saved = 1; | 291 | fhp->fh_pre_saved = 1; |
| 302 | } | 292 | } |
| 303 | } | 293 | } |
| 304 | 294 | ||
| 305 | /* | 295 | extern void fill_post_wcc(struct svc_fh *); |
| 306 | * Fill in the post_op attr for the wcc data | ||
| 307 | */ | ||
| 308 | static inline void | ||
| 309 | fill_post_wcc(struct svc_fh *fhp) | ||
| 310 | { | ||
| 311 | struct inode *inode = fhp->fh_dentry->d_inode; | ||
| 312 | |||
| 313 | if (fhp->fh_post_saved) | ||
| 314 | printk("nfsd: inode locked twice during operation.\n"); | ||
| 315 | |||
| 316 | fhp->fh_post_mode = inode->i_mode; | ||
| 317 | fhp->fh_post_nlink = inode->i_nlink; | ||
| 318 | fhp->fh_post_uid = inode->i_uid; | ||
| 319 | fhp->fh_post_gid = inode->i_gid; | ||
| 320 | fhp->fh_post_size = inode->i_size; | ||
| 321 | fhp->fh_post_blksize = BLOCK_SIZE; | ||
| 322 | fhp->fh_post_blocks = inode->i_blocks; | ||
| 323 | fhp->fh_post_rdev[0] = htonl((u32)imajor(inode)); | ||
| 324 | fhp->fh_post_rdev[1] = htonl((u32)iminor(inode)); | ||
| 325 | fhp->fh_post_atime = inode->i_atime; | ||
| 326 | fhp->fh_post_mtime = inode->i_mtime; | ||
| 327 | fhp->fh_post_ctime = inode->i_ctime; | ||
| 328 | fhp->fh_post_saved = 1; | ||
| 329 | } | ||
| 330 | #else | 296 | #else |
| 331 | #define fill_pre_wcc(ignored) | 297 | #define fill_pre_wcc(ignored) |
| 332 | #define fill_post_wcc(notused) | 298 | #define fill_post_wcc(notused) |
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h index 1b653267133a..b0ddfb41c790 100644 --- a/include/linux/nfsd/xdr4.h +++ b/include/linux/nfsd/xdr4.h | |||
| @@ -428,8 +428,8 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp) | |||
| 428 | cinfo->atomic = 1; | 428 | cinfo->atomic = 1; |
| 429 | cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec; | 429 | cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec; |
| 430 | cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec; | 430 | cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec; |
| 431 | cinfo->after_ctime_sec = fhp->fh_post_ctime.tv_sec; | 431 | cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec; |
| 432 | cinfo->after_ctime_nsec = fhp->fh_post_ctime.tv_nsec; | 432 | cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec; |
| 433 | } | 433 | } |
| 434 | 434 | ||
| 435 | int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *); | 435 | int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *); |
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index 3699dff7db8f..bd7a6b0a87af 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h | |||
| @@ -136,16 +136,6 @@ sunrpc_cache_update(struct cache_detail *detail, | |||
| 136 | struct cache_head *new, struct cache_head *old, int hash); | 136 | struct cache_head *new, struct cache_head *old, int hash); |
| 137 | 137 | ||
| 138 | 138 | ||
| 139 | #define cache_for_each(pos, detail, index, member) \ | ||
| 140 | for (({read_lock(&(detail)->hash_lock); index = (detail)->hash_size;}) ; \ | ||
| 141 | ({if (index==0)read_unlock(&(detail)->hash_lock); index--;}); \ | ||
| 142 | ) \ | ||
| 143 | for (pos = container_of((detail)->hash_table[index], typeof(*pos), member); \ | ||
| 144 | &pos->member; \ | ||
| 145 | pos = container_of(pos->member.next, typeof(*pos), member)) | ||
| 146 | |||
| 147 | |||
| 148 | |||
| 149 | extern void cache_clean_deferred(void *owner); | 139 | extern void cache_clean_deferred(void *owner); |
| 150 | 140 | ||
| 151 | static inline struct cache_head *cache_get(struct cache_head *h) | 141 | static inline struct cache_head *cache_get(struct cache_head *h) |
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 7da7050f06c3..73940df6c460 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
| @@ -631,7 +631,8 @@ svc_safe_putnetobj(struct kvec *resv, struct xdr_netobj *o) | |||
| 631 | return 0; | 631 | return 0; |
| 632 | } | 632 | } |
| 633 | 633 | ||
| 634 | /* Verify the checksum on the header and return SVC_OK on success. | 634 | /* |
| 635 | * Verify the checksum on the header and return SVC_OK on success. | ||
| 635 | * Otherwise, return SVC_DROP (in the case of a bad sequence number) | 636 | * Otherwise, return SVC_DROP (in the case of a bad sequence number) |
| 636 | * or return SVC_DENIED and indicate error in authp. | 637 | * or return SVC_DENIED and indicate error in authp. |
| 637 | */ | 638 | */ |
| @@ -961,6 +962,78 @@ gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip) | |||
| 961 | } | 962 | } |
| 962 | 963 | ||
| 963 | /* | 964 | /* |
| 965 | * Having read the cred already and found we're in the context | ||
| 966 | * initiation case, read the verifier and initiate (or check the results | ||
| 967 | * of) upcalls to userspace for help with context initiation. If | ||
| 968 | * the upcall results are available, write the verifier and result. | ||
| 969 | * Otherwise, drop the request pending an answer to the upcall. | ||
| 970 | */ | ||
| 971 | static int svcauth_gss_handle_init(struct svc_rqst *rqstp, | ||
| 972 | struct rpc_gss_wire_cred *gc, __be32 *authp) | ||
| 973 | { | ||
| 974 | struct kvec *argv = &rqstp->rq_arg.head[0]; | ||
| 975 | struct kvec *resv = &rqstp->rq_res.head[0]; | ||
| 976 | struct xdr_netobj tmpobj; | ||
| 977 | struct rsi *rsip, rsikey; | ||
| 978 | |||
| 979 | /* Read the verifier; should be NULL: */ | ||
| 980 | *authp = rpc_autherr_badverf; | ||
| 981 | if (argv->iov_len < 2 * 4) | ||
| 982 | return SVC_DENIED; | ||
| 983 | if (svc_getnl(argv) != RPC_AUTH_NULL) | ||
| 984 | return SVC_DENIED; | ||
| 985 | if (svc_getnl(argv) != 0) | ||
| 986 | return SVC_DENIED; | ||
| 987 | |||
| 988 | /* Martial context handle and token for upcall: */ | ||
| 989 | *authp = rpc_autherr_badcred; | ||
| 990 | if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) | ||
| 991 | return SVC_DENIED; | ||
| 992 | memset(&rsikey, 0, sizeof(rsikey)); | ||
| 993 | if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx)) | ||
| 994 | return SVC_DROP; | ||
| 995 | *authp = rpc_autherr_badverf; | ||
| 996 | if (svc_safe_getnetobj(argv, &tmpobj)) { | ||
| 997 | kfree(rsikey.in_handle.data); | ||
| 998 | return SVC_DENIED; | ||
| 999 | } | ||
| 1000 | if (dup_netobj(&rsikey.in_token, &tmpobj)) { | ||
| 1001 | kfree(rsikey.in_handle.data); | ||
| 1002 | return SVC_DROP; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | /* Perform upcall, or find upcall result: */ | ||
| 1006 | rsip = rsi_lookup(&rsikey); | ||
| 1007 | rsi_free(&rsikey); | ||
| 1008 | if (!rsip) | ||
| 1009 | return SVC_DROP; | ||
| 1010 | switch (cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) { | ||
| 1011 | case -EAGAIN: | ||
| 1012 | case -ETIMEDOUT: | ||
| 1013 | case -ENOENT: | ||
| 1014 | /* No upcall result: */ | ||
| 1015 | return SVC_DROP; | ||
| 1016 | case 0: | ||
| 1017 | /* Got an answer to the upcall; use it: */ | ||
| 1018 | if (gss_write_init_verf(rqstp, rsip)) | ||
| 1019 | return SVC_DROP; | ||
| 1020 | if (resv->iov_len + 4 > PAGE_SIZE) | ||
| 1021 | return SVC_DROP; | ||
| 1022 | svc_putnl(resv, RPC_SUCCESS); | ||
| 1023 | if (svc_safe_putnetobj(resv, &rsip->out_handle)) | ||
| 1024 | return SVC_DROP; | ||
| 1025 | if (resv->iov_len + 3 * 4 > PAGE_SIZE) | ||
| 1026 | return SVC_DROP; | ||
| 1027 | svc_putnl(resv, rsip->major_status); | ||
| 1028 | svc_putnl(resv, rsip->minor_status); | ||
| 1029 | svc_putnl(resv, GSS_SEQ_WIN); | ||
| 1030 | if (svc_safe_putnetobj(resv, &rsip->out_token)) | ||
| 1031 | return SVC_DROP; | ||
| 1032 | } | ||
| 1033 | return SVC_COMPLETE; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | /* | ||
| 964 | * Accept an rpcsec packet. | 1037 | * Accept an rpcsec packet. |
| 965 | * If context establishment, punt to user space | 1038 | * If context establishment, punt to user space |
| 966 | * If data exchange, verify/decrypt | 1039 | * If data exchange, verify/decrypt |
| @@ -974,11 +1047,9 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
| 974 | struct kvec *argv = &rqstp->rq_arg.head[0]; | 1047 | struct kvec *argv = &rqstp->rq_arg.head[0]; |
| 975 | struct kvec *resv = &rqstp->rq_res.head[0]; | 1048 | struct kvec *resv = &rqstp->rq_res.head[0]; |
| 976 | u32 crlen; | 1049 | u32 crlen; |
| 977 | struct xdr_netobj tmpobj; | ||
| 978 | struct gss_svc_data *svcdata = rqstp->rq_auth_data; | 1050 | struct gss_svc_data *svcdata = rqstp->rq_auth_data; |
| 979 | struct rpc_gss_wire_cred *gc; | 1051 | struct rpc_gss_wire_cred *gc; |
| 980 | struct rsc *rsci = NULL; | 1052 | struct rsc *rsci = NULL; |
| 981 | struct rsi *rsip, rsikey; | ||
| 982 | __be32 *rpcstart; | 1053 | __be32 *rpcstart; |
| 983 | __be32 *reject_stat = resv->iov_base + resv->iov_len; | 1054 | __be32 *reject_stat = resv->iov_base + resv->iov_len; |
| 984 | int ret; | 1055 | int ret; |
| @@ -1023,30 +1094,14 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
| 1023 | if ((gc->gc_proc != RPC_GSS_PROC_DATA) && (rqstp->rq_proc != 0)) | 1094 | if ((gc->gc_proc != RPC_GSS_PROC_DATA) && (rqstp->rq_proc != 0)) |
| 1024 | goto auth_err; | 1095 | goto auth_err; |
| 1025 | 1096 | ||
| 1026 | /* | ||
| 1027 | * We've successfully parsed the credential. Let's check out the | ||
| 1028 | * verifier. An AUTH_NULL verifier is allowed (and required) for | ||
| 1029 | * INIT and CONTINUE_INIT requests. AUTH_RPCSEC_GSS is required for | ||
| 1030 | * PROC_DATA and PROC_DESTROY. | ||
| 1031 | * | ||
| 1032 | * AUTH_NULL verifier is 0 (AUTH_NULL), 0 (length). | ||
| 1033 | * AUTH_RPCSEC_GSS verifier is: | ||
| 1034 | * 6 (AUTH_RPCSEC_GSS), length, checksum. | ||
| 1035 | * checksum is calculated over rpcheader from xid up to here. | ||
| 1036 | */ | ||
| 1037 | *authp = rpc_autherr_badverf; | 1097 | *authp = rpc_autherr_badverf; |
| 1038 | switch (gc->gc_proc) { | 1098 | switch (gc->gc_proc) { |
| 1039 | case RPC_GSS_PROC_INIT: | 1099 | case RPC_GSS_PROC_INIT: |
| 1040 | case RPC_GSS_PROC_CONTINUE_INIT: | 1100 | case RPC_GSS_PROC_CONTINUE_INIT: |
| 1041 | if (argv->iov_len < 2 * 4) | 1101 | return svcauth_gss_handle_init(rqstp, gc, authp); |
| 1042 | goto auth_err; | ||
| 1043 | if (svc_getnl(argv) != RPC_AUTH_NULL) | ||
| 1044 | goto auth_err; | ||
| 1045 | if (svc_getnl(argv) != 0) | ||
| 1046 | goto auth_err; | ||
| 1047 | break; | ||
| 1048 | case RPC_GSS_PROC_DATA: | 1102 | case RPC_GSS_PROC_DATA: |
| 1049 | case RPC_GSS_PROC_DESTROY: | 1103 | case RPC_GSS_PROC_DESTROY: |
| 1104 | /* Look up the context, and check the verifier: */ | ||
| 1050 | *authp = rpcsec_gsserr_credproblem; | 1105 | *authp = rpcsec_gsserr_credproblem; |
| 1051 | rsci = gss_svc_searchbyctx(&gc->gc_ctx); | 1106 | rsci = gss_svc_searchbyctx(&gc->gc_ctx); |
| 1052 | if (!rsci) | 1107 | if (!rsci) |
| @@ -1067,51 +1122,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
| 1067 | 1122 | ||
| 1068 | /* now act upon the command: */ | 1123 | /* now act upon the command: */ |
| 1069 | switch (gc->gc_proc) { | 1124 | switch (gc->gc_proc) { |
| 1070 | case RPC_GSS_PROC_INIT: | ||
| 1071 | case RPC_GSS_PROC_CONTINUE_INIT: | ||
| 1072 | *authp = rpc_autherr_badcred; | ||
| 1073 | if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) | ||
| 1074 | goto auth_err; | ||
| 1075 | memset(&rsikey, 0, sizeof(rsikey)); | ||
| 1076 | if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx)) | ||
| 1077 | goto drop; | ||
| 1078 | *authp = rpc_autherr_badverf; | ||
| 1079 | if (svc_safe_getnetobj(argv, &tmpobj)) { | ||
| 1080 | kfree(rsikey.in_handle.data); | ||
| 1081 | goto auth_err; | ||
| 1082 | } | ||
| 1083 | if (dup_netobj(&rsikey.in_token, &tmpobj)) { | ||
| 1084 | kfree(rsikey.in_handle.data); | ||
| 1085 | goto drop; | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | rsip = rsi_lookup(&rsikey); | ||
| 1089 | rsi_free(&rsikey); | ||
| 1090 | if (!rsip) { | ||
| 1091 | goto drop; | ||
| 1092 | } | ||
| 1093 | switch(cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) { | ||
| 1094 | case -EAGAIN: | ||
| 1095 | case -ETIMEDOUT: | ||
| 1096 | case -ENOENT: | ||
| 1097 | goto drop; | ||
| 1098 | case 0: | ||
| 1099 | if (gss_write_init_verf(rqstp, rsip)) | ||
| 1100 | goto drop; | ||
| 1101 | if (resv->iov_len + 4 > PAGE_SIZE) | ||
| 1102 | goto drop; | ||
| 1103 | svc_putnl(resv, RPC_SUCCESS); | ||
| 1104 | if (svc_safe_putnetobj(resv, &rsip->out_handle)) | ||
| 1105 | goto drop; | ||
| 1106 | if (resv->iov_len + 3 * 4 > PAGE_SIZE) | ||
| 1107 | goto drop; | ||
| 1108 | svc_putnl(resv, rsip->major_status); | ||
| 1109 | svc_putnl(resv, rsip->minor_status); | ||
| 1110 | svc_putnl(resv, GSS_SEQ_WIN); | ||
| 1111 | if (svc_safe_putnetobj(resv, &rsip->out_token)) | ||
| 1112 | goto drop; | ||
| 1113 | } | ||
| 1114 | goto complete; | ||
| 1115 | case RPC_GSS_PROC_DESTROY: | 1125 | case RPC_GSS_PROC_DESTROY: |
| 1116 | if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq)) | 1126 | if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq)) |
| 1117 | goto auth_err; | 1127 | goto auth_err; |
| @@ -1158,7 +1168,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
| 1158 | goto out; | 1168 | goto out; |
| 1159 | } | 1169 | } |
| 1160 | auth_err: | 1170 | auth_err: |
| 1161 | /* Restore write pointer to original value: */ | 1171 | /* Restore write pointer to its original value: */ |
| 1162 | xdr_ressize_check(rqstp, reject_stat); | 1172 | xdr_ressize_check(rqstp, reject_stat); |
| 1163 | ret = SVC_DENIED; | 1173 | ret = SVC_DENIED; |
| 1164 | goto out; | 1174 | goto out; |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 55ea6df069de..a4a6bf7deaa4 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
| @@ -777,6 +777,30 @@ svc_register(struct svc_serv *serv, int proto, unsigned short port) | |||
| 777 | } | 777 | } |
| 778 | 778 | ||
| 779 | /* | 779 | /* |
| 780 | * Printk the given error with the address of the client that caused it. | ||
| 781 | */ | ||
| 782 | static int | ||
| 783 | __attribute__ ((format (printf, 2, 3))) | ||
| 784 | svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) | ||
| 785 | { | ||
| 786 | va_list args; | ||
| 787 | int r; | ||
| 788 | char buf[RPC_MAX_ADDRBUFLEN]; | ||
| 789 | |||
| 790 | if (!net_ratelimit()) | ||
| 791 | return 0; | ||
| 792 | |||
| 793 | printk(KERN_WARNING "svc: %s: ", | ||
| 794 | svc_print_addr(rqstp, buf, sizeof(buf))); | ||
| 795 | |||
| 796 | va_start(args, fmt); | ||
| 797 | r = vprintk(fmt, args); | ||
| 798 | va_end(args); | ||
| 799 | |||
| 800 | return r; | ||
| 801 | } | ||
| 802 | |||
| 803 | /* | ||
| 780 | * Process the RPC request. | 804 | * Process the RPC request. |
| 781 | */ | 805 | */ |
| 782 | int | 806 | int |
| @@ -963,14 +987,13 @@ svc_process(struct svc_rqst *rqstp) | |||
| 963 | return 0; | 987 | return 0; |
| 964 | 988 | ||
| 965 | err_short_len: | 989 | err_short_len: |
| 966 | if (net_ratelimit()) | 990 | svc_printk(rqstp, "short len %Zd, dropping request\n", |
| 967 | printk("svc: short len %Zd, dropping request\n", argv->iov_len); | 991 | argv->iov_len); |
| 968 | 992 | ||
| 969 | goto dropit; /* drop request */ | 993 | goto dropit; /* drop request */ |
| 970 | 994 | ||
| 971 | err_bad_dir: | 995 | err_bad_dir: |
| 972 | if (net_ratelimit()) | 996 | svc_printk(rqstp, "bad direction %d, dropping request\n", dir); |
| 973 | printk("svc: bad direction %d, dropping request\n", dir); | ||
| 974 | 997 | ||
| 975 | serv->sv_stats->rpcbadfmt++; | 998 | serv->sv_stats->rpcbadfmt++; |
| 976 | goto dropit; /* drop request */ | 999 | goto dropit; /* drop request */ |
| @@ -1000,8 +1023,7 @@ err_bad_prog: | |||
| 1000 | goto sendit; | 1023 | goto sendit; |
| 1001 | 1024 | ||
| 1002 | err_bad_vers: | 1025 | err_bad_vers: |
| 1003 | if (net_ratelimit()) | 1026 | svc_printk(rqstp, "unknown version (%d for prog %d, %s)\n", |
| 1004 | printk("svc: unknown version (%d for prog %d, %s)\n", | ||
| 1005 | vers, prog, progp->pg_name); | 1027 | vers, prog, progp->pg_name); |
| 1006 | 1028 | ||
| 1007 | serv->sv_stats->rpcbadfmt++; | 1029 | serv->sv_stats->rpcbadfmt++; |
| @@ -1011,16 +1033,14 @@ err_bad_vers: | |||
| 1011 | goto sendit; | 1033 | goto sendit; |
| 1012 | 1034 | ||
| 1013 | err_bad_proc: | 1035 | err_bad_proc: |
| 1014 | if (net_ratelimit()) | 1036 | svc_printk(rqstp, "unknown procedure (%d)\n", proc); |
| 1015 | printk("svc: unknown procedure (%d)\n", proc); | ||
| 1016 | 1037 | ||
| 1017 | serv->sv_stats->rpcbadfmt++; | 1038 | serv->sv_stats->rpcbadfmt++; |
| 1018 | svc_putnl(resv, RPC_PROC_UNAVAIL); | 1039 | svc_putnl(resv, RPC_PROC_UNAVAIL); |
| 1019 | goto sendit; | 1040 | goto sendit; |
| 1020 | 1041 | ||
| 1021 | err_garbage: | 1042 | err_garbage: |
| 1022 | if (net_ratelimit()) | 1043 | svc_printk(rqstp, "failed to decode args\n"); |
| 1023 | printk("svc: failed to decode args\n"); | ||
| 1024 | 1044 | ||
| 1025 | rpc_stat = rpc_garbage_args; | 1045 | rpc_stat = rpc_garbage_args; |
| 1026 | err_bad: | 1046 | err_bad: |
