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