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:
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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: */
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 *,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user