svn commit: r305601 - head/sys/ufs/ufs
Konstantin Belousov
kib at FreeBSD.org
Thu Sep 8 12:09:35 UTC 2016
Author: kib
Date: Thu Sep 8 12:09:34 2016
New Revision: 305601
URL: https://svnweb.freebsd.org/changeset/base/305601
Log:
On rename, do not perform truncation of dirhash if the vnode
truncation failed.
Doing so resulted in inconsistent state of the ufs dirhash with regard
to the actual directory inode state, and could lead to spurious ENOENT
errors for lookups of existing files in production kernels, or
assertion failures in the debugging kernels.
Change the logic of calling ufsdirhash_dirtrunc() to be same as in
ufs_direnter(). Execute UFS_TRUNCATE() first, log error, and only do
dirtrunc() if UFS_TRUNCATE() succeeded.
Note that the problem was exacerbated by the bug in the
flush_newblk_dep() function (see r305599), which caused in the spurios
errors from ffs_sync() and then ffs_truncate().
In collaboration with: pho
Reviewed by: mckusick
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Modified:
head/sys/ufs/ufs/ufs_vnops.c
Modified: head/sys/ufs/ufs/ufs_vnops.c
==============================================================================
--- head/sys/ufs/ufs/ufs_vnops.c Thu Sep 8 12:09:13 2016 (r305600)
+++ head/sys/ufs/ufs/ufs_vnops.c Thu Sep 8 12:09:34 2016 (r305601)
@@ -1529,11 +1529,21 @@ unlockout:
* are no longer needed.
*/
if (error == 0 && endoff != 0) {
+ error = UFS_TRUNCATE(tdvp, endoff, IO_NORMAL | IO_SYNC,
+ tcnp->cn_cred);
+ if (error != 0)
+ vn_printf(tdvp, "ufs_rename: failed to truncate "
+ "err %d", error);
#ifdef UFS_DIRHASH
- if (tdp->i_dirhash != NULL)
+ else if (tdp->i_dirhash != NULL)
ufsdirhash_dirtrunc(tdp, endoff);
#endif
- UFS_TRUNCATE(tdvp, endoff, IO_NORMAL | IO_SYNC, tcnp->cn_cred);
+ /*
+ * Even if the directory compaction failed, rename was
+ * succesful. Do not propagate a UFS_TRUNCATE() error
+ * to the caller.
+ */
+ error = 0;
}
if (error == 0 && tdp->i_flag & IN_NEEDSYNC)
error = VOP_FSYNC(tdvp, MNT_WAIT, td);
More information about the svn-src-all
mailing list