static LIST_HEAD(nfsnodehashhead, nfsnode) * nfsnodehashtbl;
static u_long nfsnodehash;
-static lck_grp_t *nfs_node_hash_lck_grp;
-static lck_grp_t *nfs_node_lck_grp;
-static lck_grp_t *nfs_data_lck_grp;
-lck_mtx_t *nfs_node_hash_mutex;
+static LCK_GRP_DECLARE(nfs_node_hash_lck_grp, "nfs_node_hash");
+static LCK_GRP_DECLARE(nfs_node_lck_grp, "nfs_node");
+static LCK_GRP_DECLARE(nfs_data_lck_grp, "nfs_data");
+LCK_MTX_DECLARE(nfs_node_hash_mutex, &nfs_node_hash_lck_grp);
ZONE_DECLARE(nfsnode_zone, "NFS node",
sizeof(struct nfsnode), ZC_ZFREE_CLEARMEM);
#define NFS_NODE_DBG(...) NFS_DBG(NFS_FAC_NODE, 7, ## __VA_ARGS__)
-/*
- * Initialize hash links for nfsnodes
- * and build nfsnode free list.
- */
-void
-nfs_nhinit(void)
-{
- nfs_node_hash_lck_grp = lck_grp_alloc_init("nfs_node_hash", LCK_GRP_ATTR_NULL);
- nfs_node_hash_mutex = lck_mtx_alloc_init(nfs_node_hash_lck_grp, LCK_ATTR_NULL);
- nfs_node_lck_grp = lck_grp_alloc_init("nfs_node", LCK_GRP_ATTR_NULL);
- nfs_data_lck_grp = lck_grp_alloc_init("nfs_data", LCK_GRP_ATTR_NULL);
-}
-
void
nfs_nhinit_finish(void)
{
- lck_mtx_lock(nfs_node_hash_mutex);
+ lck_mtx_lock(&nfs_node_hash_mutex);
if (!nfsnodehashtbl) {
nfsnodehashtbl = hashinit(desiredvnodes, M_NFSNODE, &nfsnodehash);
}
- lck_mtx_unlock(nfs_node_hash_mutex);
+ lck_mtx_unlock(&nfs_node_hash_mutex);
}
/*
cn_namelen = cnp ? cnp->cn_namelen : 0;
nfshash = nfs_hash(fhp, fhsize);
loop:
- lck_mtx_lock(nfs_node_hash_mutex);
+ lck_mtx_lock(&nfs_node_hash_mutex);
nhpp = NFSNOHASH(nfshash);
for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) {
mp2 = (np->n_hflag & NHINIT) ? np->n_mount : NFSTOMP(np);
if ((np->n_hflag & NHINIT) || ((np->n_hflag & NHLOCKED) && !(flags & NG_NOCREATE))) {
np->n_hflag |= NHLOCKWANT;
FSDBG(263, dnp, np, np->n_flag, 0xcace2222);
- msleep(np, nfs_node_hash_mutex, PDROP | PINOD, "nfs_nget", NULL);
+ msleep(np, &nfs_node_hash_mutex, PDROP | PINOD, "nfs_nget", NULL);
FSDBG(263, dnp, np, np->n_flag, 0xcace3333);
goto loop;
}
vp = NFSTOV(np);
vid = vnode_vid(vp);
- lck_mtx_unlock(nfs_node_hash_mutex);
+ lck_mtx_unlock(&nfs_node_hash_mutex);
if ((error = vnode_getwithvid(vp, vid))) {
/*
* If vnode is being reclaimed or has already
FSDBG(263, mp, dnp, npp, 0xaaaaaaaa);
if (flags & NG_NOCREATE) {
- lck_mtx_unlock(nfs_node_hash_mutex);
+ lck_mtx_unlock(&nfs_node_hash_mutex);
*npp = 0;
FSDBG_BOT(263, dnp, *npp, 0x80000001, ENOENT);
return ENOENT;
if (fhsize > NFS_SMALLFH) {
MALLOC(np->n_fhp, u_char *, fhsize, M_NFSBIGFH, M_WAITOK);
if (!np->n_fhp) {
- lck_mtx_unlock(nfs_node_hash_mutex);
+ lck_mtx_unlock(&nfs_node_hash_mutex);
NFS_ZFREE(nfsnode_zone, np);
*npp = 0;
FSDBG_BOT(263, dnp, *npp, 0x80000002, ENOMEM);
FSDBG(266, 0, np, np->n_flag, np->n_hflag);
/* lock the new nfsnode */
- lck_mtx_init(&np->n_lock, nfs_node_lck_grp, LCK_ATTR_NULL);
- lck_rw_init(&np->n_datalock, nfs_data_lck_grp, LCK_ATTR_NULL);
- lck_mtx_init(&np->n_openlock, nfs_open_grp, LCK_ATTR_NULL);
+ lck_mtx_init(&np->n_lock, &nfs_node_lck_grp, LCK_ATTR_NULL);
+ lck_rw_init(&np->n_datalock, &nfs_data_lck_grp, LCK_ATTR_NULL);
+ lck_mtx_init(&np->n_openlock, &nfs_open_grp, LCK_ATTR_NULL);
lck_mtx_lock(&np->n_lock);
/* release lock on hash table */
- lck_mtx_unlock(nfs_node_hash_mutex);
+ lck_mtx_unlock(&nfs_node_hash_mutex);
/* do initial loading of attributes */
NACLINVALIDATE(np);
if (error) {
FSDBG(266, 0, np, np->n_flag, 0xb1eb1e);
nfs_node_unlock(np);
- lck_mtx_lock(nfs_node_hash_mutex);
+ lck_mtx_lock(&nfs_node_hash_mutex);
LIST_REMOVE(np, n_hash);
np->n_hflag &= ~(NHHASHED | NHINIT | NHLOCKED);
if (np->n_hflag & NHLOCKWANT) {
np->n_hflag &= ~NHLOCKWANT;
wakeup(np);
}
- lck_mtx_unlock(nfs_node_hash_mutex);
+ lck_mtx_unlock(&nfs_node_hash_mutex);
if (np->n_parent) {
if (!vnode_get(np->n_parent)) {
vnode_rele(np->n_parent);
}
np->n_parent = NULL;
}
- lck_mtx_destroy(&np->n_lock, nfs_node_lck_grp);
- lck_rw_destroy(&np->n_datalock, nfs_data_lck_grp);
- lck_mtx_destroy(&np->n_openlock, nfs_open_grp);
+ lck_mtx_destroy(&np->n_lock, &nfs_node_lck_grp);
+ lck_rw_destroy(&np->n_datalock, &nfs_data_lck_grp);
+ lck_mtx_destroy(&np->n_openlock, &nfs_open_grp);
if (np->n_fhsize > NFS_SMALLFH) {
FREE(np->n_fhp, M_NFSBIGFH);
}
if (error) {
FSDBG(266, 0, np, np->n_flag, 0xb1eb1e);
nfs_node_unlock(np);
- lck_mtx_lock(nfs_node_hash_mutex);
+ lck_mtx_lock(&nfs_node_hash_mutex);
LIST_REMOVE(np, n_hash);
np->n_hflag &= ~(NHHASHED | NHINIT | NHLOCKED);
if (np->n_hflag & NHLOCKWANT) {
np->n_hflag &= ~NHLOCKWANT;
wakeup(np);
}
- lck_mtx_unlock(nfs_node_hash_mutex);
+ lck_mtx_unlock(&nfs_node_hash_mutex);
if (np->n_parent) {
if (!vnode_get(np->n_parent)) {
vnode_rele(np->n_parent);
}
np->n_parent = NULL;
}
- lck_mtx_destroy(&np->n_lock, nfs_node_lck_grp);
- lck_rw_destroy(&np->n_datalock, nfs_data_lck_grp);
- lck_mtx_destroy(&np->n_openlock, nfs_open_grp);
+ lck_mtx_destroy(&np->n_lock, &nfs_node_lck_grp);
+ lck_rw_destroy(&np->n_datalock, &nfs_data_lck_grp);
+ lck_mtx_destroy(&np->n_openlock, &nfs_open_grp);
if (np->n_fhsize > NFS_SMALLFH) {
FREE(np->n_fhp, M_NFSBIGFH);
}
/* node is now initialized */
/* check if anyone's waiting on this node */
- lck_mtx_lock(nfs_node_hash_mutex);
+ lck_mtx_lock(&nfs_node_hash_mutex);
np->n_hflag &= ~(NHINIT | NHLOCKED);
if (np->n_hflag & NHLOCKWANT) {
np->n_hflag &= ~NHLOCKWANT;
wakeup(np);
}
- lck_mtx_unlock(nfs_node_hash_mutex);
+ lck_mtx_unlock(&nfs_node_hash_mutex);
*npp = np;
ubc_setsize(vp, 0);
}
- /* mark this node and the directory busy while we do the remove */
- busyerror = nfs_node_set_busy2(nsp->nsr_dnp, np, vfs_context_thread(ctx));
+ if (!vfs_isforce(nmp->nm_mountp)) {
+ /* mark this node and the directory busy while we do the remove */
+ busyerror = nfs_node_set_busy2(nsp->nsr_dnp, np, vfs_context_thread(ctx));
+ } else {
+ /* we are in force unmount we can't trust nsp->nsr_dnp, mark this np busy only */
+ busyerror = nfs_node_set_busy(np, vfs_context_thread(ctx));
+ }
/* lock the node while we remove the silly file */
- lck_mtx_lock(nfs_node_hash_mutex);
+ lck_mtx_lock(&nfs_node_hash_mutex);
while (np->n_hflag & NHLOCKED) {
np->n_hflag |= NHLOCKWANT;
- msleep(np, nfs_node_hash_mutex, PINOD, "nfs_inactive", NULL);
+ msleep(np, &nfs_node_hash_mutex, PINOD, "nfs_inactive", NULL);
}
np->n_hflag |= NHLOCKED;
- lck_mtx_unlock(nfs_node_hash_mutex);
+ lck_mtx_unlock(&nfs_node_hash_mutex);
- /* purge the name cache to deter others from finding it */
- bzero(&cn, sizeof(cn));
- cn.cn_nameptr = nsp->nsr_name;
- cn.cn_namelen = nsp->nsr_namlen;
- nfs_name_cache_purge(nsp->nsr_dnp, np, &cn, ctx);
+ if (!vfs_isforce(nmp->nm_mountp)) {
+ /* purge the name cache to deter others from finding it */
+ bzero(&cn, sizeof(cn));
+ cn.cn_nameptr = nsp->nsr_name;
+ cn.cn_namelen = nsp->nsr_namlen;
+ nfs_name_cache_purge(nsp->nsr_dnp, np, &cn, ctx);
+ }
FSDBG(264, np, np->n_size, np->n_vattr.nva_size, 0xf00d00f1);
- /* now remove the silly file */
- nfs_removeit(nsp);
+ if (!vfs_isforce(nmp->nm_mountp)) {
+ /* now remove the silly file */
+ nfs_removeit(nsp);
+ }
/* clear all flags other than these */
nfs_node_lock_force(np);
nfs_node_unlock(np);
if (!busyerror) {
- nfs_node_clear_busy2(nsp->nsr_dnp, np);
+ if (!vfs_isforce(nmp->nm_mountp)) {
+ nfs_node_clear_busy2(nsp->nsr_dnp, np);
+ } else {
+ nfs_node_clear_busy(np);
+ }
}
if (unhash && vnode_isinuse(vp, 0)) {
ubc_setsize(vp, np->n_size);
}
- lck_mtx_lock(nfs_node_hash_mutex);
+ lck_mtx_lock(&nfs_node_hash_mutex);
if (unhash) {
/*
* remove nfsnode from hash now so we can't accidentally find it
np->n_hflag &= ~NHLOCKWANT;
wakeup(np);
}
- lck_mtx_unlock(nfs_node_hash_mutex);
+ lck_mtx_unlock(&nfs_node_hash_mutex);
/* cleanup sillyrename info */
if (nsp->nsr_cred != NOCRED) {
kauth_cred_unref(&nsp->nsr_cred);
}
- vnode_rele(NFSTOV(nsp->nsr_dnp));
+ if (!vfs_isforce(nmp->nm_mountp)) {
+ /* in case of forceful unmount usecounts ignore anyways */
+ vnode_rele(NFSTOV(nsp->nsr_dnp));
+ }
FREE(nsp, M_TEMP);
FSDBG_BOT(264, vp, np, np->n_flag, 0);
out_free:
lck_mtx_unlock(&nmp->nm_lock);
}
- lck_mtx_lock(nfs_buf_mutex);
+ lck_mtx_lock(&nfs_buf_mutex);
if (!force && (!LIST_EMPTY(&np->n_dirtyblkhd) || !LIST_EMPTY(&np->n_cleanblkhd))) {
NP(np, "nfs_reclaim: dropping %s buffers", (!LIST_EMPTY(&np->n_dirtyblkhd) ? "dirty" : "clean"));
}
- lck_mtx_unlock(nfs_buf_mutex);
+ lck_mtx_unlock(&nfs_buf_mutex);
nfs_vinvalbuf(vp, V_IGNORE_WRITEERR, ap->a_context, 0);
- lck_mtx_lock(nfs_node_hash_mutex);
+ lck_mtx_lock(&nfs_node_hash_mutex);
if ((vnode_vtype(vp) != VDIR) && np->n_sillyrename) {
if (!force) {
np->n_hflag &= ~NHHASHED;
FSDBG(266, 0, np, np->n_flag, 0xb1eb1e);
}
- lck_mtx_unlock(nfs_node_hash_mutex);
+ lck_mtx_unlock(&nfs_node_hash_mutex);
/*
* Free up any directory cookie structures and large file handle
np->n_parent = NULL;
}
- lck_mtx_destroy(&np->n_lock, nfs_node_lck_grp);
- lck_rw_destroy(&np->n_datalock, nfs_data_lck_grp);
- lck_mtx_destroy(&np->n_openlock, nfs_open_grp);
+ lck_mtx_destroy(&np->n_lock, &nfs_node_lck_grp);
+ lck_rw_destroy(&np->n_datalock, &nfs_data_lck_grp);
+ lck_mtx_destroy(&np->n_openlock, &nfs_open_grp);
FSDBG_BOT(265, vp, np, np->n_flag, 0xd1ed1e);
NFS_ZFREE(nfsnode_zone, np);
u_long ncnt = 0;
microuptime(&now);
#endif
- lck_mtx_lock(nfs_node_hash_mutex);
+ lck_mtx_lock(&nfs_node_hash_mutex);
for (i = 0; i <= nfsnodehash; i++) {
LIST_FOREACH(np, &nfsnodehashtbl[i], n_hash) {
#ifdef DODEBUG
}
}
out:
- lck_mtx_unlock(nfs_node_hash_mutex);
+ lck_mtx_unlock(&nfs_node_hash_mutex);
#ifdef DODEBUG
microuptime(&then);
timersub(&then, &now, &diff);