/*
- * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
+ *
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
- *
+ *
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
+ *
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
- *
+ *
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
static lck_grp_t *nfs_data_lck_grp;
lck_mtx_t *nfs_node_hash_mutex;
+#define NFS_NODE_DBG(...) NFS_DBG(NFS_FAC_NODE, 7, ## __VA_ARGS__)
+
/*
* Initialize hash links for nfsnodes
* and build nfsnode free list.
int answer = 0;
int skip = 0;
- if (nmp == NULL) {
+ if (nfs_mount_gone(nmp)) {
return (0);
}
skip = 1;
}
- if (!skip && NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_CASE_INSENSITIVE))
+ if (!skip && (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_CASE_INSENSITIVE))
answer = 1;
lck_mtx_unlock(&nmp->nm_lock);
FSDBG_TOP(263, mp, dnp, flags, npp);
/* Check for unmount in progress */
- if (!mp || (mp->mnt_kern_flag & MNTK_FRCUNMOUNT)) {
+ if (!mp || vfs_isforce(mp)) {
*npp = NULL;
error = ENXIO;
FSDBG_BOT(263, mp, dnp, 0xd1e, error);
* Update the vnode if the name/and or the parent has
* changed. We need to do this so that if getattrlist is
* called asking for ATTR_CMN_NAME, that the "most"
- * correct name is being returned if we're not making an
- * entry. In addition for monitored vnodes we need to
- * kick the vnode out of the name cache. We do this so
- * that if there are hard links in the same directory
- * the link will not be found and a lookup will get us
- * here to return the name of the current link. In
- * addition by removing the name from the name cache the
- * old name will not be found after a rename done on
- * another client or the server. The principle reason
- * to do this is because Finder is asking for
- * notifications on a directory. The directory changes,
- * Finder gets notified, reads the directory (which we
- * have purged) and for each entry returned calls
- * getattrlist with the name returned from
- * readdir. gettattrlist has to call namei/lookup to
- * resolve the name, because its not in the cache we end
- * up here. We need to update the name so Finder will
- * get the name it called us with.
+ * correct name is being returned. In addition for
+ * monitored vnodes we need to kick the vnode out of the
+ * name cache. We do this so that if there are hard
+ * links in the same directory the link will not be
+ * found and a lookup will get us here to return the
+ * name of the current link. In addition by removing the
+ * name from the name cache the old name will not be
+ * found after a rename done on another client or the
+ * server. The principle reason to do this is because
+ * Finder is asking for notifications on a directory.
+ * The directory changes, Finder gets notified, reads
+ * the directory (which we have purged) and for each
+ * entry returned calls getattrlist with the name
+ * returned from readdir. gettattrlist has to call
+ * namei/lookup to resolve the name, because its not in
+ * the cache we end up here. We need to update the name
+ * so Finder will get the name it called us with.
*
* We had an imperfect solution with respect to case
* sensitivity. There is a test that is run in
* ATTR_CMN_NAME</rant>
*/
if (dnp && cnp && (vp != NFSTOV(dnp))) {
- int update_flags = vnode_ismonitored((NFSTOV(dnp))) ? VNODE_UPDATE_CACHE : 0;
+ int update_flags = (vnode_ismonitored((NFSTOV(dnp)))) ? VNODE_UPDATE_CACHE : 0;
int (*cmp)(const char *s1, const char *s2, size_t n);
cmp = nfs_case_insensitive(mp) ? strncasecmp : strncmp;
update_flags |= VNODE_UPDATE_NAME;
if (vnode_parent(vp) != NFSTOV(dnp))
update_flags |= VNODE_UPDATE_PARENT;
- if (update_flags)
+ if (update_flags) {
+ NFS_NODE_DBG("vnode_update_identity old name %s new name %.*s update flags = %x\n",
+ vp->v_name, cnp->cn_namelen, cnp->cn_nameptr ? cnp->cn_nameptr : "", update_flags);
vnode_update_identity(vp, NFSTOV(dnp), cnp->cn_nameptr, cnp->cn_namelen, 0, update_flags);
+ }
}
*npp = np;
int
-nfs_vnop_inactive(ap)
+nfs_vnop_inactive(
struct vnop_inactive_args /* {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
- } */ *ap;
+ } */ *ap)
{
vnode_t vp = ap->a_vp;
vfs_context_t ctx = ap->a_context;
- nfsnode_t np = VTONFS(ap->a_vp);
+ nfsnode_t np;
struct nfs_sillyrename *nsp;
struct nfs_vattr nvattr;
int unhash, attrerr, busyerror, error, inuse, busied, force;
struct nfs_open_file *nofp;
struct componentname cn;
- struct nfsmount *nmp = NFSTONMP(np);
- mount_t mp = vnode_mount(vp);
+ struct nfsmount *nmp;
+ mount_t mp;
+
+ if (vp == NULL)
+ panic("nfs_vnop_inactive: vp == NULL");
+ np = VTONFS(vp);
+ if (np == NULL)
+ panic("nfs_vnop_inactive: np == NULL");
+
+ nmp = NFSTONMP(np);
+ mp = vnode_mount(vp);
restart:
- force = (!mp || (mp->mnt_kern_flag & MNTK_FRCUNMOUNT));
+ force = (!mp || vfs_isforce(mp));
error = 0;
inuse = (nfs_mount_state_in_use_start(nmp, NULL) == 0);
/* There shouldn't be any open or lock state at this point */
lck_mtx_lock(&np->n_openlock);
- if (np->n_openrefcnt && !force)
+ if (np->n_openrefcnt && !force) {
+ /*
+ * vnode_rele and vnode_put drop the vnode lock before
+ * calling VNOP_INACTIVE, so there is a race were the
+ * vnode could become active again. Perhaps there are
+ * other places where this can happen, so if we've got
+ * here we need to get out.
+ */
+#ifdef NFS_NODE_DEBUG
NP(np, "nfs_vnop_inactive: still open: %d", np->n_openrefcnt);
+#endif
+ lck_mtx_unlock(&np->n_openlock);
+ return 0;
+ }
+
TAILQ_FOREACH(nofp, &np->n_opens, nof_link) {
lck_mtx_lock(&nofp->nof_lock);
if (nofp->nof_flags & NFS_OPEN_FILE_BUSY) {
* Reclaim an nfsnode so that it can be used for other purposes.
*/
int
-nfs_vnop_reclaim(ap)
+nfs_vnop_reclaim(
struct vnop_reclaim_args /* {
struct vnodeop_desc *a_desc;
vnode_t a_vp;
vfs_context_t a_context;
- } */ *ap;
+ } */ *ap)
{
vnode_t vp = ap->a_vp;
nfsnode_t np = VTONFS(vp);
int force;
FSDBG_TOP(265, vp, np, np->n_flag, 0);
- force = (!mp || (mp->mnt_kern_flag & MNTK_FRCUNMOUNT));
+ force = (!mp || vfs_isforce(mp) || nfs_mount_gone(nmp));
/* There shouldn't be any open or lock state at this point */
lck_mtx_lock(&np->n_openlock);
}
#define DODEBUG 1
+
int
nfs_mount_is_dirty(mount_t mp)
{
microuptime(&then);
timersub(&then, &now, &diff);
- printf("nfs_mount_is_dirty took %lld mics for %ld slots and %ld nodes return %d\n",
- (uint64_t)diff.tv_sec * 1000000LL + diff.tv_usec, i, ncnt, (i <= nfsnodehash));
+ NFS_DBG(NFS_FAC_SOCK, 7, "mount_is_dirty for %s took %lld mics for %ld slots and %ld nodes return %d\n",
+ vfs_statfs(mp)->f_mntfromname, (uint64_t)diff.tv_sec * 1000000LL + diff.tv_usec, i, ncnt, (i <= nfsnodehash));
#endif
return (i <= nfsnodehash);