git: 5e198e7646a2 - main - ffs_close_ea: do not relock vnode under lock_ea
Konstantin Belousov
kib at FreeBSD.org
Wed Feb 24 07:57:09 UTC 2021
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=5e198e7646a27412c0541719f7bf1bbc0bd89223
commit 5e198e7646a27412c0541719f7bf1bbc0bd89223
Author: Konstantin Belousov <kib at FreeBSD.org>
AuthorDate: 2021-02-21 10:10:06 +0000
Commit: Konstantin Belousov <kib at FreeBSD.org>
CommitDate: 2021-02-24 07:55:04 +0000
ffs_close_ea: do not relock vnode under lock_ea
ffs_lock_ea is after the vnode lock, so vnode must not be relocked under
lock_ea. Move ffs_truncate() call in ffs_close_ea() after the lock_ea is
dropped, and only truncate to length zero, since this is the only mode
supported by ffs_truncate() for EAs. Previously code did truncation and
then write.
Zero the part of the ext area that is unused, if truncation is due but not
done because ea area is not zero-length.
Reviewed by: mckusick
Tested by: pho
MFC after: 1 week
Sponsored by: The FreeBSD Foundation
---
sys/ufs/ffs/ffs_vnops.c | 37 +++++++++++++++++++++++++++----------
1 file changed, 27 insertions(+), 10 deletions(-)
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index 4e574f85c9e4..9be46951c04e 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -1422,9 +1422,10 @@ ffs_close_ea(struct vnode *vp, int commit, struct ucred *cred, struct thread *td
{
struct inode *ip;
struct uio luio;
- struct iovec liovec;
+ struct iovec *liovec;
struct ufs2_dinode *dp;
- int error;
+ size_t ea_len, tlen;
+ int error, i, lcnt;
ip = VTOI(vp);
@@ -1439,18 +1440,31 @@ ffs_close_ea(struct vnode *vp, int commit, struct ucred *cred, struct thread *td
ASSERT_VOP_ELOCKED(vp, "ffs_close_ea commit");
if (cred == NOCRED)
cred = vp->v_mount->mnt_cred;
- liovec.iov_base = ip->i_ea_area;
- liovec.iov_len = ip->i_ea_len;
- luio.uio_iov = &liovec;
- luio.uio_iovcnt = 1;
+
+ ea_len = MAX(ip->i_ea_len, dp->di_extsize);
+ for (lcnt = 1, tlen = ea_len - ip->i_ea_len; tlen > 0;) {
+ tlen -= MIN(ZERO_REGION_SIZE, tlen);
+ lcnt++;
+ }
+
+ liovec = __builtin_alloca(lcnt * sizeof(struct iovec));
+ luio.uio_iovcnt = lcnt;
+
+ liovec[0].iov_base = ip->i_ea_area;
+ liovec[0].iov_len = ip->i_ea_len;
+ for (i = 1, tlen = ea_len; i < lcnt; i++) {
+ liovec[i].iov_base = __DECONST(void *, zero_region);
+ liovec[i].iov_len = MIN(ZERO_REGION_SIZE, tlen);
+ tlen -= liovec[i].iov_len;
+ }
+ MPASS(tlen == ip->i_ea_len);
+
+ luio.uio_iov = liovec;
luio.uio_offset = 0;
- luio.uio_resid = ip->i_ea_len;
+ luio.uio_resid = ea_len;
luio.uio_segflg = UIO_SYSSPACE;
luio.uio_rw = UIO_WRITE;
luio.uio_td = td;
- /* XXX: I'm not happy about truncating to zero size */
- if (ip->i_ea_len < dp->di_extsize)
- error = ffs_truncate(vp, 0, IO_EXT, cred);
error = ffs_extwrite(vp, &luio, IO_EXT | IO_SYNC, cred);
}
if (--ip->i_ea_refs == 0) {
@@ -1460,6 +1474,9 @@ ffs_close_ea(struct vnode *vp, int commit, struct ucred *cred, struct thread *td
ip->i_ea_error = 0;
}
ffs_unlock_ea(vp);
+
+ if (commit && error == 0 && ip->i_ea_len == 0)
+ ffs_truncate(vp, 0, IO_EXT, cred);
return (error);
}
More information about the dev-commits-src-all
mailing list