Page MenuHomeFreeBSD

D23162.id66872.diff
No OneTemporary

D23162.id66872.diff

Index: lib/libc/gen/opendir.c
===================================================================
--- lib/libc/gen/opendir.c
+++ lib/libc/gen/opendir.c
@@ -273,6 +273,24 @@
return (true);
}
+static int
+is_unionstack(int fd)
+{
+ struct statfs sfb;
+ int unionstack;
+
+ unionstack = _fcntl(fd, F_ISUNIONSTACK);
+ if (unionstack != -1)
+ return (unionstack);
+
+ /*
+ * Temporary compat for kernels which don't provide F_ISUNIONSTACK.
+ */
+ if (_fstatfs(fd, &sfb) < 0)
+ return (-1);
+ return (strcmp(sfb.f_fstypename, "unionfs") == 0 ||
+ (sfb.f_flags & MNT_UNION));
+}
/*
* Common routine for opendir(3), __opendir2(3) and fdopendir(3).
@@ -310,15 +328,11 @@
/*
* Determine whether this directory is the top of a union stack.
*/
+ unionstack = 0;
if (flags & DTF_NODUP) {
- struct statfs sfb;
-
- if (_fstatfs(fd, &sfb) < 0)
+ unionstack = is_unionstack(fd);
+ if (unionstack == -1)
goto fail;
- unionstack = !strcmp(sfb.f_fstypename, "unionfs")
- || (sfb.f_flags & MNT_UNION);
- } else {
- unionstack = 0;
}
if (unionstack) {
Index: lib/libc/sys/fcntl.2
===================================================================
--- lib/libc/sys/fcntl.2
+++ lib/libc/sys/fcntl.2
@@ -185,6 +185,9 @@
seals.
.It Dv F_GET_SEALS
Get seals associated with the file, if the underlying filesystem supports seals.
+.It Dv F_ISUNIONSTACK
+See if the vnode is part of a union stack (either the "union" lag from mount(2)
+or unionfs). This is a hack not intended to be used outside of libc.
.El
.Pp
The flags for the
Index: sys/fs/unionfs/union_vfsops.c
===================================================================
--- sys/fs/unionfs/union_vfsops.c
+++ sys/fs/unionfs/union_vfsops.c
@@ -296,7 +296,7 @@
if ((ump->um_lowervp->v_mount->mnt_flag & MNT_LOCAL) &&
(ump->um_uppervp->v_mount->mnt_flag & MNT_LOCAL))
mp->mnt_flag |= MNT_LOCAL;
- mp->mnt_kern_flag |= MNTK_NOMSYNC;
+ mp->mnt_kern_flag |= MNTK_NOMSYNC | MNTK_UNIONFS;
MNT_IUNLOCK(mp);
/*
Index: sys/kern/kern_descrip.c
===================================================================
--- sys/kern/kern_descrip.c
+++ sys/kern/kern_descrip.c
@@ -489,6 +489,7 @@
struct filedescent *fde;
struct proc *p;
struct vnode *vp;
+ struct mount *mp;
int error, flg, seals, tmp;
uint64_t bsize;
off_t foffset;
@@ -816,6 +817,49 @@
fdrop(fp, td);
break;
+ case F_ISUNIONSTACK:
+ /*
+ * See if the vnode is part of a union stack (either the "union"
+ * flag from mount(2) or unionfs).
+ *
+ * Prior to introduction of this op libc's readdir would call
+ * fstatfs(2), in effect unnecessarily copying kilobytes of
+ * data just to check fs name and a mount flag.
+ *
+ * Fixing the code to handle everything in the kernel instead
+ * is a non-trivial endeavor and has low priority, thus this
+ * horrible kludge facilitates the current behavior in a much
+ * cheaper manner until someone(tm) sorts this out.
+ */
+ error = fget_unlocked(fdp, fd, &cap_no_rights, &fp, NULL);
+ if (error != 0)
+ break;
+ if (fp->f_type != DTYPE_VNODE) {
+ fdrop(fp, td);
+ error = EBADF;
+ break;
+ }
+ vp = fp->f_vnode;
+ /*
+ * Since we don't prevent dooming the vnode even non-null mp
+ * found can become immediately stale. This is tolerable since
+ * mount points are type-stable (providing safe memory access)
+ * and any vfs op on this vnode going forward will return an
+ * error (meaning return value in this case is meaningless).
+ */
+ mp = (struct mount *)atomic_load_ptr(&vp->v_mount);
+ if (__predict_false(mp == NULL)) {
+ fdrop(fp, td);
+ error = EBADF;
+ break;
+ }
+ td->td_retval[0] = 0;
+ if (mp->mnt_kern_flag & MNTK_UNIONFS ||
+ mp->mnt_flag & MNT_UNION)
+ td->td_retval[0] = 1;
+ fdrop(fp, td);
+ break;
+
default:
error = EINVAL;
break;
Index: sys/sys/fcntl.h
===================================================================
--- sys/sys/fcntl.h
+++ sys/sys/fcntl.h
@@ -250,6 +250,7 @@
#define F_DUP2FD_CLOEXEC 18 /* Like F_DUP2FD, but FD_CLOEXEC is set */
#define F_ADD_SEALS 19
#define F_GET_SEALS 20
+#define F_ISUNIONSTACK 21 /* Kludge for libc, don't use it. */
/* Seals (F_ADD_SEALS, F_GET_SEALS). */
#define F_SEAL_SEAL 0x0001 /* Prevent adding sealings */
Index: sys/sys/mount.h
===================================================================
--- sys/sys/mount.h
+++ sys/sys/mount.h
@@ -414,6 +414,7 @@
#define MNTK_USES_BCACHE 0x00004000 /* FS uses the buffer cache. */
#define MNTK_TEXT_REFS 0x00008000 /* Keep use ref for text */
#define MNTK_VMSETSIZE_BUG 0x00010000
+#define MNTK_UNIONFS 0x00020000 /* A hack for F_ISUNIONSTACK */
#define MNTK_NOASYNC 0x00800000 /* disable async */
#define MNTK_UNMOUNT 0x01000000 /* unmount in progress */
#define MNTK_MWAIT 0x02000000 /* waiting for unmount to finish */

File Metadata

Mime Type
text/plain
Expires
Tue, Apr 21, 1:03 PM (3 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31910693
Default Alt Text
D23162.id66872.diff (4 KB)

Event Timeline