aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4callback.c5
-rw-r--r--fs/nfsd/nfs4recover.c4
-rw-r--r--fs/nfsd/nfs4state.c4
-rw-r--r--fs/nfsd/nfs4xdr.c2
-rw-r--r--fs/nfsd/nfsctl.c24
-rw-r--r--fs/nfsd/vfs.c153
6 files changed, 100 insertions, 92 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index c6eed2a3b093..4bc22c763de7 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -525,6 +525,8 @@ static struct rpc_cred *callback_cred;
525 525
526int set_callback_cred(void) 526int set_callback_cred(void)
527{ 527{
528 if (callback_cred)
529 return 0;
528 callback_cred = rpc_lookup_machine_cred(); 530 callback_cred = rpc_lookup_machine_cred();
529 if (!callback_cred) 531 if (!callback_cred)
530 return -ENOMEM; 532 return -ENOMEM;
@@ -542,7 +544,8 @@ void do_probe_callback(struct nfs4_client *clp)
542 }; 544 };
543 int status; 545 int status;
544 546
545 status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_SOFT, 547 status = rpc_call_async(cb->cb_client, &msg,
548 RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
546 &nfsd4_cb_probe_ops, (void *)clp); 549 &nfsd4_cb_probe_ops, (void *)clp);
547 if (status) { 550 if (status) {
548 warn_no_callback_path(clp, status); 551 warn_no_callback_path(clp, status);
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 5a754f7b71ed..98fb98e330b4 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -119,9 +119,7 @@ out_no_tfm:
119static void 119static void
120nfsd4_sync_rec_dir(void) 120nfsd4_sync_rec_dir(void)
121{ 121{
122 mutex_lock(&rec_dir.dentry->d_inode->i_mutex); 122 vfs_fsync(NULL, rec_dir.dentry, 0);
123 nfsd_sync_dir(rec_dir.dentry);
124 mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
125} 123}
126 124
127int 125int
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index fcafe6087f69..c97fddbd17db 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2482,8 +2482,10 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
2482 } 2482 }
2483 memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t)); 2483 memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t));
2484 2484
2485 if (nfsd4_has_session(&resp->cstate)) 2485 if (nfsd4_has_session(&resp->cstate)) {
2486 open->op_stateowner->so_confirmed = 1; 2486 open->op_stateowner->so_confirmed = 1;
2487 nfsd4_create_clid_dir(open->op_stateowner->so_client);
2488 }
2487 2489
2488 /* 2490 /*
2489 * Attempt to hand out a delegation. No error return, because the 2491 * Attempt to hand out a delegation. No error return, because the
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index bbf72d8f9fc0..78c7e24e5129 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1434,7 +1434,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1434 } 1434 }
1435 op->opnum = ntohl(*argp->p++); 1435 op->opnum = ntohl(*argp->p++);
1436 1436
1437 if (op->opnum >= OP_ACCESS && op->opnum < ops->nops) 1437 if (op->opnum >= FIRST_NFS4_OP && op->opnum <= LAST_NFS4_OP)
1438 op->status = ops->decoders[op->opnum](argp, &op->u); 1438 op->status = ops->decoders[op->opnum](argp, &op->u);
1439 else { 1439 else {
1440 op->opnum = OP_ILLEGAL; 1440 op->opnum = OP_ILLEGAL;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 2604c3e70ea5..0f0e77f2012f 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -988,6 +988,7 @@ static ssize_t __write_ports_delfd(char *buf)
988static ssize_t __write_ports_addxprt(char *buf) 988static ssize_t __write_ports_addxprt(char *buf)
989{ 989{
990 char transport[16]; 990 char transport[16];
991 struct svc_xprt *xprt;
991 int port, err; 992 int port, err;
992 993
993 if (sscanf(buf, "%15s %4u", transport, &port) != 2) 994 if (sscanf(buf, "%15s %4u", transport, &port) != 2)
@@ -1002,13 +1003,24 @@ static ssize_t __write_ports_addxprt(char *buf)
1002 1003
1003 err = svc_create_xprt(nfsd_serv, transport, 1004 err = svc_create_xprt(nfsd_serv, transport,
1004 PF_INET, port, SVC_SOCK_ANONYMOUS); 1005 PF_INET, port, SVC_SOCK_ANONYMOUS);
1005 if (err < 0) { 1006 if (err < 0)
1006 /* Give a reasonable perror msg for bad transport string */ 1007 goto out_err;
1007 if (err == -ENOENT) 1008
1008 err = -EPROTONOSUPPORT; 1009 err = svc_create_xprt(nfsd_serv, transport,
1009 return err; 1010 PF_INET6, port, SVC_SOCK_ANONYMOUS);
1010 } 1011 if (err < 0 && err != -EAFNOSUPPORT)
1012 goto out_close;
1011 return 0; 1013 return 0;
1014out_close:
1015 xprt = svc_find_xprt(nfsd_serv, transport, PF_INET, port);
1016 if (xprt != NULL) {
1017 svc_close_xprt(xprt);
1018 svc_xprt_put(xprt);
1019 }
1020out_err:
1021 /* Decrease the count, but don't shut down the service */
1022 nfsd_serv->sv_nrthreads--;
1023 return err;
1012} 1024}
1013 1025
1014/* 1026/*
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 8eca17df4f63..a11b0e8678ee 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -26,6 +26,8 @@
26#include <linux/jhash.h> 26#include <linux/jhash.h>
27#include <linux/ima.h> 27#include <linux/ima.h>
28#include <asm/uaccess.h> 28#include <asm/uaccess.h>
29#include <linux/exportfs.h>
30#include <linux/writeback.h>
29 31
30#ifdef CONFIG_NFSD_V3 32#ifdef CONFIG_NFSD_V3
31#include "xdr3.h" 33#include "xdr3.h"
@@ -270,6 +272,32 @@ out:
270 return err; 272 return err;
271} 273}
272 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}
273 301
274/* 302/*
275 * Set various file attributes. 303 * Set various file attributes.
@@ -767,43 +795,6 @@ nfsd_close(struct file *filp)
767} 795}
768 796
769/* 797/*
770 * Sync a file
771 * As this calls fsync (not fdatasync) there is no need for a write_inode
772 * after it.
773 */
774static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
775 const struct file_operations *fop)
776{
777 struct inode *inode = dp->d_inode;
778 int (*fsync) (struct file *, struct dentry *, int);
779 int err;
780
781 err = filemap_write_and_wait(inode->i_mapping);
782 if (err == 0 && fop && (fsync = fop->fsync))
783 err = fsync(filp, dp, 0);
784 return err;
785}
786
787static int
788nfsd_sync(struct file *filp)
789{
790 int err;
791 struct inode *inode = filp->f_path.dentry->d_inode;
792 dprintk("nfsd: sync file %s\n", filp->f_path.dentry->d_name.name);
793 mutex_lock(&inode->i_mutex);
794 err=nfsd_dosync(filp, filp->f_path.dentry, filp->f_op);
795 mutex_unlock(&inode->i_mutex);
796
797 return err;
798}
799
800int
801nfsd_sync_dir(struct dentry *dp)
802{
803 return nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
804}
805
806/*
807 * Obtain the readahead parameters for the file 798 * Obtain the readahead parameters for the file
808 * specified by (dev, ino). 799 * specified by (dev, ino).
809 */ 800 */
@@ -1006,7 +997,7 @@ static int wait_for_concurrent_writes(struct file *file)
1006 997
1007 if (inode->i_state & I_DIRTY) { 998 if (inode->i_state & I_DIRTY) {
1008 dprintk("nfsd: write sync %d\n", task_pid_nr(current)); 999 dprintk("nfsd: write sync %d\n", task_pid_nr(current));
1009 err = nfsd_sync(file); 1000 err = vfs_fsync(file, file->f_path.dentry, 0);
1010 } 1001 }
1011 last_ino = inode->i_ino; 1002 last_ino = inode->i_ino;
1012 last_dev = inode->i_sb->s_dev; 1003 last_dev = inode->i_sb->s_dev;
@@ -1154,8 +1145,9 @@ out:
1154#ifdef CONFIG_NFSD_V3 1145#ifdef CONFIG_NFSD_V3
1155/* 1146/*
1156 * Commit all pending writes to stable storage. 1147 * Commit all pending writes to stable storage.
1157 * Strictly speaking, we could sync just the indicated file region here, 1148 *
1158 * 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.
1159 * 1151 *
1160 * 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
1161 * 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.
@@ -1165,23 +1157,32 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
1165 loff_t offset, unsigned long count) 1157 loff_t offset, unsigned long count)
1166{ 1158{
1167 struct file *file; 1159 struct file *file;
1168 __be32 err; 1160 loff_t end = LLONG_MAX;
1161 __be32 err = nfserr_inval;
1169 1162
1170 if ((u64)count > ~(u64)offset) 1163 if (offset < 0)
1171 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 }
1172 1170
1173 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file); 1171 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file);
1174 if (err) 1172 if (err)
1175 return err; 1173 goto out;
1176 if (EX_ISSYNC(fhp->fh_export)) { 1174 if (EX_ISSYNC(fhp->fh_export)) {
1177 if (file->f_op && file->f_op->fsync) { 1175 int err2 = vfs_fsync_range(file, file->f_path.dentry,
1178 err = nfserrno(nfsd_sync(file)); 1176 offset, end, 0);
1179 } else { 1177
1178 if (err2 != -EINVAL)
1179 err = nfserrno(err2);
1180 else
1180 err = nfserr_notsupp; 1181 err = nfserr_notsupp;
1181 }
1182 } 1182 }
1183 1183
1184 nfsd_close(file); 1184 nfsd_close(file);
1185out:
1185 return err; 1186 return err;
1186} 1187}
1187#endif /* CONFIG_NFSD_V3 */ 1188#endif /* CONFIG_NFSD_V3 */
@@ -1334,12 +1335,14 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1334 goto out_nfserr; 1335 goto out_nfserr;
1335 } 1336 }
1336 1337
1337 if (EX_ISSYNC(fhp->fh_export)) { 1338 err = nfsd_create_setattr(rqstp, resfhp, iap);
1338 err = nfserrno(nfsd_sync_dir(dentry));
1339 write_inode_now(dchild->d_inode, 1);
1340 }
1341 1339
1342 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));
1343 if (err2) 1346 if (err2)
1344 err = err2; 1347 err = err2;
1345 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1348 mnt_drop_write(fhp->fh_export->ex_path.mnt);
@@ -1371,7 +1374,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1371 struct dentry *dentry, *dchild = NULL; 1374 struct dentry *dentry, *dchild = NULL;
1372 struct inode *dirp; 1375 struct inode *dirp;
1373 __be32 err; 1376 __be32 err;
1374 __be32 err2;
1375 int host_err; 1377 int host_err;
1376 __u32 v_mtime=0, v_atime=0; 1378 __u32 v_mtime=0, v_atime=0;
1377 1379
@@ -1466,11 +1468,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1466 if (created) 1468 if (created)
1467 *created = 1; 1469 *created = 1;
1468 1470
1469 if (EX_ISSYNC(fhp->fh_export)) {
1470 err = nfserrno(nfsd_sync_dir(dentry));
1471 /* setattr will sync the child (or not) */
1472 }
1473
1474 nfsd_check_ignore_resizing(iap); 1471 nfsd_check_ignore_resizing(iap);
1475 1472
1476 if (createmode == NFS3_CREATE_EXCLUSIVE) { 1473 if (createmode == NFS3_CREATE_EXCLUSIVE) {
@@ -1485,9 +1482,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1485 } 1482 }
1486 1483
1487 set_attr: 1484 set_attr:
1488 err2 = nfsd_create_setattr(rqstp, resfhp, iap); 1485 err = nfsd_create_setattr(rqstp, resfhp, iap);
1489 if (err2) 1486
1490 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));
1491 1492
1492 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1493 mnt_drop_write(fhp->fh_export->ex_path.mnt);
1493 /* 1494 /*
@@ -1602,12 +1603,9 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
1602 } 1603 }
1603 } else 1604 } else
1604 host_err = vfs_symlink(dentry->d_inode, dnew, path); 1605 host_err = vfs_symlink(dentry->d_inode, dnew, path);
1605
1606 if (!host_err) {
1607 if (EX_ISSYNC(fhp->fh_export))
1608 host_err = nfsd_sync_dir(dentry);
1609 }
1610 err = nfserrno(host_err); 1606 err = nfserrno(host_err);
1607 if (!err)
1608 err = nfserrno(commit_metadata(fhp));
1611 fh_unlock(fhp); 1609 fh_unlock(fhp);
1612 1610
1613 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1611 mnt_drop_write(fhp->fh_export->ex_path.mnt);
@@ -1669,11 +1667,9 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1669 } 1667 }
1670 host_err = vfs_link(dold, dirp, dnew); 1668 host_err = vfs_link(dold, dirp, dnew);
1671 if (!host_err) { 1669 if (!host_err) {
1672 if (EX_ISSYNC(ffhp->fh_export)) { 1670 err = nfserrno(commit_metadata(ffhp));
1673 err = nfserrno(nfsd_sync_dir(ddir)); 1671 if (!err)
1674 write_inode_now(dest, 1); 1672 err = nfserrno(commit_metadata(tfhp));
1675 }
1676 err = 0;
1677 } else { 1673 } else {
1678 if (host_err == -EXDEV && rqstp->rq_vers == 2) 1674 if (host_err == -EXDEV && rqstp->rq_vers == 2)
1679 err = nfserr_acces; 1675 err = nfserr_acces;
@@ -1769,10 +1765,10 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1769 goto out_dput_new; 1765 goto out_dput_new;
1770 1766
1771 host_err = vfs_rename(fdir, odentry, tdir, ndentry); 1767 host_err = vfs_rename(fdir, odentry, tdir, ndentry);
1772 if (!host_err && EX_ISSYNC(tfhp->fh_export)) { 1768 if (!host_err) {
1773 host_err = nfsd_sync_dir(tdentry); 1769 host_err = commit_metadata(tfhp);
1774 if (!host_err) 1770 if (!host_err)
1775 host_err = nfsd_sync_dir(fdentry); 1771 host_err = commit_metadata(ffhp);
1776 } 1772 }
1777 1773
1778 mnt_drop_write(ffhp->fh_export->ex_path.mnt); 1774 mnt_drop_write(ffhp->fh_export->ex_path.mnt);
@@ -1853,12 +1849,9 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1853 1849
1854 dput(rdentry); 1850 dput(rdentry);
1855 1851
1856 if (host_err) 1852 if (!host_err)
1857 goto out_drop; 1853 host_err = commit_metadata(fhp);
1858 if (EX_ISSYNC(fhp->fh_export))
1859 host_err = nfsd_sync_dir(dentry);
1860 1854
1861out_drop:
1862 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1855 mnt_drop_write(fhp->fh_export->ex_path.mnt);
1863out_nfserr: 1856out_nfserr:
1864 err = nfserrno(host_err); 1857 err = nfserrno(host_err);