diff options
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r-- | fs/nfsd/vfs.c | 107 |
1 files changed, 106 insertions, 1 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index e3e9d217236e..ae3940dc85cc 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -46,8 +46,9 @@ | |||
46 | #include <linux/nfsd/nfsfh.h> | 46 | #include <linux/nfsd/nfsfh.h> |
47 | #include <linux/quotaops.h> | 47 | #include <linux/quotaops.h> |
48 | #include <linux/dnotify.h> | 48 | #include <linux/dnotify.h> |
49 | #ifdef CONFIG_NFSD_V4 | 49 | #include <linux/xattr_acl.h> |
50 | #include <linux/posix_acl.h> | 50 | #include <linux/posix_acl.h> |
51 | #ifdef CONFIG_NFSD_V4 | ||
51 | #include <linux/posix_acl_xattr.h> | 52 | #include <linux/posix_acl_xattr.h> |
52 | #include <linux/xattr_acl.h> | 53 | #include <linux/xattr_acl.h> |
53 | #include <linux/xattr.h> | 54 | #include <linux/xattr.h> |
@@ -1857,3 +1858,107 @@ nfsd_racache_init(int cache_size) | |||
1857 | nfsdstats.ra_size = cache_size; | 1858 | nfsdstats.ra_size = cache_size; |
1858 | return 0; | 1859 | return 0; |
1859 | } | 1860 | } |
1861 | |||
1862 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) | ||
1863 | struct posix_acl * | ||
1864 | nfsd_get_posix_acl(struct svc_fh *fhp, int type) | ||
1865 | { | ||
1866 | struct inode *inode = fhp->fh_dentry->d_inode; | ||
1867 | char *name; | ||
1868 | void *value = NULL; | ||
1869 | ssize_t size; | ||
1870 | struct posix_acl *acl; | ||
1871 | |||
1872 | if (!IS_POSIXACL(inode) || !inode->i_op || !inode->i_op->getxattr) | ||
1873 | return ERR_PTR(-EOPNOTSUPP); | ||
1874 | switch(type) { | ||
1875 | case ACL_TYPE_ACCESS: | ||
1876 | name = XATTR_NAME_ACL_ACCESS; | ||
1877 | break; | ||
1878 | case ACL_TYPE_DEFAULT: | ||
1879 | name = XATTR_NAME_ACL_DEFAULT; | ||
1880 | break; | ||
1881 | default: | ||
1882 | return ERR_PTR(-EOPNOTSUPP); | ||
1883 | } | ||
1884 | |||
1885 | size = inode->i_op->getxattr(fhp->fh_dentry, name, NULL, 0); | ||
1886 | |||
1887 | if (size < 0) { | ||
1888 | acl = ERR_PTR(size); | ||
1889 | goto getout; | ||
1890 | } else if (size > 0) { | ||
1891 | value = kmalloc(size, GFP_KERNEL); | ||
1892 | if (!value) { | ||
1893 | acl = ERR_PTR(-ENOMEM); | ||
1894 | goto getout; | ||
1895 | } | ||
1896 | size = inode->i_op->getxattr(fhp->fh_dentry, name, value, size); | ||
1897 | if (size < 0) { | ||
1898 | acl = ERR_PTR(size); | ||
1899 | goto getout; | ||
1900 | } | ||
1901 | } | ||
1902 | acl = posix_acl_from_xattr(value, size); | ||
1903 | |||
1904 | getout: | ||
1905 | kfree(value); | ||
1906 | return acl; | ||
1907 | } | ||
1908 | |||
1909 | int | ||
1910 | nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl) | ||
1911 | { | ||
1912 | struct inode *inode = fhp->fh_dentry->d_inode; | ||
1913 | char *name; | ||
1914 | void *value = NULL; | ||
1915 | size_t size; | ||
1916 | int error; | ||
1917 | |||
1918 | if (!IS_POSIXACL(inode) || !inode->i_op || | ||
1919 | !inode->i_op->setxattr || !inode->i_op->removexattr) | ||
1920 | return -EOPNOTSUPP; | ||
1921 | switch(type) { | ||
1922 | case ACL_TYPE_ACCESS: | ||
1923 | name = XATTR_NAME_ACL_ACCESS; | ||
1924 | break; | ||
1925 | case ACL_TYPE_DEFAULT: | ||
1926 | name = XATTR_NAME_ACL_DEFAULT; | ||
1927 | break; | ||
1928 | default: | ||
1929 | return -EOPNOTSUPP; | ||
1930 | } | ||
1931 | |||
1932 | if (acl && acl->a_count) { | ||
1933 | size = xattr_acl_size(acl->a_count); | ||
1934 | value = kmalloc(size, GFP_KERNEL); | ||
1935 | if (!value) | ||
1936 | return -ENOMEM; | ||
1937 | size = posix_acl_to_xattr(acl, value, size); | ||
1938 | if (size < 0) { | ||
1939 | error = size; | ||
1940 | goto getout; | ||
1941 | } | ||
1942 | } else | ||
1943 | size = 0; | ||
1944 | |||
1945 | if (!fhp->fh_locked) | ||
1946 | fh_lock(fhp); /* unlocking is done automatically */ | ||
1947 | if (size) | ||
1948 | error = inode->i_op->setxattr(fhp->fh_dentry, name, | ||
1949 | value, size, 0); | ||
1950 | else { | ||
1951 | if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT) | ||
1952 | error = 0; | ||
1953 | else { | ||
1954 | error = inode->i_op->removexattr(fhp->fh_dentry, name); | ||
1955 | if (error == -ENODATA) | ||
1956 | error = 0; | ||
1957 | } | ||
1958 | } | ||
1959 | |||
1960 | getout: | ||
1961 | kfree(value); | ||
1962 | return error; | ||
1963 | } | ||
1964 | #endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */ | ||