while (*scan != '/' && *scan)
scan++;
- strlcpy(component, start, scan - start);
+ strlcpy(component, start, (scan - start) + 1);
if (*scan == '/')
scan++;
dev_dup_entry(devnode_t * parent, devdirent_t * back, devdirent_t * *dnm_pp,
struct devfsmount *dvm)
{
- devdirent_t * entry_p;
+ devdirent_t * entry_p = NULL;
devdirent_t * newback;
devdirent_t * newfront;
int error;
* go get the node made (if we need to)
* use the back one as a prototype
*/
- if ((error = dev_add_entry(back->de_name, parent, type,
- NULL, dnp,
- parent?parent->dn_dvm:dvm, &entry_p)) != 0) {
+ error = dev_add_entry(back->de_name, parent, type, NULL, dnp,
+ parent?parent->dn_dvm:dvm, &entry_p);
+ if (!error && (entry_p == NULL)) {
+ error = ENOMEM; /* Really can't happen, but make static analyzer happy */
+ }
+ if (error != 0) {
printf("duplicating %s failed\n",back->de_name);
+ goto out;
}
/*
}
}
}
+out:
*dnm_pp = entry_p;
return error;
}
DEVFS_UNLOCK();
- error = vnode_getwithvid(vn_p, vid);
+ /*
+ * We want to use the drainok variant of vnode_getwithvid
+ * because we _don't_ want to get an iocount if the vnode is
+ * is blocked in vnode_drain as it can cause infinite
+ * loops in vn_open_auth. While in use vnodes are typically
+ * only reclaimed on forced unmounts, In use devfs tty vnodes
+ * can be quite frequently reclaimed by revoke(2) or by the
+ * exit of a controlling process.
+ */
+ error = vnode_getwithvid_drainok(vn_p, vid);
DEVFS_LOCK();
* vnode. Therefore, ENOENT is a valid result.
*/
error = ENOENT;
+ } else if (error == ENODEV) {
+ /*
+ * The Filesystem is getting unmounted.
+ */
+ error = ENOENT;
} else if (error && (nretries < DEV_MAX_VNODE_RETRY)) {
/*
* If we got an error from vnode_getwithvid, it means
* we raced with a recycle and lost i.e. we asked for
- * an iocount only after vnode_drain had completed on
- * the vnode and returned with an error only after
- * devfs_reclaim was called on the vnode. While
- * devfs_reclaim sets dn_vn to NULL but while we were
- * waiting to reacquire DEVFS_LOCK, another vnode might
- * have gotten associated with the dnp. In either case,
- * we need to retry otherwise we will end up returning
- * an ENOENT for this lookup but the next lookup will
- * succeed because it creates a new vnode (or a racing
- * lookup created a new vnode already).
- *
- * We cap the number of retries at 8.
+ * an iocount only after vnode_drain had been entered
+ * for the vnode and returned with an error only after
+ * devfs_reclaim was called on the vnode. devfs_reclaim
+ * sets dn_vn to NULL but while we were waiting to
+ * reacquire DEVFS_LOCK, another vnode might have gotten
+ * associated with the dnp. In either case, we need to
+ * retry otherwise we will end up returning an ENOENT
+ * for this lookup but the next lookup will succeed
+ * because it creates a new vnode (or a racing lookup
+ * created a new vnode already).
*/
error = 0;
nretries++;