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
This commit is contained in:
Poul-Henning Kamp 2005-04-07 07:55:37 +00:00
parent 2e0b9b22f0
commit f4b423ae60
2 changed files with 26 additions and 9 deletions

View File

@ -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) */
};
/*

View File

@ -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