]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: Simplify inotify_handler()
authorVolker Lendecke <vl@samba.org>
Fri, 23 May 2025 13:22:39 +0000 (15:22 +0200)
committerRalph Boehme <slow@samba.org>
Mon, 2 Jun 2025 17:08:34 +0000 (17:08 +0000)
[sizeof(struct inotify_event) + NAME_MAX + 1] is the recommended
buffer size in "man 7 inotify". Pulling everything out of the inotify
buffer makes sense if we would reliably get the two rename events in
the same read-call. Unfortunately this is not the case, even with a
buffer size of 64k I've seen MOVED_FROM and MOVED_to in separate reads
from the socket. We'll have to take care of this situation next. Until
then, we don't have to FIONREAD and then read everything that's
there. Rather go through another event loop, replacing the ioctl with
a epoll_wait syscall.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=15864
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
source3/smbd/notify_inotify.c

index 5c57ffd46fb523560a707e832dc57b50812e6cc2..5873de75c6c1108be44265e03099d56b78ddb325 100644 (file)
@@ -24,7 +24,7 @@
 #include "includes.h"
 #include "../librpc/gen_ndr/notify.h"
 #include "smbd/smbd.h"
-#include "lib/util/sys_rw_data.h"
+#include "lib/util/sys_rw.h"
 
 #include <sys/inotify.h>
 
@@ -258,38 +258,25 @@ static void inotify_handler(struct tevent_context *ev, struct tevent_fd *fde,
 {
        struct inotify_private *in = talloc_get_type(private_data,
                                                     struct inotify_private);
+       char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
        int bufsize = 0;
-       struct inotify_event *e0, *e;
+       struct inotify_event *e = NULL;
        uint32_t prev_cookie=0;
        int prev_wd = -1;
        ssize_t ret;
 
-       /*
-         we must use FIONREAD as we cannot predict the length of the
-         filenames, and thus can't know how much to allocate
-         otherwise
-       */
-       if (ioctl(in->fd, FIONREAD, &bufsize) != 0 ||
-           bufsize == 0) {
-               DEBUG(0,("No data on inotify fd?!\n"));
-               TALLOC_FREE(fde);
-               return;
-       }
-
-       e0 = e = (struct inotify_event *)TALLOC_SIZE(in, bufsize + 1);
-       if (e == NULL) return;
-       ((uint8_t *)e)[bufsize] = '\0';
-
-       ret = read_data(in->fd, e0, bufsize);
-       if (ret != bufsize) {
+       ret = sys_read(in->fd, buf, sizeof(buf));
+       if (ret == -1) {
                DEBUG(0, ("Failed to read all inotify data - %s\n",
                          strerror(errno)));
-               talloc_free(e0);
                /* the inotify fd will now be out of sync,
                 * can't keep reading data off it */
                TALLOC_FREE(fde);
                return;
        }
+       bufsize = ret;
+
+       e = (struct inotify_event *)buf;
 
        /* we can get more than one event in the buffer */
        while (e && (bufsize >= sizeof(*e))) {
@@ -303,8 +290,6 @@ static void inotify_handler(struct tevent_context *ev, struct tevent_fd *fde,
                prev_cookie = e->cookie;
                e = e2;
        }
-
-       talloc_free(e0);
 }
 
 /*