version 1.8.2.6, 2007/12/07 17:31:57 |
version 1.8.2.7, 2008/01/21 09:45:47 |
Line 76 u_long dehash; /* size of hash table - |
|
Line 76 u_long dehash; /* size of hash table - |
|
#define DEHASH(dev, dcl, doff) \ |
#define DEHASH(dev, dcl, doff) \ |
(((dev) + (dcl) + (doff) / sizeof(struct direntry)) & dehash) |
(((dev) + (dcl) + (doff) / sizeof(struct direntry)) & dehash) |
|
|
struct simplelock msdosfs_ihash_slock; |
kmutex_t msdosfs_ihash_lock; |
|
kmutex_t msdosfs_hashlock; |
|
|
struct pool msdosfs_denode_pool; |
struct pool msdosfs_denode_pool; |
|
|
Line 89 static const struct genfs_ops msdosfs_ge |
|
Line 90 static const struct genfs_ops msdosfs_ge |
|
.gop_markupdate = msdosfs_gop_markupdate, |
.gop_markupdate = msdosfs_gop_markupdate, |
}; |
}; |
|
|
static struct denode *msdosfs_hashget(dev_t, u_long, u_long); |
static struct denode *msdosfs_hashget(dev_t, u_long, u_long, int); |
static void msdosfs_hashins(struct denode *); |
static void msdosfs_hashins(struct denode *); |
static void msdosfs_hashrem(struct denode *); |
static void msdosfs_hashrem(struct denode *); |
|
|
|
|
"msdosnopl", &pool_allocator_nointr, IPL_NONE); |
"msdosnopl", &pool_allocator_nointr, IPL_NONE); |
dehashtbl = hashinit(desiredvnodes / 2, HASH_LIST, M_MSDOSFSMNT, |
dehashtbl = hashinit(desiredvnodes / 2, HASH_LIST, M_MSDOSFSMNT, |
M_WAITOK, &dehash); |
M_WAITOK, &dehash); |
simple_lock_init(&msdosfs_ihash_slock); |
mutex_init(&msdosfs_ihash_lock, MUTEX_DEFAULT, IPL_NONE); |
|
mutex_init(&msdosfs_hashlock, MUTEX_DEFAULT, IPL_NONE); |
} |
} |
|
|
/* |
/* |
Line 124 msdosfs_reinit() |
|
Line 126 msdosfs_reinit() |
|
hash = hashinit(desiredvnodes / 2, HASH_LIST, M_MSDOSFSMNT, M_WAITOK, |
hash = hashinit(desiredvnodes / 2, HASH_LIST, M_MSDOSFSMNT, M_WAITOK, |
&mask); |
&mask); |
|
|
simple_lock(&msdosfs_ihash_slock); |
mutex_enter(&msdosfs_ihash_lock); |
oldhash = dehashtbl; |
oldhash = dehashtbl; |
oldmask = dehash; |
oldmask = dehash; |
dehashtbl = hash; |
dehashtbl = hash; |
Line 137 msdosfs_reinit() |
|
Line 139 msdosfs_reinit() |
|
LIST_INSERT_HEAD(&hash[val], dep, de_hash); |
LIST_INSERT_HEAD(&hash[val], dep, de_hash); |
} |
} |
} |
} |
simple_unlock(&msdosfs_ihash_slock); |
mutex_exit(&msdosfs_ihash_lock); |
hashdone(oldhash, M_MSDOSFSMNT); |
hashdone(oldhash, M_MSDOSFSMNT); |
} |
} |
|
|
|
|
{ |
{ |
hashdone(dehashtbl, M_MSDOSFSMNT); |
hashdone(dehashtbl, M_MSDOSFSMNT); |
pool_destroy(&msdosfs_denode_pool); |
pool_destroy(&msdosfs_denode_pool); |
|
mutex_destroy(&msdosfs_ihash_lock); |
|
mutex_destroy(&msdosfs_hashlock); |
malloc_type_detach(M_MSDOSFSTMP); |
malloc_type_detach(M_MSDOSFSTMP); |
malloc_type_detach(M_MSDOSFSFAT); |
malloc_type_detach(M_MSDOSFSFAT); |
malloc_type_detach(M_MSDOSFSMNT); |
malloc_type_detach(M_MSDOSFSMNT); |
} |
} |
|
|
static struct denode * |
static struct denode * |
msdosfs_hashget(dev, dirclust, diroff) |
msdosfs_hashget(dev, dirclust, diroff, flags) |
dev_t dev; |
dev_t dev; |
u_long dirclust; |
u_long dirclust; |
u_long diroff; |
u_long diroff; |
|
int flags; |
{ |
{ |
struct denode *dep; |
struct denode *dep; |
struct vnode *vp; |
struct vnode *vp; |
|
|
loop: |
loop: |
simple_lock(&msdosfs_ihash_slock); |
mutex_enter(&msdosfs_ihash_lock); |
LIST_FOREACH(dep, &dehashtbl[DEHASH(dev, dirclust, diroff)], de_hash) { |
LIST_FOREACH(dep, &dehashtbl[DEHASH(dev, dirclust, diroff)], de_hash) { |
if (dirclust == dep->de_dirclust && |
if (dirclust == dep->de_dirclust && |
diroff == dep->de_diroffset && |
diroff == dep->de_diroffset && |
dev == dep->de_dev && |
dev == dep->de_dev && |
dep->de_refcnt != 0) { |
dep->de_refcnt != 0) { |
vp = DETOV(dep); |
vp = DETOV(dep); |
simple_lock(&vp->v_interlock); |
if (flags == 0) { |
simple_unlock(&msdosfs_ihash_slock); |
mutex_exit(&msdosfs_ihash_lock); |
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) |
} else { |
goto loop; |
mutex_enter(&vp->v_interlock); |
|
mutex_exit(&msdosfs_ihash_lock); |
|
if (vget(vp, flags | LK_INTERLOCK)) |
|
goto loop; |
|
} |
return (dep); |
return (dep); |
} |
} |
} |
} |
simple_unlock(&msdosfs_ihash_slock); |
mutex_exit(&msdosfs_ihash_lock); |
return (NULL); |
return (NULL); |
} |
} |
|
|
Line 186 msdosfs_hashins(dep) |
|
Line 195 msdosfs_hashins(dep) |
|
struct ihashhead *depp; |
struct ihashhead *depp; |
int val; |
int val; |
|
|
simple_lock(&msdosfs_ihash_slock); |
KASSERT(mutex_owned(&msdosfs_hashlock)); |
|
|
|
mutex_enter(&msdosfs_ihash_lock); |
val = DEHASH(dep->de_dev, dep->de_dirclust, dep->de_diroffset); |
val = DEHASH(dep->de_dev, dep->de_dirclust, dep->de_diroffset); |
depp = &dehashtbl[val]; |
depp = &dehashtbl[val]; |
LIST_INSERT_HEAD(depp, dep, de_hash); |
LIST_INSERT_HEAD(depp, dep, de_hash); |
simple_unlock(&msdosfs_ihash_slock); |
mutex_exit(&msdosfs_ihash_lock); |
} |
} |
|
|
static void |
static void |
msdosfs_hashrem(dep) |
msdosfs_hashrem(dep) |
struct denode *dep; |
struct denode *dep; |
{ |
{ |
simple_lock(&msdosfs_ihash_slock); |
mutex_enter(&msdosfs_ihash_lock); |
LIST_REMOVE(dep, de_hash); |
LIST_REMOVE(dep, de_hash); |
simple_unlock(&msdosfs_ihash_slock); |
mutex_exit(&msdosfs_ihash_lock); |
} |
} |
|
|
/* |
/* |
Line 252 deget(pmp, dirclust, diroffset, depp) |
|
Line 263 deget(pmp, dirclust, diroffset, depp) |
|
* entry that represented the file happens to be reused while the |
* entry that represented the file happens to be reused while the |
* deleted file is still open. |
* deleted file is still open. |
*/ |
*/ |
ldep = msdosfs_hashget(pmp->pm_dev, dirclust, diroffset); |
retry: |
|
ldep = msdosfs_hashget(pmp->pm_dev, dirclust, diroffset, LK_EXCLUSIVE); |
if (ldep) { |
if (ldep) { |
*depp = ldep; |
*depp = ldep; |
return (0); |
return (0); |
Line 270 deget(pmp, dirclust, diroffset, depp) |
|
Line 282 deget(pmp, dirclust, diroffset, depp) |
|
return (error); |
return (error); |
} |
} |
ldep = pool_get(&msdosfs_denode_pool, PR_WAITOK); |
ldep = pool_get(&msdosfs_denode_pool, PR_WAITOK); |
|
|
|
/* |
|
* If someone beat us to it, put back the freshly allocated |
|
* vnode/inode pair and retry. |
|
*/ |
|
mutex_enter(&msdosfs_hashlock); |
|
if (msdosfs_hashget(pmp->pm_dev, dirclust, diroffset, 0)) { |
|
mutex_exit(&msdosfs_hashlock); |
|
ungetnewvnode(nvp); |
|
pool_put(&msdosfs_denode_pool, ldep); |
|
goto retry; |
|
} |
memset(ldep, 0, sizeof *ldep); |
memset(ldep, 0, sizeof *ldep); |
nvp->v_data = ldep; |
nvp->v_data = ldep; |
ldep->de_vnode = nvp; |
ldep->de_vnode = nvp; |
Line 289 deget(pmp, dirclust, diroffset, depp) |
|
Line 313 deget(pmp, dirclust, diroffset, depp) |
|
vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY); |
vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY); |
genfs_node_init(nvp, &msdosfs_genfsops); |
genfs_node_init(nvp, &msdosfs_genfsops); |
msdosfs_hashins(ldep); |
msdosfs_hashins(ldep); |
|
mutex_exit(&msdosfs_hashlock); |
|
|
ldep->de_pmp = pmp; |
ldep->de_pmp = pmp; |
ldep->de_devvp = pmp->pm_devvp; |
ldep->de_devvp = pmp->pm_devvp; |
Line 560 deextend(dep, length, cred) |
|
Line 585 deextend(dep, length, cred) |
|
} |
} |
} |
} |
|
|
|
/* |
|
* Zero extend file range; uvm_vnp_zerorange() uses ubc_alloc() and a |
|
* memset(); we set the write size so ubc won't read in file data that |
|
* is zero'd later. |
|
*/ |
osize = dep->de_FileSize; |
osize = dep->de_FileSize; |
dep->de_FileSize = length; |
dep->de_FileSize = length; |
uvm_vnp_setsize(DETOV(dep), (voff_t)dep->de_FileSize); |
uvm_vnp_setwritesize(DETOV(dep), (voff_t)dep->de_FileSize); |
dep->de_flag |= DE_UPDATE|DE_MODIFIED; |
dep->de_flag |= DE_UPDATE|DE_MODIFIED; |
uvm_vnp_zerorange(DETOV(dep), (off_t)osize, |
uvm_vnp_zerorange(DETOV(dep), (off_t)osize, |
(size_t)(dep->de_FileSize - osize)); |
(size_t)(dep->de_FileSize - osize)); |
|
uvm_vnp_setsize(DETOV(dep), (voff_t)dep->de_FileSize); |
return (deupdat(dep, 1)); |
return (deupdat(dep, 1)); |
} |
} |
|
|
|
|
*/ |
*/ |
if (dep->de_Attributes & ATTR_DIRECTORY) |
if (dep->de_Attributes & ATTR_DIRECTORY) |
return; |
return; |
|
mutex_enter(&msdosfs_hashlock); |
msdosfs_hashrem(dep); |
msdosfs_hashrem(dep); |
msdosfs_hashins(dep); |
msdosfs_hashins(dep); |
|
mutex_exit(&msdosfs_hashlock); |
} |
} |
|
|
int |
int |
Line 606 msdosfs_reclaim(v) |
|
Line 639 msdosfs_reclaim(v) |
|
dep, dep->de_Name, dep->de_refcnt); |
dep, dep->de_Name, dep->de_refcnt); |
#endif |
#endif |
|
|
if (prtactive && vp->v_usecount != 0) |
if (prtactive && vp->v_usecount > 1) |
vprint("msdosfs_reclaim(): pushing active", vp); |
vprint("msdosfs_reclaim(): pushing active", vp); |
/* |
/* |
* Remove the denode from its hash chain. |
* Remove the denode from its hash chain. |
Line 635 msdosfs_inactive(v) |
|
Line 668 msdosfs_inactive(v) |
|
{ |
{ |
struct vop_inactive_args /* { |
struct vop_inactive_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
|
bool *a_recycle; |
} */ *ap = v; |
} */ *ap = v; |
struct vnode *vp = ap->a_vp; |
struct vnode *vp = ap->a_vp; |
struct denode *dep = VTODE(vp); |
struct denode *dep = VTODE(vp); |
Line 644 msdosfs_inactive(v) |
|
Line 678 msdosfs_inactive(v) |
|
printf("msdosfs_inactive(): dep %p, de_Name[0] %x\n", dep, dep->de_Name[0]); |
printf("msdosfs_inactive(): dep %p, de_Name[0] %x\n", dep, dep->de_Name[0]); |
#endif |
#endif |
|
|
if (prtactive && vp->v_usecount != 0) |
|
vprint("msdosfs_inactive(): pushing active", vp); |
|
|
|
/* |
/* |
* Get rid of denodes related to stale file handles. |
* Get rid of denodes related to stale file handles. |
*/ |
*/ |
Line 671 msdosfs_inactive(v) |
|
Line 702 msdosfs_inactive(v) |
|
} |
} |
deupdat(dep, 0); |
deupdat(dep, 0); |
out: |
out: |
VOP_UNLOCK(vp, 0); |
|
/* |
/* |
* If we are done with the denode, reclaim it |
* If we are done with the denode, reclaim it |
* so that it can be reused immediately. |
* so that it can be reused immediately. |
|
|
printf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n", |
printf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n", |
vp->v_usecount, dep->de_Name[0]); |
vp->v_usecount, dep->de_Name[0]); |
#endif |
#endif |
if (dep->de_Name[0] == SLOT_DELETED) |
*ap->a_recycle = (dep->de_Name[0] == SLOT_DELETED); |
vrecycle(vp, (struct simplelock *)0, curlwp); |
VOP_UNLOCK(vp, 0); |
return (error); |
return (error); |
} |
} |
|
|