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.c168
1 files changed, 78 insertions, 90 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 7c2e337d05af..6dd5f1970e01 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -20,13 +20,15 @@
20#include <linux/fcntl.h> 20#include <linux/fcntl.h>
21#include <linux/namei.h> 21#include <linux/namei.h>
22#include <linux/delay.h> 22#include <linux/delay.h>
23#include <linux/quotaops.h>
24#include <linux/fsnotify.h> 23#include <linux/fsnotify.h>
25#include <linux/posix_acl_xattr.h> 24#include <linux/posix_acl_xattr.h>
26#include <linux/xattr.h> 25#include <linux/xattr.h>
27#include <linux/jhash.h> 26#include <linux/jhash.h>
28#include <linux/ima.h> 27#include <linux/ima.h>
28#include <linux/slab.h>
29#include <asm/uaccess.h> 29#include <asm/uaccess.h>
30#include <linux/exportfs.h>
31#include <linux/writeback.h>
30 32
31#ifdef CONFIG_NFSD_V3 33#ifdef CONFIG_NFSD_V3
32#include "xdr3.h" 34#include "xdr3.h"
@@ -271,6 +273,32 @@ out:
271 return err; 273 return err;
272} 274}
273 275
276/*
277 * Commit metadata changes to stable storage.
278 */
279static int
280commit_metadata(struct svc_fh *fhp)
281{
282 struct inode *inode = fhp->fh_dentry->d_inode;
283 const struct export_operations *export_ops = inode->i_sb->s_export_op;
284 int error = 0;
285
286 if (!EX_ISSYNC(fhp->fh_export))
287 return 0;
288
289 if (export_ops->commit_metadata) {
290 error = export_ops->commit_metadata(inode);
291 } else {
292 struct writeback_control wbc = {
293 .sync_mode = WB_SYNC_ALL,
294 .nr_to_write = 0, /* metadata only */
295 };
296
297 error = sync_inode(inode, &wbc);
298 }
299
300 return error;
301}
274 302
275/* 303/*
276 * Set various file attributes. 304 * Set various file attributes.
@@ -361,7 +389,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
361 * If we are changing the size of the file, then 389 * If we are changing the size of the file, then
362 * we need to break all leases. 390 * we need to break all leases.
363 */ 391 */
364 host_err = break_lease(inode, FMODE_WRITE | O_NONBLOCK); 392 host_err = break_lease(inode, O_WRONLY | O_NONBLOCK);
365 if (host_err == -EWOULDBLOCK) 393 if (host_err == -EWOULDBLOCK)
366 host_err = -ETIMEDOUT; 394 host_err = -ETIMEDOUT;
367 if (host_err) /* ENOMEM or EWOULDBLOCK */ 395 if (host_err) /* ENOMEM or EWOULDBLOCK */
@@ -377,7 +405,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
377 put_write_access(inode); 405 put_write_access(inode);
378 goto out_nfserr; 406 goto out_nfserr;
379 } 407 }
380 vfs_dq_init(inode);
381 } 408 }
382 409
383 /* sanitize the mode change */ 410 /* sanitize the mode change */
@@ -734,7 +761,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
734 * Check to see if there are any leases on this file. 761 * Check to see if there are any leases on this file.
735 * This may block while leases are broken. 762 * This may block while leases are broken.
736 */ 763 */
737 host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? FMODE_WRITE : 0)); 764 host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0));
738 if (host_err == -EWOULDBLOCK) 765 if (host_err == -EWOULDBLOCK)
739 host_err = -ETIMEDOUT; 766 host_err = -ETIMEDOUT;
740 if (host_err) /* NOMEM or WOULDBLOCK */ 767 if (host_err) /* NOMEM or WOULDBLOCK */
@@ -745,13 +772,13 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
745 flags = O_RDWR|O_LARGEFILE; 772 flags = O_RDWR|O_LARGEFILE;
746 else 773 else
747 flags = O_WRONLY|O_LARGEFILE; 774 flags = O_WRONLY|O_LARGEFILE;
748
749 vfs_dq_init(inode);
750 } 775 }
751 *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt), 776 *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt),
752 flags, current_cred()); 777 flags, current_cred());
753 if (IS_ERR(*filp)) 778 if (IS_ERR(*filp))
754 host_err = PTR_ERR(*filp); 779 host_err = PTR_ERR(*filp);
780 else
781 host_err = ima_file_check(*filp, access);
755out_nfserr: 782out_nfserr:
756 err = nfserrno(host_err); 783 err = nfserrno(host_err);
757out: 784out:
@@ -769,46 +796,6 @@ nfsd_close(struct file *filp)
769} 796}
770 797
771/* 798/*
772 * Sync a file
773 * As this calls fsync (not fdatasync) there is no need for a write_inode
774 * after it.
775 */
776static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
777 const struct file_operations *fop)
778{
779 struct inode *inode = dp->d_inode;
780 int (*fsync) (struct file *, struct dentry *, int);
781 int err;
782
783 err = filemap_fdatawrite(inode->i_mapping);
784 if (err == 0 && fop && (fsync = fop->fsync))
785 err = fsync(filp, dp, 0);
786 if (err == 0)
787 err = filemap_fdatawait(inode->i_mapping);
788
789 return err;
790}
791
792static int
793nfsd_sync(struct file *filp)
794{
795 int err;
796 struct inode *inode = filp->f_path.dentry->d_inode;
797 dprintk("nfsd: sync file %s\n", filp->f_path.dentry->d_name.name);
798 mutex_lock(&inode->i_mutex);
799 err=nfsd_dosync(filp, filp->f_path.dentry, filp->f_op);
800 mutex_unlock(&inode->i_mutex);
801
802 return err;
803}
804
805int
806nfsd_sync_dir(struct dentry *dp)
807{
808 return nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
809}
810
811/*
812 * Obtain the readahead parameters for the file 799 * Obtain the readahead parameters for the file
813 * specified by (dev, ino). 800 * specified by (dev, ino).
814 */ 801 */
@@ -1011,7 +998,7 @@ static int wait_for_concurrent_writes(struct file *file)
1011 998
1012 if (inode->i_state & I_DIRTY) { 999 if (inode->i_state & I_DIRTY) {
1013 dprintk("nfsd: write sync %d\n", task_pid_nr(current)); 1000 dprintk("nfsd: write sync %d\n", task_pid_nr(current));
1014 err = nfsd_sync(file); 1001 err = vfs_fsync(file, file->f_path.dentry, 0);
1015 } 1002 }
1016 last_ino = inode->i_ino; 1003 last_ino = inode->i_ino;
1017 last_dev = inode->i_sb->s_dev; 1004 last_dev = inode->i_sb->s_dev;
@@ -1159,8 +1146,9 @@ out:
1159#ifdef CONFIG_NFSD_V3 1146#ifdef CONFIG_NFSD_V3
1160/* 1147/*
1161 * Commit all pending writes to stable storage. 1148 * Commit all pending writes to stable storage.
1162 * Strictly speaking, we could sync just the indicated file region here, 1149 *
1163 * but there's currently no way we can ask the VFS to do so. 1150 * Note: we only guarantee that data that lies within the range specified
1151 * by the 'offset' and 'count' parameters will be synced.
1164 * 1152 *
1165 * Unfortunately we cannot lock the file to make sure we return full WCC 1153 * Unfortunately we cannot lock the file to make sure we return full WCC
1166 * data to the client, as locking happens lower down in the filesystem. 1154 * data to the client, as locking happens lower down in the filesystem.
@@ -1170,23 +1158,32 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
1170 loff_t offset, unsigned long count) 1158 loff_t offset, unsigned long count)
1171{ 1159{
1172 struct file *file; 1160 struct file *file;
1173 __be32 err; 1161 loff_t end = LLONG_MAX;
1162 __be32 err = nfserr_inval;
1174 1163
1175 if ((u64)count > ~(u64)offset) 1164 if (offset < 0)
1176 return nfserr_inval; 1165 goto out;
1166 if (count != 0) {
1167 end = offset + (loff_t)count - 1;
1168 if (end < offset)
1169 goto out;
1170 }
1177 1171
1178 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file); 1172 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file);
1179 if (err) 1173 if (err)
1180 return err; 1174 goto out;
1181 if (EX_ISSYNC(fhp->fh_export)) { 1175 if (EX_ISSYNC(fhp->fh_export)) {
1182 if (file->f_op && file->f_op->fsync) { 1176 int err2 = vfs_fsync_range(file, file->f_path.dentry,
1183 err = nfserrno(nfsd_sync(file)); 1177 offset, end, 0);
1184 } else { 1178
1179 if (err2 != -EINVAL)
1180 err = nfserrno(err2);
1181 else
1185 err = nfserr_notsupp; 1182 err = nfserr_notsupp;
1186 }
1187 } 1183 }
1188 1184
1189 nfsd_close(file); 1185 nfsd_close(file);
1186out:
1190 return err; 1187 return err;
1191} 1188}
1192#endif /* CONFIG_NFSD_V3 */ 1189#endif /* CONFIG_NFSD_V3 */
@@ -1339,12 +1336,14 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1339 goto out_nfserr; 1336 goto out_nfserr;
1340 } 1337 }
1341 1338
1342 if (EX_ISSYNC(fhp->fh_export)) { 1339 err = nfsd_create_setattr(rqstp, resfhp, iap);
1343 err = nfserrno(nfsd_sync_dir(dentry));
1344 write_inode_now(dchild->d_inode, 1);
1345 }
1346 1340
1347 err2 = nfsd_create_setattr(rqstp, resfhp, iap); 1341 /*
1342 * nfsd_setattr already committed the child. Transactional filesystems
1343 * had a chance to commit changes for both parent and child
1344 * simultaneously making the following commit_metadata a noop.
1345 */
1346 err2 = nfserrno(commit_metadata(fhp));
1348 if (err2) 1347 if (err2)
1349 err = err2; 1348 err = err2;
1350 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1349 mnt_drop_write(fhp->fh_export->ex_path.mnt);
@@ -1376,7 +1375,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1376 struct dentry *dentry, *dchild = NULL; 1375 struct dentry *dentry, *dchild = NULL;
1377 struct inode *dirp; 1376 struct inode *dirp;
1378 __be32 err; 1377 __be32 err;
1379 __be32 err2;
1380 int host_err; 1378 int host_err;
1381 __u32 v_mtime=0, v_atime=0; 1379 __u32 v_mtime=0, v_atime=0;
1382 1380
@@ -1471,11 +1469,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1471 if (created) 1469 if (created)
1472 *created = 1; 1470 *created = 1;
1473 1471
1474 if (EX_ISSYNC(fhp->fh_export)) {
1475 err = nfserrno(nfsd_sync_dir(dentry));
1476 /* setattr will sync the child (or not) */
1477 }
1478
1479 nfsd_check_ignore_resizing(iap); 1472 nfsd_check_ignore_resizing(iap);
1480 1473
1481 if (createmode == NFS3_CREATE_EXCLUSIVE) { 1474 if (createmode == NFS3_CREATE_EXCLUSIVE) {
@@ -1490,9 +1483,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1490 } 1483 }
1491 1484
1492 set_attr: 1485 set_attr:
1493 err2 = nfsd_create_setattr(rqstp, resfhp, iap); 1486 err = nfsd_create_setattr(rqstp, resfhp, iap);
1494 if (err2) 1487
1495 err = err2; 1488 /*
1489 * nfsd_setattr already committed the child (and possibly also the parent).
1490 */
1491 if (!err)
1492 err = nfserrno(commit_metadata(fhp));
1496 1493
1497 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1494 mnt_drop_write(fhp->fh_export->ex_path.mnt);
1498 /* 1495 /*
@@ -1607,12 +1604,9 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
1607 } 1604 }
1608 } else 1605 } else
1609 host_err = vfs_symlink(dentry->d_inode, dnew, path); 1606 host_err = vfs_symlink(dentry->d_inode, dnew, path);
1610
1611 if (!host_err) {
1612 if (EX_ISSYNC(fhp->fh_export))
1613 host_err = nfsd_sync_dir(dentry);
1614 }
1615 err = nfserrno(host_err); 1607 err = nfserrno(host_err);
1608 if (!err)
1609 err = nfserrno(commit_metadata(fhp));
1616 fh_unlock(fhp); 1610 fh_unlock(fhp);
1617 1611
1618 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1612 mnt_drop_write(fhp->fh_export->ex_path.mnt);
@@ -1674,11 +1668,9 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1674 } 1668 }
1675 host_err = vfs_link(dold, dirp, dnew); 1669 host_err = vfs_link(dold, dirp, dnew);
1676 if (!host_err) { 1670 if (!host_err) {
1677 if (EX_ISSYNC(ffhp->fh_export)) { 1671 err = nfserrno(commit_metadata(ffhp));
1678 err = nfserrno(nfsd_sync_dir(ddir)); 1672 if (!err)
1679 write_inode_now(dest, 1); 1673 err = nfserrno(commit_metadata(tfhp));
1680 }
1681 err = 0;
1682 } else { 1674 } else {
1683 if (host_err == -EXDEV && rqstp->rq_vers == 2) 1675 if (host_err == -EXDEV && rqstp->rq_vers == 2)
1684 err = nfserr_acces; 1676 err = nfserr_acces;
@@ -1774,10 +1766,10 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1774 goto out_dput_new; 1766 goto out_dput_new;
1775 1767
1776 host_err = vfs_rename(fdir, odentry, tdir, ndentry); 1768 host_err = vfs_rename(fdir, odentry, tdir, ndentry);
1777 if (!host_err && EX_ISSYNC(tfhp->fh_export)) { 1769 if (!host_err) {
1778 host_err = nfsd_sync_dir(tdentry); 1770 host_err = commit_metadata(tfhp);
1779 if (!host_err) 1771 if (!host_err)
1780 host_err = nfsd_sync_dir(fdentry); 1772 host_err = commit_metadata(ffhp);
1781 } 1773 }
1782 1774
1783 mnt_drop_write(ffhp->fh_export->ex_path.mnt); 1775 mnt_drop_write(ffhp->fh_export->ex_path.mnt);
@@ -1858,12 +1850,9 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1858 1850
1859 dput(rdentry); 1851 dput(rdentry);
1860 1852
1861 if (host_err) 1853 if (!host_err)
1862 goto out_drop; 1854 host_err = commit_metadata(fhp);
1863 if (EX_ISSYNC(fhp->fh_export))
1864 host_err = nfsd_sync_dir(dentry);
1865 1855
1866out_drop:
1867 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1856 mnt_drop_write(fhp->fh_export->ex_path.mnt);
1868out_nfserr: 1857out_nfserr:
1869 err = nfserrno(host_err); 1858 err = nfserrno(host_err);
@@ -2130,7 +2119,6 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
2130 */ 2119 */
2131 path.mnt = exp->ex_path.mnt; 2120 path.mnt = exp->ex_path.mnt;
2132 path.dentry = dentry; 2121 path.dentry = dentry;
2133 err = ima_path_check(&path, acc & (MAY_READ | MAY_WRITE | MAY_EXEC));
2134nfsd_out: 2122nfsd_out:
2135 return err? nfserrno(err) : 0; 2123 return err? nfserrno(err) : 0;
2136} 2124}