linux: Add inotify support

Implement the Linux inotify system calls using the native implementation
in vfs_inotify.c.

PR:		240874
Reviewed by:	brooks
MFC after:	3 months
Sponsored by:	Klara, Inc.
Differential Revision:	https://reviews.freebsd.org/D50761
This commit is contained in:
Mark Johnston
2025-06-06 13:25:09 +00:00
parent 1d8664d690
commit 3965de642c
10 changed files with 201 additions and 18 deletions
+9 -2
View File
@@ -1476,10 +1476,17 @@
int linux_inotify_init(void);
}
254 AUE_NULL STD {
int linux_inotify_add_watch(void);
int linux_inotify_add_watch(
l_int fd,
const char *pathname,
uint32_t mask
);
}
255 AUE_NULL STD {
int linux_inotify_rm_watch(void);
int linux_inotify_rm_watch(
l_int fd,
uint32_t wd
);
}
256 AUE_NULL STD {
int linux_migrate_pages(void);
+12 -3
View File
@@ -1589,10 +1589,17 @@
int linux_inotify_init(void);
}
292 AUE_NULL STD {
int linux_inotify_add_watch(void);
int linux_inotify_add_watch(
l_int fd,
const char *pathname,
uint32_t mask
);
}
293 AUE_NULL STD {
int linux_inotify_rm_watch(void);
int linux_inotify_rm_watch(
l_int fd,
uint32_t wd
);
}
; Linux 2.6.16:
294 AUE_NULL STD {
@@ -1860,7 +1867,9 @@
);
}
332 AUE_NULL STD {
int linux_inotify_init1(void);
int linux_inotify_init1(
l_int flags
);
}
; Linux 2.6.30:
333 AUE_NULL STD {
+9 -2
View File
@@ -170,10 +170,17 @@
);
}
27 AUE_NULL STD {
int linux_inotify_add_watch(void);
int linux_inotify_add_watch(
l_int fd,
const char *pathname,
uint32_t mask
);
}
28 AUE_NULL STD {
int linux_inotify_rm_watch(void);
int linux_inotify_rm_watch(
l_int fd,
uint32_t wd
);
}
29 AUE_IOCTL STD {
int linux_ioctl(
-4
View File
@@ -74,9 +74,6 @@ DUMMY(kexec_load);
DUMMY(add_key);
DUMMY(request_key);
DUMMY(keyctl);
/* Linux 2.6.13: */
DUMMY(inotify_add_watch);
DUMMY(inotify_rm_watch);
/* Linux 2.6.16: */
DUMMY(migrate_pages);
DUMMY(unshare);
@@ -87,7 +84,6 @@ DUMMY(vmsplice);
DUMMY(move_pages);
/* Linux 2.6.27: */
DUMMY(signalfd4);
DUMMY(inotify_init1);
/* Linux 2.6.31: */
DUMMY(perf_event_open);
/* Linux 2.6.36: */
+121
View File
@@ -32,11 +32,13 @@
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/inotify.h>
#include <sys/lock.h>
#include <sys/mman.h>
#include <sys/selinfo.h>
#include <sys/pipe.h>
#include <sys/proc.h>
#include <sys/specialfd.h>
#include <sys/stat.h>
#include <sys/sx.h>
#include <sys/syscallsubr.h>
@@ -1877,3 +1879,122 @@ linux_writev(struct thread *td, struct linux_writev_args *args)
freeuio(auio);
return (linux_enobufs2eagain(td, args->fd, error));
}
static int
linux_inotify_init_flags(int l_flags)
{
int bsd_flags;
if ((l_flags & ~(LINUX_IN_CLOEXEC | LINUX_IN_NONBLOCK)) != 0)
linux_msg(NULL, "inotify_init1 unsupported flags 0x%x",
l_flags);
bsd_flags = 0;
if ((l_flags & LINUX_IN_CLOEXEC) != 0)
bsd_flags |= O_CLOEXEC;
if ((l_flags & LINUX_IN_NONBLOCK) != 0)
bsd_flags |= O_NONBLOCK;
return (bsd_flags);
}
static int
inotify_init_common(struct thread *td, int flags)
{
struct specialfd_inotify si;
si.flags = linux_inotify_init_flags(flags);
return (kern_specialfd(td, SPECIALFD_INOTIFY, &si));
}
#if defined(__i386__) || defined(__amd64__)
int
linux_inotify_init(struct thread *td, struct linux_inotify_init_args *args)
{
return (inotify_init_common(td, 0));
}
#endif
int
linux_inotify_init1(struct thread *td, struct linux_inotify_init1_args *args)
{
return (inotify_init_common(td, args->flags));
}
/*
* The native implementation uses the same values for inotify events as
* libinotify, which gives us binary compatibility with Linux. This simplifies
* the shim implementation a lot, as otherwise we would have to handle read(2)
* calls on inotify descriptors and translate events to Linux's ABI.
*/
_Static_assert(LINUX_IN_ACCESS == IN_ACCESS,
"IN_ACCESS mismatch");
_Static_assert(LINUX_IN_MODIFY == IN_MODIFY,
"IN_MODIFY mismatch");
_Static_assert(LINUX_IN_ATTRIB == IN_ATTRIB,
"IN_ATTRIB mismatch");
_Static_assert(LINUX_IN_CLOSE_WRITE == IN_CLOSE_WRITE,
"IN_CLOSE_WRITE mismatch");
_Static_assert(LINUX_IN_CLOSE_NOWRITE == IN_CLOSE_NOWRITE,
"IN_CLOSE_NOWRITE mismatch");
_Static_assert(LINUX_IN_OPEN == IN_OPEN,
"IN_OPEN mismatch");
_Static_assert(LINUX_IN_MOVED_FROM == IN_MOVED_FROM,
"IN_MOVED_FROM mismatch");
_Static_assert(LINUX_IN_MOVED_TO == IN_MOVED_TO,
"IN_MOVED_TO mismatch");
_Static_assert(LINUX_IN_CREATE == IN_CREATE,
"IN_CREATE mismatch");
_Static_assert(LINUX_IN_DELETE == IN_DELETE,
"IN_DELETE mismatch");
_Static_assert(LINUX_IN_DELETE_SELF == IN_DELETE_SELF,
"IN_DELETE_SELF mismatch");
_Static_assert(LINUX_IN_MOVE_SELF == IN_MOVE_SELF,
"IN_MOVE_SELF mismatch");
_Static_assert(LINUX_IN_UNMOUNT == IN_UNMOUNT,
"IN_UNMOUNT mismatch");
_Static_assert(LINUX_IN_Q_OVERFLOW == IN_Q_OVERFLOW,
"IN_Q_OVERFLOW mismatch");
_Static_assert(LINUX_IN_IGNORED == IN_IGNORED,
"IN_IGNORED mismatch");
_Static_assert(LINUX_IN_ISDIR == IN_ISDIR,
"IN_ISDIR mismatch");
_Static_assert(LINUX_IN_ONLYDIR == IN_ONLYDIR,
"IN_ONLYDIR mismatch");
_Static_assert(LINUX_IN_DONT_FOLLOW == IN_DONT_FOLLOW,
"IN_DONT_FOLLOW mismatch");
_Static_assert(LINUX_IN_MASK_CREATE == IN_MASK_CREATE,
"IN_MASK_CREATE mismatch");
_Static_assert(LINUX_IN_MASK_ADD == IN_MASK_ADD,
"IN_MASK_ADD mismatch");
_Static_assert(LINUX_IN_ONESHOT == IN_ONESHOT,
"IN_ONESHOT mismatch");
_Static_assert(LINUX_IN_EXCL_UNLINK == IN_EXCL_UNLINK,
"IN_EXCL_UNLINK mismatch");
static int
linux_inotify_watch_flags(int l_flags)
{
if ((l_flags & ~(LINUX_IN_ALL_EVENTS | LINUX_IN_ALL_FLAGS)) != 0) {
linux_msg(NULL, "inotify_add_watch unsupported flags 0x%x",
l_flags);
}
return (l_flags);
}
int
linux_inotify_add_watch(struct thread *td,
struct linux_inotify_add_watch_args *args)
{
return (kern_inotify_add_watch(args->fd, AT_FDCWD, args->pathname,
linux_inotify_watch_flags(args->mask), td));
}
int
linux_inotify_rm_watch(struct thread *td,
struct linux_inotify_rm_watch_args *args)
{
return (kern_inotify_rm_watch(args->fd, args->wd, td));
}
+32
View File
@@ -189,6 +189,38 @@
#define LINUX_HUGETLB_FLAG_ENCODE_2GB (31 << LINUX_HUGETLB_FLAG_ENCODE_SHIFT)
#define LINUX_HUGETLB_FLAG_ENCODE_16GB (34U << LINUX_HUGETLB_FLAG_ENCODE_SHIFT)
/* inotify flags */
#define LINUX_IN_ACCESS 0x00000001
#define LINUX_IN_MODIFY 0x00000002
#define LINUX_IN_ATTRIB 0x00000004
#define LINUX_IN_CLOSE_WRITE 0x00000008
#define LINUX_IN_CLOSE_NOWRITE 0x00000010
#define LINUX_IN_OPEN 0x00000020
#define LINUX_IN_MOVED_FROM 0x00000040
#define LINUX_IN_MOVED_TO 0x00000080
#define LINUX_IN_CREATE 0x00000100
#define LINUX_IN_DELETE 0x00000200
#define LINUX_IN_DELETE_SELF 0x00000400
#define LINUX_IN_MOVE_SELF 0x00000800
#define LINUX_IN_UNMOUNT 0x00002000
#define LINUX_IN_Q_OVERFLOW 0x00004000
#define LINUX_IN_IGNORED 0x00008000
#define LINUX_IN_ONLYDIR 0x01000000
#define LINUX_IN_DONT_FOLLOW 0x02000000
#define LINUX_IN_EXCL_UNLINK 0x04000000
#define LINUX_IN_MASK_CREATE 0x10000000
#define LINUX_IN_MASK_ADD 0x20000000
#define LINUX_IN_ISDIR 0x40000000
#define LINUX_IN_ONESHOT 0x80000000
#define LINUX_IN_ALL_EVENTS 0x00000fff
#define LINUX_IN_ALL_FLAGS 0xf700e000
#define LINUX_IN_NONBLOCK 0x00000800
#define LINUX_IN_CLOEXEC 0x00080000
#if defined(_KERNEL)
struct l_file_handle {
l_uint handle_bytes;
+12 -3
View File
@@ -1605,10 +1605,17 @@
int linux_inotify_init(void);
}
292 AUE_NULL STD {
int linux_inotify_add_watch(void);
int linux_inotify_add_watch(
l_int fd,
const char *pathname,
uint32_t mask
);
}
293 AUE_NULL STD {
int linux_inotify_rm_watch(void);
int linux_inotify_rm_watch(
l_int fd,
uint32_t wd
);
}
; Linux 2.6.16:
294 AUE_NULL STD {
@@ -1872,7 +1879,9 @@
);
}
332 AUE_NULL STD {
int linux_inotify_init1(void);
int linux_inotify_init1(
l_int flags
);
}
; Linux 2.6.30:
333 AUE_NULL STD {
+2 -2
View File
@@ -872,7 +872,7 @@ fget_inotify(struct thread *td, int fd, const cap_rights_t *needrightsp,
return (0);
}
static int
int
kern_inotify_add_watch(int fd, int dfd, const char *path, uint32_t mask,
struct thread *td)
{
@@ -958,7 +958,7 @@ sys_inotify_add_watch_at(struct thread *td,
uap->mask, td));
}
static int
int
kern_inotify_rm_watch(int fd, uint32_t wd, struct thread *td)
{
struct file *fp;
+4
View File
@@ -89,6 +89,10 @@ struct vnode;
int inotify_create_file(struct thread *, struct file *, int, int *);
void inotify_log(struct vnode *, const char *, size_t, int, __uint32_t);
int kern_inotify_rm_watch(int, uint32_t, struct thread *);
int kern_inotify_add_watch(int, int, const char *, uint32_t,
struct thread *);
void vn_inotify(struct vnode *, struct vnode *, struct componentname *, int,
uint32_t);
int vn_inotify_add_watch(struct vnode *, struct inotify_softc *,
-2
View File
@@ -46,7 +46,5 @@ LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
DUMMY(sysfs);
DUMMY(quotactl);
/* Linux 2.6.13: */
DUMMY(inotify_init);
/* Linux 2.6.22: */
DUMMY(signalfd);