Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153331928
D23162.id66872.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D23162.id66872.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D23162: vfs: provide F_ISUNIONSTACK as a kludge for libc
Attached
Detach File
Event Timeline
Log In to Comment