aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c125
1 files changed, 48 insertions, 77 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index bb36b4304491..eef0576a7785 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -48,8 +48,8 @@
48#include <linux/fsnotify.h> 48#include <linux/fsnotify.h>
49#include <linux/posix_acl.h> 49#include <linux/posix_acl.h>
50#include <linux/posix_acl_xattr.h> 50#include <linux/posix_acl_xattr.h>
51#ifdef CONFIG_NFSD_V4
52#include <linux/xattr.h> 51#include <linux/xattr.h>
52#ifdef CONFIG_NFSD_V4
53#include <linux/nfs4.h> 53#include <linux/nfs4.h>
54#include <linux/nfs4_acl.h> 54#include <linux/nfs4_acl.h>
55#include <linux/nfsd_idmap.h> 55#include <linux/nfsd_idmap.h>
@@ -365,8 +365,30 @@ out_nfserr:
365 goto out; 365 goto out;
366} 366}
367 367
368#if defined(CONFIG_NFSD_V4) 368#if defined(CONFIG_NFSD_V2_ACL) || \
369 defined(CONFIG_NFSD_V3_ACL) || \
370 defined(CONFIG_NFSD_V4)
371static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
372{
373 ssize_t buflen;
374 int error;
375
376 buflen = vfs_getxattr(dentry, key, NULL, 0);
377 if (buflen <= 0)
378 return buflen;
369 379
380 *buf = kmalloc(buflen, GFP_KERNEL);
381 if (!*buf)
382 return -ENOMEM;
383
384 error = vfs_getxattr(dentry, key, *buf, buflen);
385 if (error < 0)
386 return error;
387 return buflen;
388}
389#endif
390
391#if defined(CONFIG_NFSD_V4)
370static int 392static int
371set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key) 393set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
372{ 394{
@@ -374,7 +396,6 @@ set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
374 size_t buflen; 396 size_t buflen;
375 char *buf = NULL; 397 char *buf = NULL;
376 int error = 0; 398 int error = 0;
377 struct inode *inode = dentry->d_inode;
378 399
379 buflen = posix_acl_xattr_size(pacl->a_count); 400 buflen = posix_acl_xattr_size(pacl->a_count);
380 buf = kmalloc(buflen, GFP_KERNEL); 401 buf = kmalloc(buflen, GFP_KERNEL);
@@ -388,15 +409,7 @@ set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
388 goto out; 409 goto out;
389 } 410 }
390 411
391 error = -EOPNOTSUPP; 412 error = vfs_setxattr(dentry, key, buf, len, 0);
392 if (inode->i_op && inode->i_op->setxattr) {
393 mutex_lock(&inode->i_mutex);
394 security_inode_setxattr(dentry, key, buf, len, 0);
395 error = inode->i_op->setxattr(dentry, key, buf, len, 0);
396 if (!error)
397 security_inode_post_setxattr(dentry, key, buf, len, 0);
398 mutex_unlock(&inode->i_mutex);
399 }
400out: 413out:
401 kfree(buf); 414 kfree(buf);
402 return error; 415 return error;
@@ -455,44 +468,19 @@ out_nfserr:
455static struct posix_acl * 468static struct posix_acl *
456_get_posix_acl(struct dentry *dentry, char *key) 469_get_posix_acl(struct dentry *dentry, char *key)
457{ 470{
458 struct inode *inode = dentry->d_inode; 471 void *buf = NULL;
459 char *buf = NULL;
460 int buflen, error = 0;
461 struct posix_acl *pacl = NULL; 472 struct posix_acl *pacl = NULL;
473 int buflen;
462 474
463 error = -EOPNOTSUPP; 475 buflen = nfsd_getxattr(dentry, key, &buf);
464 if (inode->i_op == NULL) 476 if (!buflen)
465 goto out_err; 477 buflen = -ENODATA;
466 if (inode->i_op->getxattr == NULL) 478 if (buflen <= 0)
467 goto out_err; 479 return ERR_PTR(buflen);
468
469 error = security_inode_getxattr(dentry, key);
470 if (error)
471 goto out_err;
472
473 buflen = inode->i_op->getxattr(dentry, key, NULL, 0);
474 if (buflen <= 0) {
475 error = buflen < 0 ? buflen : -ENODATA;
476 goto out_err;
477 }
478
479 buf = kmalloc(buflen, GFP_KERNEL);
480 if (buf == NULL) {
481 error = -ENOMEM;
482 goto out_err;
483 }
484
485 error = inode->i_op->getxattr(dentry, key, buf, buflen);
486 if (error < 0)
487 goto out_err;
488 480
489 pacl = posix_acl_from_xattr(buf, buflen); 481 pacl = posix_acl_from_xattr(buf, buflen);
490 out:
491 kfree(buf); 482 kfree(buf);
492 return pacl; 483 return pacl;
493 out_err:
494 pacl = ERR_PTR(error);
495 goto out;
496} 484}
497 485
498int 486int
@@ -1884,39 +1872,25 @@ nfsd_get_posix_acl(struct svc_fh *fhp, int type)
1884 ssize_t size; 1872 ssize_t size;
1885 struct posix_acl *acl; 1873 struct posix_acl *acl;
1886 1874
1887 if (!IS_POSIXACL(inode) || !inode->i_op || !inode->i_op->getxattr) 1875 if (!IS_POSIXACL(inode))
1876 return ERR_PTR(-EOPNOTSUPP);
1877
1878 switch (type) {
1879 case ACL_TYPE_ACCESS:
1880 name = POSIX_ACL_XATTR_ACCESS;
1881 break;
1882 case ACL_TYPE_DEFAULT:
1883 name = POSIX_ACL_XATTR_DEFAULT;
1884 break;
1885 default:
1888 return ERR_PTR(-EOPNOTSUPP); 1886 return ERR_PTR(-EOPNOTSUPP);
1889 switch(type) {
1890 case ACL_TYPE_ACCESS:
1891 name = POSIX_ACL_XATTR_ACCESS;
1892 break;
1893 case ACL_TYPE_DEFAULT:
1894 name = POSIX_ACL_XATTR_DEFAULT;
1895 break;
1896 default:
1897 return ERR_PTR(-EOPNOTSUPP);
1898 } 1887 }
1899 1888
1900 size = inode->i_op->getxattr(fhp->fh_dentry, name, NULL, 0); 1889 size = nfsd_getxattr(fhp->fh_dentry, name, &value);
1890 if (size < 0)
1891 return ERR_PTR(size);
1901 1892
1902 if (size < 0) {
1903 acl = ERR_PTR(size);
1904 goto getout;
1905 } else if (size > 0) {
1906 value = kmalloc(size, GFP_KERNEL);
1907 if (!value) {
1908 acl = ERR_PTR(-ENOMEM);
1909 goto getout;
1910 }
1911 size = inode->i_op->getxattr(fhp->fh_dentry, name, value, size);
1912 if (size < 0) {
1913 acl = ERR_PTR(size);
1914 goto getout;
1915 }
1916 }
1917 acl = posix_acl_from_xattr(value, size); 1893 acl = posix_acl_from_xattr(value, size);
1918
1919getout:
1920 kfree(value); 1894 kfree(value);
1921 return acl; 1895 return acl;
1922} 1896}
@@ -1957,16 +1931,13 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
1957 } else 1931 } else
1958 size = 0; 1932 size = 0;
1959 1933
1960 if (!fhp->fh_locked)
1961 fh_lock(fhp); /* unlocking is done automatically */
1962 if (size) 1934 if (size)
1963 error = inode->i_op->setxattr(fhp->fh_dentry, name, 1935 error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
1964 value, size, 0);
1965 else { 1936 else {
1966 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT) 1937 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
1967 error = 0; 1938 error = 0;
1968 else { 1939 else {
1969 error = inode->i_op->removexattr(fhp->fh_dentry, name); 1940 error = vfs_removexattr(fhp->fh_dentry, name);
1970 if (error == -ENODATA) 1941 if (error == -ENODATA)
1971 error = 0; 1942 error = 0;
1972 } 1943 }