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) */ | |