vfs.c (62813858fb5d1fb661433d7884668aa111115a35) vfs.c (4ac7249ea5a0ceef9f8269f63f33cc873c3fac61)
1/*
2 * File operations used by nfsd. Some of these have been ripped from
3 * other parts of the kernel because they weren't exported, others
4 * are partial duplicates with added or changed functionality.
5 *
6 * Note that several functions dget() the dentry upon which they want
7 * to act, most notably those that create directory entries. Response
8 * dentry's are dput()'d if necessary in the release callback.

--- 454 unchanged lines hidden (view full) ---

463 if (size_change)
464 put_write_access(inode);
465 if (!err)
466 commit_metadata(fhp);
467out:
468 return err;
469}
470
1/*
2 * File operations used by nfsd. Some of these have been ripped from
3 * other parts of the kernel because they weren't exported, others
4 * are partial duplicates with added or changed functionality.
5 *
6 * Note that several functions dget() the dentry upon which they want
7 * to act, most notably those that create directory entries. Response
8 * dentry's are dput()'d if necessary in the release callback.

--- 454 unchanged lines hidden (view full) ---

463 if (size_change)
464 put_write_access(inode);
465 if (!err)
466 commit_metadata(fhp);
467out:
468 return err;
469}
470
471#if defined(CONFIG_NFSD_V2_ACL) || \
472 defined(CONFIG_NFSD_V3_ACL) || \
473 defined(CONFIG_NFSD_V4)
474static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
475{
476 ssize_t buflen;
477 ssize_t ret;
478
479 buflen = vfs_getxattr(dentry, key, NULL, 0);
480 if (buflen <= 0)
481 return buflen;
482
483 *buf = kmalloc(buflen, GFP_KERNEL);
484 if (!*buf)
485 return -ENOMEM;
486
487 ret = vfs_getxattr(dentry, key, *buf, buflen);
488 if (ret < 0)
489 kfree(*buf);
490 return ret;
491}
492#endif
493
494#if defined(CONFIG_NFSD_V4)
471#if defined(CONFIG_NFSD_V4)
495static int
496set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
497{
498 int len;
499 size_t buflen;
500 char *buf = NULL;
501 int error = 0;
502
503 buflen = posix_acl_xattr_size(pacl->a_count);
504 buf = kmalloc(buflen, GFP_KERNEL);
505 error = -ENOMEM;
506 if (buf == NULL)
507 goto out;
508
509 len = posix_acl_to_xattr(&init_user_ns, pacl, buf, buflen);
510 if (len < 0) {
511 error = len;
512 goto out;
513 }
514
515 error = vfs_setxattr(dentry, key, buf, len, 0);
516out:
517 kfree(buf);
518 return error;
519}
520
521__be32
522nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
523 struct nfs4_acl *acl)
524{
525 __be32 error;
526 int host_error;
527 struct dentry *dentry;
528 struct inode *inode;
529 struct posix_acl *pacl = NULL, *dpacl = NULL;
530 unsigned int flags = 0;
531
532 /* Get inode */
533 error = fh_verify(rqstp, fhp, 0, NFSD_MAY_SATTR);
534 if (error)
535 return error;
536
537 dentry = fhp->fh_dentry;
538 inode = dentry->d_inode;
539 if (S_ISDIR(inode->i_mode))
540 flags = NFS4_ACL_DIR;
541
542 host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
543 if (host_error == -EINVAL) {
544 return nfserr_attrnotsupp;
545 } else if (host_error < 0)
546 goto out_nfserr;
547
548 host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
549 if (host_error < 0)
550 goto out_release;
551
552 if (S_ISDIR(inode->i_mode))
553 host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
554
555out_release:
556 posix_acl_release(pacl);
557 posix_acl_release(dpacl);
558out_nfserr:
559 if (host_error == -EOPNOTSUPP)
560 return nfserr_attrnotsupp;
561 else
562 return nfserrno(host_error);
563}
564
565static struct posix_acl *
566_get_posix_acl(struct dentry *dentry, char *key)
567{
568 void *buf = NULL;
569 struct posix_acl *pacl = NULL;
570 int buflen;
571
572 buflen = nfsd_getxattr(dentry, key, &buf);
573 if (!buflen)
574 buflen = -ENODATA;
575 if (buflen <= 0)
576 return ERR_PTR(buflen);
577
578 pacl = posix_acl_from_xattr(&init_user_ns, buf, buflen);
579 kfree(buf);
580 return pacl;
581}
582
583int
584nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl)
585{
586 struct inode *inode = dentry->d_inode;
587 int error = 0;
588 struct posix_acl *pacl = NULL, *dpacl = NULL;
589 unsigned int flags = 0;
590
591 pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS);
592 if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
593 pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
594 if (IS_ERR(pacl)) {
595 error = PTR_ERR(pacl);
596 pacl = NULL;
597 goto out;
598 }
599
600 if (S_ISDIR(inode->i_mode)) {
601 dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT);
602 if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
603 dpacl = NULL;
604 else if (IS_ERR(dpacl)) {
605 error = PTR_ERR(dpacl);
606 dpacl = NULL;
607 goto out;
608 }
609 flags = NFS4_ACL_DIR;
610 }
611
612 *acl = nfs4_acl_posix_to_nfsv4(pacl, dpacl, flags);
613 if (IS_ERR(*acl)) {
614 error = PTR_ERR(*acl);
615 *acl = NULL;
616 }
617 out:
618 posix_acl_release(pacl);
619 posix_acl_release(dpacl);
620 return error;
621}
622
623/*
624 * NFS junction information is stored in an extended attribute.
625 */
626#define NFSD_JUNCTION_XATTR_NAME XATTR_TRUSTED_PREFIX "junction.nfs"
627
628/**
629 * nfsd4_is_junction - Test if an object could be an NFS junction
630 *

--- 1648 unchanged lines hidden (view full) ---

2279 nfsdstats.ra_size = cache_size;
2280 return 0;
2281
2282out_nomem:
2283 dprintk("nfsd: kmalloc failed, freeing readahead buffers\n");
2284 nfsd_racache_shutdown();
2285 return -ENOMEM;
2286}
472/*
473 * NFS junction information is stored in an extended attribute.
474 */
475#define NFSD_JUNCTION_XATTR_NAME XATTR_TRUSTED_PREFIX "junction.nfs"
476
477/**
478 * nfsd4_is_junction - Test if an object could be an NFS junction
479 *

--- 1648 unchanged lines hidden (view full) ---

2128 nfsdstats.ra_size = cache_size;
2129 return 0;
2130
2131out_nomem:
2132 dprintk("nfsd: kmalloc failed, freeing readahead buffers\n");
2133 nfsd_racache_shutdown();
2134 return -ENOMEM;
2135}
2287
2288#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
2289struct posix_acl *
2290nfsd_get_posix_acl(struct svc_fh *fhp, int type)
2291{
2292 struct inode *inode = fhp->fh_dentry->d_inode;
2293 char *name;
2294 void *value = NULL;
2295 ssize_t size;
2296 struct posix_acl *acl;
2297
2298 if (!IS_POSIXACL(inode))
2299 return ERR_PTR(-EOPNOTSUPP);
2300
2301 switch (type) {
2302 case ACL_TYPE_ACCESS:
2303 name = POSIX_ACL_XATTR_ACCESS;
2304 break;
2305 case ACL_TYPE_DEFAULT:
2306 name = POSIX_ACL_XATTR_DEFAULT;
2307 break;
2308 default:
2309 return ERR_PTR(-EOPNOTSUPP);
2310 }
2311
2312 size = nfsd_getxattr(fhp->fh_dentry, name, &value);
2313 if (size < 0)
2314 return ERR_PTR(size);
2315
2316 acl = posix_acl_from_xattr(&init_user_ns, value, size);
2317 kfree(value);
2318 return acl;
2319}
2320
2321int
2322nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
2323{
2324 struct inode *inode = fhp->fh_dentry->d_inode;
2325 char *name;
2326 void *value = NULL;
2327 size_t size;
2328 int error;
2329
2330 if (!IS_POSIXACL(inode) ||
2331 !inode->i_op->setxattr || !inode->i_op->removexattr)
2332 return -EOPNOTSUPP;
2333 switch(type) {
2334 case ACL_TYPE_ACCESS:
2335 name = POSIX_ACL_XATTR_ACCESS;
2336 break;
2337 case ACL_TYPE_DEFAULT:
2338 name = POSIX_ACL_XATTR_DEFAULT;
2339 break;
2340 default:
2341 return -EOPNOTSUPP;
2342 }
2343
2344 if (acl && acl->a_count) {
2345 size = posix_acl_xattr_size(acl->a_count);
2346 value = kmalloc(size, GFP_KERNEL);
2347 if (!value)
2348 return -ENOMEM;
2349 error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
2350 if (error < 0)
2351 goto getout;
2352 size = error;
2353 } else
2354 size = 0;
2355
2356 error = fh_want_write(fhp);
2357 if (error)
2358 goto getout;
2359 if (size)
2360 error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
2361 else {
2362 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
2363 error = 0;
2364 else {
2365 error = vfs_removexattr(fhp->fh_dentry, name);
2366 if (error == -ENODATA)
2367 error = 0;
2368 }
2369 }
2370 fh_drop_write(fhp);
2371
2372getout:
2373 kfree(value);
2374 return error;
2375}
2376#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */