diff options
author | phk <phk@FreeBSD.org> | 2005-04-07 07:55:37 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2005-04-07 07:55:37 +0000 |
commit | bae9f6cfa0c2c9dd7716b10fa98896be0722850c (patch) | |
tree | 27302aa42f5e6b37b7bd6e06813acd6a8118297f /sys/fs | |
parent | b7a4869221a838f4dd4856a2d45e1a47c03f4e72 (diff) | |
download | FreeBSD-src-bae9f6cfa0c2c9dd7716b10fa98896be0722850c.zip FreeBSD-src-bae9f6cfa0c2c9dd7716b10fa98896be0722850c.tar.gz |
Give msdosfs a unique inode number which is really the byteoffset of
the directory entry.
This solves the corruption problem I belive.
Regression test script by: silby
Diffstat (limited to 'sys/fs')
-rw-r--r-- | sys/fs/msdosfs/denode.h | 1 | ||||
-rw-r--r-- | sys/fs/msdosfs/msdosfs_denode.c | 34 |
2 files changed, 26 insertions, 9 deletions
diff --git a/sys/fs/msdosfs/denode.h b/sys/fs/msdosfs/denode.h index e3f5bb2..cbba8e7 100644 --- a/sys/fs/msdosfs/denode.h +++ b/sys/fs/msdosfs/denode.h @@ -158,6 +158,7 @@ struct denode { struct fatcache de_fc[FC_SIZE]; /* fat cache */ u_quad_t de_modrev; /* Revision level for lease. */ struct lockf *de_lockf; /* lockf */ + u_int64_t de_inode; /* Inode number (really byte offset of direntry) */ }; /* diff --git a/sys/fs/msdosfs/msdosfs_denode.c b/sys/fs/msdosfs/msdosfs_denode.c index fcb2686..af6304c 100644 --- a/sys/fs/msdosfs/msdosfs_denode.c +++ b/sys/fs/msdosfs/msdosfs_denode.c @@ -69,7 +69,16 @@ static MALLOC_DEFINE(M_MSDOSFSNODE, "MSDOSFS node", "MSDOSFS vnode private part"); -#define DEHASH(dcl, doff) ((dcl) + (doff) / sizeof(struct direntry)) +static int +de_vncmpf(struct vnode *vp, void *arg) +{ + struct denode *de; + uint64_t *a; + + a = arg; + de = VTODE(vp); + return (de->de_inode != *a); +} /* * If deget() succeeds it returns with the gotten denode locked(). @@ -91,15 +100,13 @@ deget(pmp, dirclust, diroffset, depp) struct denode **depp; /* returns the addr of the gotten denode */ { int error; - u_int hash; + uint64_t inode; struct mount *mntp = pmp->pm_mountp; struct direntry *direntptr; struct denode *ldep; struct vnode *nvp, *xvp; struct buf *bp; - hash = DEHASH(dirclust, diroffset); - #ifdef MSDOSFS_DEBUG printf("deget(pmp %p, dirclust %lu, diroffset %lx, depp %p)\n", pmp, dirclust, diroffset, depp); @@ -124,12 +131,16 @@ deget(pmp, dirclust, diroffset, depp) * entry that represented the file happens to be reused while the * deleted file is still open. */ - error = vfs_hash_get(mntp, hash, LK_EXCLUSIVE, curthread, &nvp, - NULL, NULL); + inode = pmp->pm_bpcluster * dirclust + diroffset; + + error = vfs_hash_get(mntp, inode, LK_EXCLUSIVE, curthread, &nvp, + de_vncmpf, &inode); if (error) return(error); if (nvp != NULL) { *depp = VTODE(nvp); + KASSERT((*depp)->de_dirclust == dirclust, ("wrong dirclust")); + KASSERT((*depp)->de_diroffset == diroffset, ("wrong diroffset")); return (0); } @@ -157,10 +168,11 @@ deget(pmp, dirclust, diroffset, depp) ldep->de_flag = 0; ldep->de_dirclust = dirclust; ldep->de_diroffset = diroffset; + ldep->de_inode = inode; fc_purge(ldep, 0); /* init the fat cache for this denode */ - error = vfs_hash_insert(nvp, hash, LK_EXCLUSIVE, curthread, &xvp, - NULL, NULL); + error = vfs_hash_insert(nvp, inode, LK_EXCLUSIVE, curthread, &xvp, + de_vncmpf, &inode); if (error) { *depp = NULL; return (error); @@ -510,10 +522,14 @@ reinsert(dep) * so we must remove it from the cache and re-enter it with the * hash based on the new location of the directory entry. */ +#if 0 if (dep->de_Attributes & ATTR_DIRECTORY) return; +#endif vp = DETOV(dep); - vfs_hash_rehash(vp, DEHASH(dep->de_dirclust, dep->de_diroffset)); + dep->de_inode = dep->de_pmp->pm_bpcluster * dep->de_dirclust + + dep->de_diroffset; + vfs_hash_rehash(vp, dep->de_inode); } int |