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.c250
1 files changed, 117 insertions, 133 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index af7c3c3074b0..5320e5afaddb 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;
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
369 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 down(&inode->i_sem);
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 up(&inode->i_sem);
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
@@ -717,33 +705,40 @@ nfsd_close(struct file *filp)
717 * As this calls fsync (not fdatasync) there is no need for a write_inode 705 * As this calls fsync (not fdatasync) there is no need for a write_inode
718 * after it. 706 * after it.
719 */ 707 */
720static inline void nfsd_dosync(struct file *filp, struct dentry *dp, 708static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
721 struct file_operations *fop) 709 struct file_operations *fop)
722{ 710{
723 struct inode *inode = dp->d_inode; 711 struct inode *inode = dp->d_inode;
724 int (*fsync) (struct file *, struct dentry *, int); 712 int (*fsync) (struct file *, struct dentry *, int);
713 int err;
714
715 err = filemap_fdatawrite(inode->i_mapping);
716 if (err == 0 && fop && (fsync = fop->fsync))
717 err = fsync(filp, dp, 0);
718 if (err == 0)
719 err = filemap_fdatawait(inode->i_mapping);
725 720
726 filemap_fdatawrite(inode->i_mapping); 721 return err;
727 if (fop && (fsync = fop->fsync))
728 fsync(filp, dp, 0);
729 filemap_fdatawait(inode->i_mapping);
730} 722}
731 723
732 724
733static void 725static int
734nfsd_sync(struct file *filp) 726nfsd_sync(struct file *filp)
735{ 727{
728 int err;
736 struct inode *inode = filp->f_dentry->d_inode; 729 struct inode *inode = filp->f_dentry->d_inode;
737 dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name); 730 dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name);
738 down(&inode->i_sem); 731 mutex_lock(&inode->i_mutex);
739 nfsd_dosync(filp, filp->f_dentry, filp->f_op); 732 err=nfsd_dosync(filp, filp->f_dentry, filp->f_op);
740 up(&inode->i_sem); 733 mutex_unlock(&inode->i_mutex);
734
735 return err;
741} 736}
742 737
743void 738int
744nfsd_sync_dir(struct dentry *dp) 739nfsd_sync_dir(struct dentry *dp)
745{ 740{
746 nfsd_dosync(NULL, dp, dp->d_inode->i_fop); 741 return nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
747} 742}
748 743
749/* 744/*
@@ -820,7 +815,7 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset
820 return size; 815 return size;
821} 816}
822 817
823static inline int 818static int
824nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, 819nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
825 loff_t offset, struct kvec *vec, int vlen, unsigned long *count) 820 loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
826{ 821{
@@ -874,7 +869,17 @@ out:
874 return err; 869 return err;
875} 870}
876 871
877static inline int 872static void kill_suid(struct dentry *dentry)
873{
874 struct iattr ia;
875 ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID;
876
877 mutex_lock(&dentry->d_inode->i_mutex);
878 notify_change(dentry, &ia);
879 mutex_unlock(&dentry->d_inode->i_mutex);
880}
881
882static int
878nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, 883nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
879 loff_t offset, struct kvec *vec, int vlen, 884 loff_t offset, struct kvec *vec, int vlen,
880 unsigned long cnt, int *stablep) 885 unsigned long cnt, int *stablep)
@@ -886,9 +891,9 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
886 int err = 0; 891 int err = 0;
887 int stable = *stablep; 892 int stable = *stablep;
888 893
894#ifdef MSNFS
889 err = nfserr_perm; 895 err = nfserr_perm;
890 896
891#ifdef MSNFS
892 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && 897 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
893 (!lock_may_write(file->f_dentry->d_inode, offset, cnt))) 898 (!lock_may_write(file->f_dentry->d_inode, offset, cnt)))
894 goto out; 899 goto out;
@@ -927,14 +932,8 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
927 } 932 }
928 933
929 /* clear setuid/setgid flag after write */ 934 /* clear setuid/setgid flag after write */
930 if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) { 935 if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
931 struct iattr ia; 936 kill_suid(dentry);
932 ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID;
933
934 down(&inode->i_sem);
935 notify_change(dentry, &ia);
936 up(&inode->i_sem);
937 }
938 937
939 if (err >= 0 && stable) { 938 if (err >= 0 && stable) {
940 static ino_t last_ino; 939 static ino_t last_ino;
@@ -962,7 +961,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
962 961
963 if (inode->i_state & I_DIRTY) { 962 if (inode->i_state & I_DIRTY) {
964 dprintk("nfsd: write sync %d\n", current->pid); 963 dprintk("nfsd: write sync %d\n", current->pid);
965 nfsd_sync(file); 964 err=nfsd_sync(file);
966 } 965 }
967#if 0 966#if 0
968 wake_up(&inode->i_wait); 967 wake_up(&inode->i_wait);
@@ -1066,7 +1065,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
1066 return err; 1065 return err;
1067 if (EX_ISSYNC(fhp->fh_export)) { 1066 if (EX_ISSYNC(fhp->fh_export)) {
1068 if (file->f_op && file->f_op->fsync) { 1067 if (file->f_op && file->f_op->fsync) {
1069 nfsd_sync(file); 1068 err = nfserrno(nfsd_sync(file));
1070 } else { 1069 } else {
1071 err = nfserr_notsupp; 1070 err = nfserr_notsupp;
1072 } 1071 }
@@ -1134,7 +1133,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1134 "nfsd_create: parent %s/%s not locked!\n", 1133 "nfsd_create: parent %s/%s not locked!\n",
1135 dentry->d_parent->d_name.name, 1134 dentry->d_parent->d_name.name,
1136 dentry->d_name.name); 1135 dentry->d_name.name);
1137 err = -EIO; 1136 err = nfserr_io;
1138 goto out; 1137 goto out;
1139 } 1138 }
1140 } 1139 }
@@ -1177,7 +1176,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1177 goto out_nfserr; 1176 goto out_nfserr;
1178 1177
1179 if (EX_ISSYNC(fhp->fh_export)) { 1178 if (EX_ISSYNC(fhp->fh_export)) {
1180 nfsd_sync_dir(dentry); 1179 err = nfserrno(nfsd_sync_dir(dentry));
1181 write_inode_now(dchild->d_inode, 1); 1180 write_inode_now(dchild->d_inode, 1);
1182 } 1181 }
1183 1182
@@ -1187,9 +1186,11 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1187 * send along the gid when it tries to implement setgid 1186 * send along the gid when it tries to implement setgid
1188 * directories via NFS. 1187 * directories via NFS.
1189 */ 1188 */
1190 err = 0; 1189 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) {
1191 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) 1190 int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
1192 err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); 1191 if (err2)
1192 err = err2;
1193 }
1193 /* 1194 /*
1194 * Update the file handle to get the new inode info. 1195 * Update the file handle to get the new inode info.
1195 */ 1196 */
@@ -1308,17 +1309,10 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1308 goto out_nfserr; 1309 goto out_nfserr;
1309 1310
1310 if (EX_ISSYNC(fhp->fh_export)) { 1311 if (EX_ISSYNC(fhp->fh_export)) {
1311 nfsd_sync_dir(dentry); 1312 err = nfserrno(nfsd_sync_dir(dentry));
1312 /* setattr will sync the child (or not) */ 1313 /* setattr will sync the child (or not) */
1313 } 1314 }
1314 1315
1315 /*
1316 * Update the filehandle to get the new inode info.
1317 */
1318 err = fh_update(resfhp);
1319 if (err)
1320 goto out;
1321
1322 if (createmode == NFS3_CREATE_EXCLUSIVE) { 1316 if (createmode == NFS3_CREATE_EXCLUSIVE) {
1323 /* Cram the verifier into atime/mtime/mode */ 1317 /* Cram the verifier into atime/mtime/mode */
1324 iap->ia_valid = ATTR_MTIME|ATTR_ATIME 1318 iap->ia_valid = ATTR_MTIME|ATTR_ATIME
@@ -1339,8 +1333,17 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1339 * implement setgid directories via NFS. Clear out all that cruft. 1333 * implement setgid directories via NFS. Clear out all that cruft.
1340 */ 1334 */
1341 set_attr: 1335 set_attr:
1342 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) 1336 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) {
1343 err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); 1337 int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
1338 if (err2)
1339 err = err2;
1340 }
1341
1342 /*
1343 * Update the filehandle to get the new inode info.
1344 */
1345 if (!err)
1346 err = fh_update(resfhp);
1344 1347
1345 out: 1348 out:
1346 fh_unlock(fhp); 1349 fh_unlock(fhp);
@@ -1449,10 +1452,10 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
1449 } else 1452 } else
1450 err = vfs_symlink(dentry->d_inode, dnew, path, mode); 1453 err = vfs_symlink(dentry->d_inode, dnew, path, mode);
1451 1454
1452 if (!err) { 1455 if (!err)
1453 if (EX_ISSYNC(fhp->fh_export)) 1456 if (EX_ISSYNC(fhp->fh_export))
1454 nfsd_sync_dir(dentry); 1457 err = nfsd_sync_dir(dentry);
1455 } else 1458 if (err)
1456 err = nfserrno(err); 1459 err = nfserrno(err);
1457 fh_unlock(fhp); 1460 fh_unlock(fhp);
1458 1461
@@ -1508,7 +1511,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1508 err = vfs_link(dold, dirp, dnew); 1511 err = vfs_link(dold, dirp, dnew);
1509 if (!err) { 1512 if (!err) {
1510 if (EX_ISSYNC(ffhp->fh_export)) { 1513 if (EX_ISSYNC(ffhp->fh_export)) {
1511 nfsd_sync_dir(ddir); 1514 err = nfserrno(nfsd_sync_dir(ddir));
1512 write_inode_now(dest, 1); 1515 write_inode_now(dest, 1);
1513 } 1516 }
1514 } else { 1517 } else {
@@ -1592,13 +1595,14 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1592 if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) && 1595 if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
1593 ((atomic_read(&odentry->d_count) > 1) 1596 ((atomic_read(&odentry->d_count) > 1)
1594 || (atomic_read(&ndentry->d_count) > 1))) { 1597 || (atomic_read(&ndentry->d_count) > 1))) {
1595 err = nfserr_perm; 1598 err = -EPERM;
1596 } else 1599 } else
1597#endif 1600#endif
1598 err = vfs_rename(fdir, odentry, tdir, ndentry); 1601 err = vfs_rename(fdir, odentry, tdir, ndentry);
1599 if (!err && EX_ISSYNC(tfhp->fh_export)) { 1602 if (!err && EX_ISSYNC(tfhp->fh_export)) {
1600 nfsd_sync_dir(tdentry); 1603 err = nfsd_sync_dir(tdentry);
1601 nfsd_sync_dir(fdentry); 1604 if (!err)
1605 err = nfsd_sync_dir(fdentry);
1602 } 1606 }
1603 1607
1604 out_dput_new: 1608 out_dput_new:
@@ -1663,7 +1667,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1663#ifdef MSNFS 1667#ifdef MSNFS
1664 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && 1668 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
1665 (atomic_read(&rdentry->d_count) > 1)) { 1669 (atomic_read(&rdentry->d_count) > 1)) {
1666 err = nfserr_perm; 1670 err = -EPERM;
1667 } else 1671 } else
1668#endif 1672#endif
1669 err = vfs_unlink(dirp, rdentry); 1673 err = vfs_unlink(dirp, rdentry);
@@ -1673,17 +1677,14 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1673 1677
1674 dput(rdentry); 1678 dput(rdentry);
1675 1679
1676 if (err) 1680 if (err == 0 &&
1677 goto out_nfserr; 1681 EX_ISSYNC(fhp->fh_export))
1678 if (EX_ISSYNC(fhp->fh_export)) 1682 err = nfsd_sync_dir(dentry);
1679 nfsd_sync_dir(dentry);
1680
1681out:
1682 return err;
1683 1683
1684out_nfserr: 1684out_nfserr:
1685 err = nfserrno(err); 1685 err = nfserrno(err);
1686 goto out; 1686out:
1687 return err;
1687} 1688}
1688 1689
1689/* 1690/*
@@ -1874,39 +1875,25 @@ nfsd_get_posix_acl(struct svc_fh *fhp, int type)
1874 ssize_t size; 1875 ssize_t size;
1875 struct posix_acl *acl; 1876 struct posix_acl *acl;
1876 1877
1877 if (!IS_POSIXACL(inode) || !inode->i_op || !inode->i_op->getxattr) 1878 if (!IS_POSIXACL(inode))
1879 return ERR_PTR(-EOPNOTSUPP);
1880
1881 switch (type) {
1882 case ACL_TYPE_ACCESS:
1883 name = POSIX_ACL_XATTR_ACCESS;
1884 break;
1885 case ACL_TYPE_DEFAULT:
1886 name = POSIX_ACL_XATTR_DEFAULT;
1887 break;
1888 default:
1878 return ERR_PTR(-EOPNOTSUPP); 1889 return ERR_PTR(-EOPNOTSUPP);
1879 switch(type) {
1880 case ACL_TYPE_ACCESS:
1881 name = POSIX_ACL_XATTR_ACCESS;
1882 break;
1883 case ACL_TYPE_DEFAULT:
1884 name = POSIX_ACL_XATTR_DEFAULT;
1885 break;
1886 default:
1887 return ERR_PTR(-EOPNOTSUPP);
1888 } 1890 }
1889 1891
1890 size = inode->i_op->getxattr(fhp->fh_dentry, name, NULL, 0); 1892 size = nfsd_getxattr(fhp->fh_dentry, name, &value);
1893 if (size < 0)
1894 return ERR_PTR(size);
1891 1895
1892 if (size < 0) {
1893 acl = ERR_PTR(size);
1894 goto getout;
1895 } else if (size > 0) {
1896 value = kmalloc(size, GFP_KERNEL);
1897 if (!value) {
1898 acl = ERR_PTR(-ENOMEM);
1899 goto getout;
1900 }
1901 size = inode->i_op->getxattr(fhp->fh_dentry, name, value, size);
1902 if (size < 0) {
1903 acl = ERR_PTR(size);
1904 goto getout;
1905 }
1906 }
1907 acl = posix_acl_from_xattr(value, size); 1896 acl = posix_acl_from_xattr(value, size);
1908
1909getout:
1910 kfree(value); 1897 kfree(value);
1911 return acl; 1898 return acl;
1912} 1899}
@@ -1947,16 +1934,13 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
1947 } else 1934 } else
1948 size = 0; 1935 size = 0;
1949 1936
1950 if (!fhp->fh_locked)
1951 fh_lock(fhp); /* unlocking is done automatically */
1952 if (size) 1937 if (size)
1953 error = inode->i_op->setxattr(fhp->fh_dentry, name, 1938 error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
1954 value, size, 0);
1955 else { 1939 else {
1956 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT) 1940 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
1957 error = 0; 1941 error = 0;
1958 else { 1942 else {
1959 error = inode->i_op->removexattr(fhp->fh_dentry, name); 1943 error = vfs_removexattr(fhp->fh_dentry, name);
1960 if (error == -ENODATA) 1944 if (error == -ENODATA)
1961 error = 0; 1945 error = 0;
1962 } 1946 }