diff --git a/sys/fs/fdescfs/fdesc.h b/sys/fs/fdescfs/fdesc.h --- a/sys/fs/fdescfs/fdesc.h +++ b/sys/fs/fdescfs/fdesc.h @@ -42,6 +42,7 @@ /* Private mount flags for fdescfs. */ #define FMNT_UNMOUNTF 0x01 #define FMNT_LINRDLNKF 0x02 +#define FMNT_NODUP 0x04 struct fdescmount { struct vnode *f_root; /* Root node */ diff --git a/sys/fs/fdescfs/fdesc_vfsops.c b/sys/fs/fdescfs/fdesc_vfsops.c --- a/sys/fs/fdescfs/fdesc_vfsops.c +++ b/sys/fs/fdescfs/fdesc_vfsops.c @@ -101,6 +101,8 @@ fmp->flags = 0; if (vfs_getopt(mp->mnt_optnew, "linrdlnk", NULL, NULL) == 0) fmp->flags |= FMNT_LINRDLNKF; + if (vfs_getopt(mp->mnt_optnew, "nodup", NULL, NULL) == 0) + fmp->flags |= FMNT_NODUP; error = fdesc_allocvp(Froot, -1, FD_ROOT, mp, &rvp); if (error) { free(fmp, M_FDESCMNT); diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c --- a/sys/fs/fdescfs/fdesc_vnops.c +++ b/sys/fs/fdescfs/fdesc_vnops.c @@ -267,10 +267,20 @@ struct vnode **rvp) { struct fdesc_get_ino_args *a; + struct fdescmount *fdm; + struct vnode *vp; int error; a = arg; - error = fdesc_allocvp(a->ftype, a->fd_fd, a->ix, mp, rvp); + fdm = VFSTOFDESC(mp); + if ((fdm->flags & FMNT_NODUP) != 0 && a->fp->f_type == DTYPE_VNODE) { + vp = a->fp->f_vnode; + vget(vp, lkflags | LK_RETRY); + *rvp = vp; + error = 0; + } else { + error = fdesc_allocvp(a->ftype, a->fd_fd, a->ix, mp, rvp); + } fdrop(a->fp, a->td); return (error); }