aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/platforms/ps3/system-bus.c1
-rw-r--r--drivers/hid/hidraw.c12
-rw-r--r--fs/nfsd/nfs3xdr.c59
-rw-r--r--fs/nfsd/nfs4callback.c89
-rw-r--r--fs/nfsd/nfs4idmap.c8
-rw-r--r--fs/nfsd/nfs4proc.c4
-rw-r--r--fs/nfsd/nfs4state.c200
-rw-r--r--fs/nfsd/nfs4xdr.c22
-rw-r--r--fs/nfsd/nfsctl.c7
-rw-r--r--fs/nfsd/nfssvc.c8
-rw-r--r--fs/nfsd/nfsxdr.c4
-rw-r--r--fs/nfsd/vfs.c43
-rw-r--r--include/linux/hid.h20
-rw-r--r--include/linux/hidraw.h6
-rw-r--r--include/linux/nfsd/nfsd.h18
-rw-r--r--include/linux/nfsd/nfsfh.h42
-rw-r--r--include/linux/nfsd/xdr4.h4
-rw-r--r--include/linux/sunrpc/cache.h10
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c144
-rw-r--r--net/sunrpc/svc.c40
20 files changed, 350 insertions, 391 deletions
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index ea0b2c790412..190ff4b59a55 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -440,7 +440,6 @@ static void ps3_system_bus_shutdown(struct device *_dev)
440static int ps3_system_bus_uevent(struct device *_dev, struct kobj_uevent_env *env) 440static int ps3_system_bus_uevent(struct device *_dev, struct kobj_uevent_env *env)
441{ 441{
442 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); 442 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
443 int i = 0, length = 0;
444 443
445 if (add_uevent_var(env, "MODALIAS=ps3:%d", dev->match_id)) 444 if (add_uevent_var(env, "MODALIAS=ps3:%d", dev->match_id))
446 return -ENOMEM; 445 return -ENOMEM;
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 8503197a8131..a702e2f6da7d 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -229,9 +229,15 @@ static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd
229 229
230 if (get_user(len, (int __user *)arg)) 230 if (get_user(len, (int __user *)arg))
231 return -EFAULT; 231 return -EFAULT;
232 if (copy_to_user(*((__u8 **)(user_arg + 232
233 sizeof(__u32))), 233 if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
234 dev->hid->rdesc, len)) 234 return -EINVAL;
235
236 if (copy_to_user(user_arg + offsetof(
237 struct hidraw_report_descriptor,
238 value[0]),
239 dev->hid->rdesc,
240 min(dev->hid->rsize, len)))
235 return -EFAULT; 241 return -EFAULT;
236 return 0; 242 return 0;
237 } 243 }
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 *
174encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, 174encode_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,
203static __be32 * 199static __be32 *
204encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) 200encode_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 */
265void 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
643nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p, 635nfs3svc_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
803static __be32 * 798static __be32 *
804encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, 799encode_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))
874static int 869static int
875encode_entry(struct readdir_cd *ccd, const char *name, int namlen, 870encode_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
349static struct rpc_cred * 350static int do_probe_callback(void *data)
350nfsd4_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
441out_release_clp: 435out_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
450static void
451nfs4_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));
466out:
467 put_nfs4_client(clp);
468}
469
470static 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 }
517out_put_cred: 483out_put_cred:
518 put_rpccred(msg.rpc_cred);
519out:
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
361static void
362shutdown_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
361static inline void 373static inline void
362free_client(struct nfs4_client *clp) 374free_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
377static void 390static void
378shutdown_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
389static void
390expire_client(struct nfs4_client *clp) 391expire_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
464static inline int 463static inline int
465same_name(const char *n1, const char *n2) { 464same_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
469static int 469static int
470cmp_verf(nfs4_verifier *v1, nfs4_verifier *v2) { 470same_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
474static int 475static int
475cmp_clid(clientid_t * cl1, clientid_t * cl2) { 476same_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 */
481static int 482static int
482cmp_creds(struct svc_cred *cr1, struct svc_cred *cr2){ 483same_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
487static void 488static 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
1022static void 1005void
1023nfsd4_free_slabs(void) 1006nfsd4_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
1209static int 1192static int
1210cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) { 1193same_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
1216static struct nfs4_stateowner * 1201static 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
3152void 3142int
3153nfs4_state_init(void) 3143nfs4_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
3187static void 3181static void
@@ -3242,20 +3236,15 @@ __nfs4_state_start(void)
3242 set_max_delegations(); 3236 set_max_delegations();
3243} 3237}
3244 3238
3245int 3239void
3246nfs4_state_start(void) 3240nfs4_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
3261int 3250int
@@ -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/hid.h b/include/linux/hid.h
index 55e51f9f76cb..edb8024d744b 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -29,13 +29,6 @@
29 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic 29 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
30 */ 30 */
31 31
32#include <linux/types.h>
33#include <linux/slab.h>
34#include <linux/list.h>
35#include <linux/timer.h>
36#include <linux/workqueue.h>
37#include <linux/input.h>
38
39/* 32/*
40 * USB HID (Human Interface Device) interface class code 33 * USB HID (Human Interface Device) interface class code
41 */ 34 */
@@ -69,6 +62,17 @@
69#define HID_DT_REPORT (USB_TYPE_CLASS | 0x02) 62#define HID_DT_REPORT (USB_TYPE_CLASS | 0x02)
70#define HID_DT_PHYSICAL (USB_TYPE_CLASS | 0x03) 63#define HID_DT_PHYSICAL (USB_TYPE_CLASS | 0x03)
71 64
65#define HID_MAX_DESCRIPTOR_SIZE 4096
66
67#ifdef __KERNEL__
68
69#include <linux/types.h>
70#include <linux/slab.h>
71#include <linux/list.h>
72#include <linux/timer.h>
73#include <linux/workqueue.h>
74#include <linux/input.h>
75
72/* 76/*
73 * We parse each description item into this structure. Short items data 77 * We parse each description item into this structure. Short items data
74 * values are expanded to 32-bit signed int, long items contain a pointer 78 * values are expanded to 32-bit signed int, long items contain a pointer
@@ -311,7 +315,6 @@ struct hid_global {
311 * This is the local environment. It is persistent up the next main-item. 315 * This is the local environment. It is persistent up the next main-item.
312 */ 316 */
313 317
314#define HID_MAX_DESCRIPTOR_SIZE 4096
315#define HID_MAX_USAGES 8192 318#define HID_MAX_USAGES 8192
316#define HID_DEFAULT_NUM_COLLECTIONS 16 319#define HID_DEFAULT_NUM_COLLECTIONS 16
317 320
@@ -560,4 +563,5 @@ static inline int hid_ff_init(struct hid_device *hid) { return -1; }
560#define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \ 563#define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
561 __FILE__ , ## arg) 564 __FILE__ , ## arg)
562#endif 565#endif
566#endif
563 567
diff --git a/include/linux/hidraw.h b/include/linux/hidraw.h
index 6676cd5e9954..0536f299f7ff 100644
--- a/include/linux/hidraw.h
+++ b/include/linux/hidraw.h
@@ -15,9 +15,11 @@
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 */ 16 */
17 17
18#include <linux/hid.h>
19
18struct hidraw_report_descriptor { 20struct hidraw_report_descriptor {
19 __u32 size; 21 __u32 size;
20 __u8 *value; 22 __u8 value[HID_MAX_DESCRIPTOR_SIZE];
21}; 23};
22 24
23struct hidraw_devinfo { 25struct hidraw_devinfo {
@@ -40,8 +42,6 @@ struct hidraw_devinfo {
40/* kernel-only API declarations */ 42/* kernel-only API declarations */
41#ifdef __KERNEL__ 43#ifdef __KERNEL__
42 44
43#include <linux/hid.h>
44
45struct hidraw { 45struct hidraw {
46 unsigned int minor; 46 unsigned int minor;
47 int exist; 47 int exist;
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
155extern unsigned int max_delegations; 155extern unsigned int max_delegations;
156void nfs4_state_init(void); 156int nfs4_state_init(void);
157int nfs4_state_start(void); 157void nfsd4_free_slabs(void);
158void nfs4_state_start(void);
158void nfs4_state_shutdown(void); 159void nfs4_state_shutdown(void);
159time_t nfs4_lease_time(void); 160time_t nfs4_lease_time(void);
160void nfs4_reset_lease(time_t leasetime); 161void nfs4_reset_lease(time_t leasetime);
161int nfs4_reset_recoverydir(char *recdir); 162int nfs4_reset_recoverydir(char *recdir);
162#else 163#else
163static inline void nfs4_state_init(void){}; 164static inline int nfs4_state_init(void) { return 0; }
164static inline int nfs4_state_start(void){return 0;} 165static inline void nfsd4_free_slabs(void) { }
165static inline void nfs4_state_shutdown(void){} 166static inline void nfs4_state_start(void) { }
166static inline time_t nfs4_lease_time(void){return 0;} 167static inline void nfs4_state_shutdown(void) { }
167static inline void nfs4_reset_lease(time_t leasetime){} 168static inline time_t nfs4_lease_time(void) { return 0; }
168static inline int nfs4_reset_recoverydir(char *recdir) {return 0;} 169static inline void nfs4_reset_lease(time_t leasetime) { }
170static 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/* 295extern void fill_post_wcc(struct svc_fh *);
306 * Fill in the post_op attr for the wcc data
307 */
308static inline void
309fill_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
435int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *); 435int 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
149extern void cache_clean_deferred(void *owner); 139extern void cache_clean_deferred(void *owner);
150 140
151static inline struct cache_head *cache_get(struct cache_head *h) 141static 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 */
971static 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 }
1160auth_err: 1170auth_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 */
782static int
783__attribute__ ((format (printf, 2, 3)))
784svc_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 */
782int 806int
@@ -963,14 +987,13 @@ svc_process(struct svc_rqst *rqstp)
963 return 0; 987 return 0;
964 988
965err_short_len: 989err_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
971err_bad_dir: 995err_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
1002err_bad_vers: 1025err_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
1013err_bad_proc: 1035err_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
1021err_garbage: 1042err_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;
1026err_bad: 1046err_bad: