aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYAMAMOTO Takashi <yamamoto@valinux.co.jp>2006-01-18 20:43:13 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-18 22:20:24 -0500
commitf193fbab2e4710f629e7c1859d4908646b47b126 (patch)
treef452b246ad608d2b53cf80a2ac79f77b347739df
parent6b192832daae6d141063c49ae1ded6f7dddee50e (diff)
[PATCH] nfsd: check error status from nfsd_sync_dir
Change nfsd_sync_dir to return an error if ->sync fails, and pass that error up through the stack. This involves a number of rearrangements of error paths, and care to distinguish between Linux -errno numbers and NFSERR numbers. In the 'create' routines, we continue with the 'setattr' even if a previous sync_dir failed. This patch is quite different from Takashi's in a few ways, but there is still a strong lineage. Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/nfsd/vfs.c80
-rw-r--r--include/linux/nfsd/nfsd.h2
2 files changed, 45 insertions, 37 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index eef0576a7785..acf637869ccf 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -710,14 +710,15 @@ static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
710{ 710{
711 struct inode *inode = dp->d_inode; 711 struct inode *inode = dp->d_inode;
712 int (*fsync) (struct file *, struct dentry *, int); 712 int (*fsync) (struct file *, struct dentry *, int);
713 int err = nfs_ok; 713 int err;
714 714
715 filemap_fdatawrite(inode->i_mapping); 715 err = filemap_fdatawrite(inode->i_mapping);
716 if (fop && (fsync = fop->fsync)) 716 if (err == 0 && fop && (fsync = fop->fsync))
717 err=fsync(filp, dp, 0); 717 err = fsync(filp, dp, 0);
718 filemap_fdatawait(inode->i_mapping); 718 if (err == 0)
719 err = filemap_fdatawait(inode->i_mapping);
719 720
720 return nfserrno(err); 721 return err;
721} 722}
722 723
723 724
@@ -734,10 +735,10 @@ nfsd_sync(struct file *filp)
734 return err; 735 return err;
735} 736}
736 737
737void 738int
738nfsd_sync_dir(struct dentry *dp) 739nfsd_sync_dir(struct dentry *dp)
739{ 740{
740 nfsd_dosync(NULL, dp, dp->d_inode->i_fop); 741 return nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
741} 742}
742 743
743/* 744/*
@@ -1065,6 +1066,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
1065 if (EX_ISSYNC(fhp->fh_export)) { 1066 if (EX_ISSYNC(fhp->fh_export)) {
1066 if (file->f_op && file->f_op->fsync) { 1067 if (file->f_op && file->f_op->fsync) {
1067 err = nfsd_sync(file); 1068 err = nfsd_sync(file);
1069 err = nfserrno(err);
1068 } else { 1070 } else {
1069 err = nfserr_notsupp; 1071 err = nfserr_notsupp;
1070 } 1072 }
@@ -1175,7 +1177,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1175 goto out_nfserr; 1177 goto out_nfserr;
1176 1178
1177 if (EX_ISSYNC(fhp->fh_export)) { 1179 if (EX_ISSYNC(fhp->fh_export)) {
1178 nfsd_sync_dir(dentry); 1180 err = nfsd_sync_dir(dentry);
1179 write_inode_now(dchild->d_inode, 1); 1181 write_inode_now(dchild->d_inode, 1);
1180 } 1182 }
1181 1183
@@ -1185,9 +1187,11 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1185 * send along the gid when it tries to implement setgid 1187 * send along the gid when it tries to implement setgid
1186 * directories via NFS. 1188 * directories via NFS.
1187 */ 1189 */
1188 err = 0; 1190 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) {
1189 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) 1191 int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
1190 err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); 1192 if (err2)
1193 err = err2;
1194 }
1191 /* 1195 /*
1192 * Update the file handle to get the new inode info. 1196 * Update the file handle to get the new inode info.
1193 */ 1197 */
@@ -1306,17 +1310,12 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1306 goto out_nfserr; 1310 goto out_nfserr;
1307 1311
1308 if (EX_ISSYNC(fhp->fh_export)) { 1312 if (EX_ISSYNC(fhp->fh_export)) {
1309 nfsd_sync_dir(dentry); 1313 err = nfsd_sync_dir(dentry);
1314 if (err)
1315 err = nfserrno(err);
1310 /* setattr will sync the child (or not) */ 1316 /* setattr will sync the child (or not) */
1311 } 1317 }
1312 1318
1313 /*
1314 * Update the filehandle to get the new inode info.
1315 */
1316 err = fh_update(resfhp);
1317 if (err)
1318 goto out;
1319
1320 if (createmode == NFS3_CREATE_EXCLUSIVE) { 1319 if (createmode == NFS3_CREATE_EXCLUSIVE) {
1321 /* Cram the verifier into atime/mtime/mode */ 1320 /* Cram the verifier into atime/mtime/mode */
1322 iap->ia_valid = ATTR_MTIME|ATTR_ATIME 1321 iap->ia_valid = ATTR_MTIME|ATTR_ATIME
@@ -1337,8 +1336,17 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1337 * implement setgid directories via NFS. Clear out all that cruft. 1336 * implement setgid directories via NFS. Clear out all that cruft.
1338 */ 1337 */
1339 set_attr: 1338 set_attr:
1340 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) 1339 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) {
1341 err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); 1340 int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
1341 if (err2)
1342 err = nfserrno(err2);
1343 }
1344
1345 /*
1346 * Update the filehandle to get the new inode info.
1347 */
1348 if (!err)
1349 err = fh_update(resfhp);
1342 1350
1343 out: 1351 out:
1344 fh_unlock(fhp); 1352 fh_unlock(fhp);
@@ -1447,10 +1455,10 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
1447 } else 1455 } else
1448 err = vfs_symlink(dentry->d_inode, dnew, path, mode); 1456 err = vfs_symlink(dentry->d_inode, dnew, path, mode);
1449 1457
1450 if (!err) { 1458 if (!err)
1451 if (EX_ISSYNC(fhp->fh_export)) 1459 if (EX_ISSYNC(fhp->fh_export))
1452 nfsd_sync_dir(dentry); 1460 err = nfsd_sync_dir(dentry);
1453 } else 1461 if (err)
1454 err = nfserrno(err); 1462 err = nfserrno(err);
1455 fh_unlock(fhp); 1463 fh_unlock(fhp);
1456 1464
@@ -1506,8 +1514,10 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1506 err = vfs_link(dold, dirp, dnew); 1514 err = vfs_link(dold, dirp, dnew);
1507 if (!err) { 1515 if (!err) {
1508 if (EX_ISSYNC(ffhp->fh_export)) { 1516 if (EX_ISSYNC(ffhp->fh_export)) {
1509 nfsd_sync_dir(ddir); 1517 err = nfsd_sync_dir(ddir);
1510 write_inode_now(dest, 1); 1518 write_inode_now(dest, 1);
1519 if (err)
1520 err = nfserrno(err);
1511 } 1521 }
1512 } else { 1522 } else {
1513 if (err == -EXDEV && rqstp->rq_vers == 2) 1523 if (err == -EXDEV && rqstp->rq_vers == 2)
@@ -1595,8 +1605,9 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1595#endif 1605#endif
1596 err = vfs_rename(fdir, odentry, tdir, ndentry); 1606 err = vfs_rename(fdir, odentry, tdir, ndentry);
1597 if (!err && EX_ISSYNC(tfhp->fh_export)) { 1607 if (!err && EX_ISSYNC(tfhp->fh_export)) {
1598 nfsd_sync_dir(tdentry); 1608 err = nfsd_sync_dir(tdentry);
1599 nfsd_sync_dir(fdentry); 1609 if (!err)
1610 err = nfsd_sync_dir(fdentry);
1600 } 1611 }
1601 1612
1602 out_dput_new: 1613 out_dput_new:
@@ -1671,17 +1682,14 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1671 1682
1672 dput(rdentry); 1683 dput(rdentry);
1673 1684
1674 if (err) 1685 if (err == 0 &&
1675 goto out_nfserr; 1686 EX_ISSYNC(fhp->fh_export))
1676 if (EX_ISSYNC(fhp->fh_export)) 1687 err = nfsd_sync_dir(dentry);
1677 nfsd_sync_dir(dentry);
1678
1679out:
1680 return err;
1681 1688
1682out_nfserr: 1689out_nfserr:
1683 err = nfserrno(err); 1690 err = nfserrno(err);
1684 goto out; 1691out:
1692 return err;
1685} 1693}
1686 1694
1687/* 1695/*
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 51c231a1e5a6..ec7c2e872d72 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -124,7 +124,7 @@ int nfsd_statfs(struct svc_rqst *, struct svc_fh *,
124 124
125int nfsd_notify_change(struct inode *, struct iattr *); 125int nfsd_notify_change(struct inode *, struct iattr *);
126int nfsd_permission(struct svc_export *, struct dentry *, int); 126int nfsd_permission(struct svc_export *, struct dentry *, int);
127void nfsd_sync_dir(struct dentry *dp); 127int nfsd_sync_dir(struct dentry *dp);
128 128
129#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 129#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
130#ifdef CONFIG_NFSD_V2_ACL 130#ifdef CONFIG_NFSD_V2_ACL