aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/export.c10
-rw-r--r--fs/nfsd/nfs4callback.c5
-rw-r--r--fs/nfsd/nfs4recover.c4
-rw-r--r--fs/nfsd/nfs4state.c6
-rw-r--r--fs/nfsd/nfs4xdr.c14
-rw-r--r--fs/nfsd/nfsctl.c24
-rw-r--r--fs/nfsd/vfs.c164
7 files changed, 116 insertions, 111 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index c487810a2366..a0c4016413f1 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -1316,19 +1316,11 @@ rqst_exp_parent(struct svc_rqst *rqstp, struct path *path)
1316 1316
1317static struct svc_export *find_fsidzero_export(struct svc_rqst *rqstp) 1317static struct svc_export *find_fsidzero_export(struct svc_rqst *rqstp)
1318{ 1318{
1319 struct svc_export *exp;
1320 u32 fsidv[2]; 1319 u32 fsidv[2];
1321 1320
1322 mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL); 1321 mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
1323 1322
1324 exp = rqst_exp_find(rqstp, FSID_NUM, fsidv); 1323 return rqst_exp_find(rqstp, FSID_NUM, fsidv);
1325 /*
1326 * We shouldn't have accepting an nfsv4 request at all if we
1327 * don't have a pseudoexport!:
1328 */
1329 if (IS_ERR(exp) && PTR_ERR(exp) == -ENOENT)
1330 exp = ERR_PTR(-ESERVERFAULT);
1331 return exp;
1332} 1324}
1333 1325
1334/* 1326/*
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 f19ed866c95f..c97fddbd17db 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1998,7 +1998,9 @@ nfs4_file_downgrade(struct file *filp, unsigned int share_access)
1998{ 1998{
1999 if (share_access & NFS4_SHARE_ACCESS_WRITE) { 1999 if (share_access & NFS4_SHARE_ACCESS_WRITE) {
2000 drop_file_write_access(filp); 2000 drop_file_write_access(filp);
2001 spin_lock(&filp->f_lock);
2001 filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE; 2002 filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE;
2003 spin_unlock(&filp->f_lock);
2002 } 2004 }
2003} 2005}
2004 2006
@@ -2480,8 +2482,10 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
2480 } 2482 }
2481 memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t)); 2483 memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t));
2482 2484
2483 if (nfsd4_has_session(&resp->cstate)) 2485 if (nfsd4_has_session(&resp->cstate)) {
2484 open->op_stateowner->so_confirmed = 1; 2486 open->op_stateowner->so_confirmed = 1;
2487 nfsd4_create_clid_dir(open->op_stateowner->so_client);
2488 }
2485 2489
2486 /* 2490 /*
2487 * 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 143d43a93b72..c47b4d7bafa7 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;
@@ -2121,9 +2121,15 @@ out_acl:
2121 * and this is the root of a cross-mounted filesystem. 2121 * and this is the root of a cross-mounted filesystem.
2122 */ 2122 */
2123 if (ignore_crossmnt == 0 && 2123 if (ignore_crossmnt == 0 &&
2124 exp->ex_path.mnt->mnt_root->d_inode == dentry->d_inode) { 2124 dentry == exp->ex_path.mnt->mnt_root) {
2125 err = vfs_getattr(exp->ex_path.mnt->mnt_parent, 2125 struct path path = exp->ex_path;
2126 exp->ex_path.mnt->mnt_mountpoint, &stat); 2126 path_get(&path);
2127 while (follow_up(&path)) {
2128 if (path.dentry != path.mnt->mnt_root)
2129 break;
2130 }
2131 err = vfs_getattr(path.mnt, path.dentry, &stat);
2132 path_put(&path);
2127 if (err) 2133 if (err)
2128 goto out_nfserr; 2134 goto out_nfserr;
2129 } 2135 }
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 c194793b642b..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,13 +771,13 @@ 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());
753 if (IS_ERR(*filp)) 777 if (IS_ERR(*filp))
754 host_err = PTR_ERR(*filp); 778 host_err = PTR_ERR(*filp);
779 else
780 host_err = ima_file_check(*filp, access);
755out_nfserr: 781out_nfserr:
756 err = nfserrno(host_err); 782 err = nfserrno(host_err);
757out: 783out:
@@ -769,43 +795,6 @@ nfsd_close(struct file *filp)
769} 795}
770 796
771/* 797/*
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_write_and_wait(inode->i_mapping);
784 if (err == 0 && fop && (fsync = fop->fsync))
785 err = fsync(filp, dp, 0);
786 return err;
787}
788
789static int
790nfsd_sync(struct file *filp)
791{
792 int err;
793 struct inode *inode = filp->f_path.dentry->d_inode;
794 dprintk("nfsd: sync file %s\n", filp->f_path.dentry->d_name.name);
795 mutex_lock(&inode->i_mutex);
796 err=nfsd_dosync(filp, filp->f_path.dentry, filp->f_op);
797 mutex_unlock(&inode->i_mutex);
798
799 return err;
800}
801
802int
803nfsd_sync_dir(struct dentry *dp)
804{
805 return nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
806}
807
808/*
809 * Obtain the readahead parameters for the file 798 * Obtain the readahead parameters for the file
810 * specified by (dev, ino). 799 * specified by (dev, ino).
811 */ 800 */
@@ -1008,7 +997,7 @@ static int wait_for_concurrent_writes(struct file *file)
1008 997
1009 if (inode->i_state & I_DIRTY) { 998 if (inode->i_state & I_DIRTY) {
1010 dprintk("nfsd: write sync %d\n", task_pid_nr(current)); 999 dprintk("nfsd: write sync %d\n", task_pid_nr(current));
1011 err = nfsd_sync(file); 1000 err = vfs_fsync(file, file->f_path.dentry, 0);
1012 } 1001 }
1013 last_ino = inode->i_ino; 1002 last_ino = inode->i_ino;
1014 last_dev = inode->i_sb->s_dev; 1003 last_dev = inode->i_sb->s_dev;
@@ -1156,8 +1145,9 @@ out:
1156#ifdef CONFIG_NFSD_V3 1145#ifdef CONFIG_NFSD_V3
1157/* 1146/*
1158 * Commit all pending writes to stable storage. 1147 * Commit all pending writes to stable storage.
1159 * Strictly speaking, we could sync just the indicated file region here, 1148 *
1160 * 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.
1161 * 1151 *
1162 * 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
1163 * 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.
@@ -1167,23 +1157,32 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
1167 loff_t offset, unsigned long count) 1157 loff_t offset, unsigned long count)
1168{ 1158{
1169 struct file *file; 1159 struct file *file;
1170 __be32 err; 1160 loff_t end = LLONG_MAX;
1161 __be32 err = nfserr_inval;
1171 1162
1172 if ((u64)count > ~(u64)offset) 1163 if (offset < 0)
1173 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 }
1174 1170
1175 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file); 1171 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file);
1176 if (err) 1172 if (err)
1177 return err; 1173 goto out;
1178 if (EX_ISSYNC(fhp->fh_export)) { 1174 if (EX_ISSYNC(fhp->fh_export)) {
1179 if (file->f_op && file->f_op->fsync) { 1175 int err2 = vfs_fsync_range(file, file->f_path.dentry,
1180 err = nfserrno(nfsd_sync(file)); 1176 offset, end, 0);
1181 } else { 1177
1178 if (err2 != -EINVAL)
1179 err = nfserrno(err2);
1180 else
1182 err = nfserr_notsupp; 1181 err = nfserr_notsupp;
1183 }
1184 } 1182 }
1185 1183
1186 nfsd_close(file); 1184 nfsd_close(file);
1185out:
1187 return err; 1186 return err;
1188} 1187}
1189#endif /* CONFIG_NFSD_V3 */ 1188#endif /* CONFIG_NFSD_V3 */
@@ -1336,12 +1335,14 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1336 goto out_nfserr; 1335 goto out_nfserr;
1337 } 1336 }
1338 1337
1339 if (EX_ISSYNC(fhp->fh_export)) { 1338 err = nfsd_create_setattr(rqstp, resfhp, iap);
1340 err = nfserrno(nfsd_sync_dir(dentry));
1341 write_inode_now(dchild->d_inode, 1);
1342 }
1343 1339
1344 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));
1345 if (err2) 1346 if (err2)
1346 err = err2; 1347 err = err2;
1347 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1348 mnt_drop_write(fhp->fh_export->ex_path.mnt);
@@ -1373,7 +1374,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1373 struct dentry *dentry, *dchild = NULL; 1374 struct dentry *dentry, *dchild = NULL;
1374 struct inode *dirp; 1375 struct inode *dirp;
1375 __be32 err; 1376 __be32 err;
1376 __be32 err2;
1377 int host_err; 1377 int host_err;
1378 __u32 v_mtime=0, v_atime=0; 1378 __u32 v_mtime=0, v_atime=0;
1379 1379
@@ -1468,11 +1468,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1468 if (created) 1468 if (created)
1469 *created = 1; 1469 *created = 1;
1470 1470
1471 if (EX_ISSYNC(fhp->fh_export)) {
1472 err = nfserrno(nfsd_sync_dir(dentry));
1473 /* setattr will sync the child (or not) */
1474 }
1475
1476 nfsd_check_ignore_resizing(iap); 1471 nfsd_check_ignore_resizing(iap);
1477 1472
1478 if (createmode == NFS3_CREATE_EXCLUSIVE) { 1473 if (createmode == NFS3_CREATE_EXCLUSIVE) {
@@ -1487,9 +1482,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1487 } 1482 }
1488 1483
1489 set_attr: 1484 set_attr:
1490 err2 = nfsd_create_setattr(rqstp, resfhp, iap); 1485 err = nfsd_create_setattr(rqstp, resfhp, iap);
1491 if (err2) 1486
1492 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));
1493 1492
1494 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1493 mnt_drop_write(fhp->fh_export->ex_path.mnt);
1495 /* 1494 /*
@@ -1604,12 +1603,9 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
1604 } 1603 }
1605 } else 1604 } else
1606 host_err = vfs_symlink(dentry->d_inode, dnew, path); 1605 host_err = vfs_symlink(dentry->d_inode, dnew, path);
1607
1608 if (!host_err) {
1609 if (EX_ISSYNC(fhp->fh_export))
1610 host_err = nfsd_sync_dir(dentry);
1611 }
1612 err = nfserrno(host_err); 1606 err = nfserrno(host_err);
1607 if (!err)
1608 err = nfserrno(commit_metadata(fhp));
1613 fh_unlock(fhp); 1609 fh_unlock(fhp);
1614 1610
1615 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1611 mnt_drop_write(fhp->fh_export->ex_path.mnt);
@@ -1671,11 +1667,9 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1671 } 1667 }
1672 host_err = vfs_link(dold, dirp, dnew); 1668 host_err = vfs_link(dold, dirp, dnew);
1673 if (!host_err) { 1669 if (!host_err) {
1674 if (EX_ISSYNC(ffhp->fh_export)) { 1670 err = nfserrno(commit_metadata(ffhp));
1675 err = nfserrno(nfsd_sync_dir(ddir)); 1671 if (!err)
1676 write_inode_now(dest, 1); 1672 err = nfserrno(commit_metadata(tfhp));
1677 }
1678 err = 0;
1679 } else { 1673 } else {
1680 if (host_err == -EXDEV && rqstp->rq_vers == 2) 1674 if (host_err == -EXDEV && rqstp->rq_vers == 2)
1681 err = nfserr_acces; 1675 err = nfserr_acces;
@@ -1771,10 +1765,10 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1771 goto out_dput_new; 1765 goto out_dput_new;
1772 1766
1773 host_err = vfs_rename(fdir, odentry, tdir, ndentry); 1767 host_err = vfs_rename(fdir, odentry, tdir, ndentry);
1774 if (!host_err && EX_ISSYNC(tfhp->fh_export)) { 1768 if (!host_err) {
1775 host_err = nfsd_sync_dir(tdentry); 1769 host_err = commit_metadata(tfhp);
1776 if (!host_err) 1770 if (!host_err)
1777 host_err = nfsd_sync_dir(fdentry); 1771 host_err = commit_metadata(ffhp);
1778 } 1772 }
1779 1773
1780 mnt_drop_write(ffhp->fh_export->ex_path.mnt); 1774 mnt_drop_write(ffhp->fh_export->ex_path.mnt);
@@ -1855,12 +1849,9 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1855 1849
1856 dput(rdentry); 1850 dput(rdentry);
1857 1851
1858 if (host_err) 1852 if (!host_err)
1859 goto out_drop; 1853 host_err = commit_metadata(fhp);
1860 if (EX_ISSYNC(fhp->fh_export))
1861 host_err = nfsd_sync_dir(dentry);
1862 1854
1863out_drop:
1864 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1855 mnt_drop_write(fhp->fh_export->ex_path.mnt);
1865out_nfserr: 1856out_nfserr:
1866 err = nfserrno(host_err); 1857 err = nfserrno(host_err);
@@ -2127,7 +2118,6 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
2127 */ 2118 */
2128 path.mnt = exp->ex_path.mnt; 2119 path.mnt = exp->ex_path.mnt;
2129 path.dentry = dentry; 2120 path.dentry = dentry;
2130 err = ima_path_check(&path, acc & (MAY_READ | MAY_WRITE | MAY_EXEC));
2131nfsd_out: 2121nfsd_out:
2132 return err? nfserrno(err) : 0; 2122 return err? nfserrno(err) : 0;
2133} 2123}