}
/*
- * This function builds the path to a filename in "buff". The
- * length of the buffer *INCLUDING* the trailing zero byte is
- * returned in outlen. NOTE: the length includes the trailing
- * zero byte and thus the length is one greater than what strlen
- * would return. This is important and lots of code elsewhere
- * in the kernel assumes this behavior.
+ * This function builds the path in "buff" from the supplied vnode.
+ * The length of the buffer *INCLUDING* the trailing zero byte is
+ * returned in outlen. NOTE: the length includes the trailing zero
+ * byte and thus the length is one greater than what strlen would
+ * return. This is important and lots of code elsewhere in the kernel
+ * assumes this behavior.
*
* This function can call vnop in file system if the parent vnode
* does not exist or when called for hardlinks via volfs path.
* cross over mount points during building the path.
*
* passed in vp must have a valid io_count reference
+ *
+ * If parent vnode is non-NULL it also must have an io count. This
+ * allows build_path_with_parent to be safely called for operations
+ * unlink, rmdir and rename that already have io counts on the target
+ * and the directory. In this way build_path_with_parent does not have
+ * to try and obtain an additional io count on the parent. Taking an
+ * io count ont the parent can lead to dead lock if a forced unmount
+ * occures at the right moment. For a fuller explaination on how this
+ * can occur see the comment for vn_getpath_with_parent.
+ *
*/
int
-build_path(vnode_t first_vp, char *buff, int buflen, int *outlen, int flags, vfs_context_t ctx)
+build_path_with_parent(vnode_t first_vp, vnode_t parent_vp, char *buff, int buflen, int *outlen, int flags, vfs_context_t ctx)
{
vnode_t vp, tvp;
vnode_t vp_with_iocount;
NAME_CACHE_UNLOCK();
- if (vp != first_vp && vp != vp_with_iocount) {
+ if (vp != first_vp && vp != parent_vp && vp != vp_with_iocount) {
if (vp_with_iocount) {
vnode_put(vp_with_iocount);
vp_with_iocount = NULLVP;
NAME_CACHE_UNLOCK();
- if (vp != first_vp && vp != vp_with_iocount) {
+ if (vp != first_vp && vp != parent_vp && vp != vp_with_iocount) {
if (vp_with_iocount) {
vnode_put(vp_with_iocount);
vp_with_iocount = NULLVP;
return (ret);
}
+int
+build_path(vnode_t first_vp, char *buff, int buflen, int *outlen, int flags, vfs_context_t ctx)
+{
+ return (build_path_with_parent(first_vp, NULL, buff, buflen, outlen, flags, ctx));
+}
/*
* return NULLVP if vp's parent doesn't
#if CONFIG_MACF
- /*
+ /*
* Name cache provides authorization caching (see below)
* that will short circuit MAC checks in lookup().
* We must perform MAC check here. On denial
ncpp = NCHHASH(dvp, cnp->cn_hash);
LIST_FOREACH(ncp, ncpp, nc_hash) {
if ((ncp->nc_dvp == dvp) && (ncp->nc_hashval == hashval)) {
- if (memcmp(ncp->nc_name, cnp->cn_nameptr, namelen) == 0 && ncp->nc_name[namelen] == 0)
+ if (strncmp(ncp->nc_name, cnp->cn_nameptr, namelen) == 0 && ncp->nc_name[namelen] == 0)
break;
}
}
ncpp = NCHHASH(dvp, cnp->cn_hash);
LIST_FOREACH(ncp, ncpp, nc_hash) {
if ((ncp->nc_dvp == dvp) && (ncp->nc_hashval == hashval)) {
- if (memcmp(ncp->nc_name, cnp->cn_nameptr, namelen) == 0 && ncp->nc_name[namelen] == 0)
+ if (strncmp(ncp->nc_name, cnp->cn_nameptr, namelen) == 0 && ncp->nc_name[namelen] == 0)
break;
}
}
}
static void
-cache_delete(struct namecache *ncp, int age_entry)
+cache_delete(struct namecache *ncp, int free_entry)
{
NCHSTAT(ncs_deletes);
*/
ncp->nc_hash.le_prev = NULL;
- if (age_entry) {
- /*
- * make it the next one available
- * for cache_enter's use
- */
- TAILQ_REMOVE(&nchead, ncp, nc_entry);
- TAILQ_INSERT_HEAD(&nchead, ncp, nc_entry);
- }
vfs_removename(ncp->nc_name);
ncp->nc_name = NULL;
+ if (free_entry) {
+ TAILQ_REMOVE(&nchead, ncp, nc_entry);
+ FREE_ZONE(ncp, sizeof(*ncp), M_CACHE);
+ numcache--;
+ }
}
lck_mtx_lock_spin(&strcache_mtx_locks[lock_index]);
for (entry = head->lh_first; entry != NULL; chain_len++, entry = entry->hash_chain.le_next) {
- if (memcmp(entry->str, name, len) == 0 && entry->str[len] == 0) {
+ if (strncmp(entry->str, name, len) == 0 && entry->str[len] == 0) {
entry->refcount++;
break;
}