@@ -1181,25 +1181,58 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, u64 offset,
11811181 return err ;
11821182}
11831183
1184- static __be32
1185- nfsd_create_setattr (struct svc_rqst * rqstp , struct svc_fh * resfhp ,
1186- struct iattr * iap )
1184+ /**
1185+ * nfsd_create_setattr - Set a created file's attributes
1186+ * @rqstp: RPC transaction being executed
1187+ * @fhp: NFS filehandle of parent directory
1188+ * @resfhp: NFS filehandle of new object
1189+ * @iap: requested attributes of new object
1190+ *
1191+ * Returns nfs_ok on success, or an nfsstat in network byte order.
1192+ */
1193+ __be32
1194+ nfsd_create_setattr (struct svc_rqst * rqstp , struct svc_fh * fhp ,
1195+ struct svc_fh * resfhp , struct iattr * iap )
11871196{
1197+ __be32 status ;
1198+
11881199 /*
1189- * Mode has already been set earlier in create:
1200+ * Mode has already been set by file creation.
11901201 */
11911202 iap -> ia_valid &= ~ATTR_MODE ;
1203+
11921204 /*
11931205 * Setting uid/gid works only for root. Irix appears to
11941206 * send along the gid on create when it tries to implement
11951207 * setgid directories via NFS:
11961208 */
11971209 if (!uid_eq (current_fsuid (), GLOBAL_ROOT_UID ))
11981210 iap -> ia_valid &= ~(ATTR_UID |ATTR_GID );
1211+
1212+ /*
1213+ * Callers expect new file metadata to be committed even
1214+ * if the attributes have not changed.
1215+ */
11991216 if (iap -> ia_valid )
1200- return nfsd_setattr (rqstp , resfhp , iap , 0 , (time64_t )0 );
1201- /* Callers expect file metadata to be committed here */
1202- return nfserrno (commit_metadata (resfhp ));
1217+ status = nfsd_setattr (rqstp , resfhp , iap , 0 , (time64_t )0 );
1218+ else
1219+ status = nfserrno (commit_metadata (resfhp ));
1220+
1221+ /*
1222+ * Transactional filesystems had a chance to commit changes
1223+ * for both parent and child simultaneously making the
1224+ * following commit_metadata a noop in many cases.
1225+ */
1226+ if (!status )
1227+ status = nfserrno (commit_metadata (fhp ));
1228+
1229+ /*
1230+ * Update the new filehandle to pick up the new attributes.
1231+ */
1232+ if (!status )
1233+ status = fh_update (resfhp );
1234+
1235+ return status ;
12031236}
12041237
12051238/* HPUX client sometimes creates a file in mode 000, and sets size to 0.
@@ -1226,7 +1259,6 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
12261259 struct dentry * dentry , * dchild ;
12271260 struct inode * dirp ;
12281261 __be32 err ;
1229- __be32 err2 ;
12301262 int host_err ;
12311263
12321264 dentry = fhp -> fh_dentry ;
@@ -1299,22 +1331,8 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
12991331 if (host_err < 0 )
13001332 goto out_nfserr ;
13011333
1302- err = nfsd_create_setattr (rqstp , resfhp , iap );
1334+ err = nfsd_create_setattr (rqstp , fhp , resfhp , iap );
13031335
1304- /*
1305- * nfsd_create_setattr already committed the child. Transactional
1306- * filesystems had a chance to commit changes for both parent and
1307- * child simultaneously making the following commit_metadata a
1308- * noop.
1309- */
1310- err2 = nfserrno (commit_metadata (fhp ));
1311- if (err2 )
1312- err = err2 ;
1313- /*
1314- * Update the file handle to get the new inode info.
1315- */
1316- if (!err )
1317- err = fh_update (resfhp );
13181336out :
13191337 dput (dchild );
13201338 return err ;
@@ -1505,20 +1523,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
15051523 }
15061524
15071525 set_attr :
1508- err = nfsd_create_setattr (rqstp , resfhp , iap );
1509-
1510- /*
1511- * nfsd_create_setattr already committed the child
1512- * (and possibly also the parent).
1513- */
1514- if (!err )
1515- err = nfserrno (commit_metadata (fhp ));
1516-
1517- /*
1518- * Update the filehandle to get the new inode info.
1519- */
1520- if (!err )
1521- err = fh_update (resfhp );
1526+ err = nfsd_create_setattr (rqstp , fhp , resfhp , iap );
15221527
15231528 out :
15241529 fh_unlock (fhp );
0 commit comments