diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/export.c | 10 | ||||
-rw-r--r-- | fs/nfsd/nfs4callback.c | 5 | ||||
-rw-r--r-- | fs/nfsd/nfs4recover.c | 4 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 6 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 14 | ||||
-rw-r--r-- | fs/nfsd/nfsctl.c | 24 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 164 |
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 | ||
1317 | static struct svc_export *find_fsidzero_export(struct svc_rqst *rqstp) | 1317 | static 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 | ||
526 | int set_callback_cred(void) | 526 | int 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: | |||
119 | static void | 119 | static void |
120 | nfsd4_sync_rec_dir(void) | 120 | nfsd4_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 | ||
127 | int | 125 | int |
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) | |||
988 | static ssize_t __write_ports_addxprt(char *buf) | 988 | static 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; |
1014 | out_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 | } | ||
1020 | out_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 | */ | ||
278 | static int | ||
279 | commit_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); | ||
755 | out_nfserr: | 781 | out_nfserr: |
756 | err = nfserrno(host_err); | 782 | err = nfserrno(host_err); |
757 | out: | 783 | out: |
@@ -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 | */ | ||
776 | static 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 | |||
789 | static int | ||
790 | nfsd_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 | |||
802 | int | ||
803 | nfsd_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); |
1185 | out: | ||
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 | ||
1863 | out_drop: | ||
1864 | mnt_drop_write(fhp->fh_export->ex_path.mnt); | 1855 | mnt_drop_write(fhp->fh_export->ex_path.mnt); |
1865 | out_nfserr: | 1856 | out_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)); | ||
2131 | nfsd_out: | 2121 | nfsd_out: |
2132 | return err? nfserrno(err) : 0; | 2122 | return err? nfserrno(err) : 0; |
2133 | } | 2123 | } |