summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-09-16 19:06:44 +0000
committerjhb <jhb@FreeBSD.org>2008-09-16 19:06:44 +0000
commit281938f04d3e2b1b91827e77d5ee4e74471b6a31 (patch)
treedcb0297e7f186a947d0546f2999779af9a1aeeb9 /sys/ufs
parentf4b6175ac36dd9b7f304e8379e2b49bed317fb3e (diff)
downloadFreeBSD-src-281938f04d3e2b1b91827e77d5ee4e74471b6a31.zip
FreeBSD-src-281938f04d3e2b1b91827e77d5ee4e74471b6a31.tar.gz
Retire the 'i_reclen' field from the in-memory i-node. Previously,
during a DELETE lookup operation, lookup would cache the length of the directory entry to be deleted in 'i_reclen'. Later, the actual VOP to remove the directory entry (ufs_remove, ufs_rename, etc.) would call ufs_dirremove() which extended the length of the previous directory entry to "remove" the deleted entry. However, we always read the entire block containing the directory entry when doing the removal, so we always have the directory entry to be deleted in-memory when doing the update to the directory block. Also, we already have to figure out where the directory entry that is being removed is in the block so that we can pass the component name to the dirhash code to update the dirhash. So, instead of passing 'i_reclen' from ufs_lookup() to the ufs_dirremove() routine, just read the 'd_reclen' field directly out of the entry being removed when updating the length of the previous entry in the block. This avoids a cosmetic issue of writing to 'i_reclen' while holding a shared vnode lock. It also slightly reduces the amount of side-band data passed from ufs_lookup() to operations updating a directory via the directory's i-node. Reviewed by: jeff
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ufs/inode.h1
-rw-r--r--sys/ufs/ufs/ufs_lookup.c15
2 files changed, 9 insertions, 7 deletions
diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h
index 5681cb7..39f46d0a 100644
--- a/sys/ufs/ufs/inode.h
+++ b/sys/ufs/ufs/inode.h
@@ -82,7 +82,6 @@ struct inode {
doff_t i_endoff; /* End of useful stuff in directory. */
doff_t i_diroff; /* Offset in dir, where we found last entry. */
doff_t i_offset; /* Offset of free space in directory. */
- u_int32_t i_reclen; /* Size of found directory entry. */
union {
struct dirhash *dirhash; /* Hashing for large directories. */
diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c
index d296857..042ecd0 100644
--- a/sys/ufs/ufs/ufs_lookup.c
+++ b/sys/ufs/ufs/ufs_lookup.c
@@ -362,14 +362,12 @@ foundentry:
slotstatus = FOUND;
slotoffset = i_offset;
slotsize = ep->d_reclen;
- dp->i_reclen = slotsize;
enduseful = dp->i_size;
ap->a_cnp->cn_flags |= ISWHITEOUT;
numdirpasses--;
goto notfound;
}
ino = ep->d_ino;
- dp->i_reclen = ep->d_reclen;
goto found;
}
}
@@ -1005,7 +1003,7 @@ ufs_dirremove(dvp, ip, flags, isrmdir)
int isrmdir;
{
struct inode *dp;
- struct direct *ep;
+ struct direct *ep, *rep;
struct buf *bp;
int error;
@@ -1026,14 +1024,19 @@ ufs_dirremove(dvp, ip, flags, isrmdir)
if ((error = UFS_BLKATOFF(dvp,
(off_t)(dp->i_offset - dp->i_count), (char **)&ep, &bp)) != 0)
return (error);
+
+ /* Set 'rep' to the entry being removed. */
+ if (dp->i_count == 0)
+ rep = ep;
+ else
+ rep = (struct direct *)((char *)ep + ep->d_reclen);
#ifdef UFS_DIRHASH
/*
* Remove the dirhash entry. This is complicated by the fact
* that `ep' is the previous entry when dp->i_count != 0.
*/
if (dp->i_dirhash != NULL)
- ufsdirhash_remove(dp, (dp->i_count == 0) ? ep :
- (struct direct *)((char *)ep + ep->d_reclen), dp->i_offset);
+ ufsdirhash_remove(dp, rep, dp->i_offset);
#endif
if (dp->i_count == 0) {
/*
@@ -1044,7 +1047,7 @@ ufs_dirremove(dvp, ip, flags, isrmdir)
/*
* Collapse new free space into previous entry.
*/
- ep->d_reclen += dp->i_reclen;
+ ep->d_reclen += rep->d_reclen;
}
#ifdef UFS_DIRHASH
if (dp->i_dirhash != NULL)
OpenPOWER on IntegriCloud