]> www.infradead.org Git - users/hch/block.git/commitdiff
watch_queue: sample: Display mount tree change notifications
authorDavid Howells <dhowells@redhat.com>
Fri, 7 Jun 2019 14:13:21 +0000 (15:13 +0100)
committerDavid Howells <dhowells@redhat.com>
Mon, 3 Aug 2020 11:15:38 +0000 (12:15 +0100)
This is run like:

./watch_test

and watches "/" for changes to the mount topology and the attributes of
individual mount objects.

# mount -t tmpfs none /mnt
# mount -o remount,ro /mnt
# mount -o remount,rw /mnt

producing:

# ./watch_test
read() = 16
NOTIFY[000]: ty=000002 sy=00 i=02000010
MOUNT 00000060 change=0[new_mount] aux=416
read() = 16
NOTIFY[000]: ty=000002 sy=04 i=02010010
MOUNT 000001a0 change=4[setattr] aux=0
read() = 16
NOTIFY[000]: ty=000002 sy=04 i=02010010
MOUNT 000001a0 change=4[setattr] aux=0

Signed-off-by: David Howells <dhowells@redhat.com>
samples/watch_queue/watch_test.c

index 46e618a897fef943c52749f46d8038459ca3f53a..d82554436152349234b4832d697ccc8084d877e9 100644 (file)
@@ -26,6 +26,9 @@
 #ifndef __NR_keyctl
 #define __NR_keyctl -1
 #endif
+#ifndef __NR_watch_mount
+#define __NR_watch_mount -1
+#endif
 
 #define BUF_SIZE 256
 
@@ -58,6 +61,29 @@ static void saw_key_change(struct watch_notification *n, size_t len)
               k->key_id, n->subtype, key_subtypes[n->subtype], k->aux);
 }
 
+static const char *mount_subtypes[256] = {
+       [NOTIFY_MOUNT_NEW_MOUNT]        = "new_mount",
+       [NOTIFY_MOUNT_UNMOUNT]          = "unmount",
+       [NOTIFY_MOUNT_EXPIRY]           = "expiry",
+       [NOTIFY_MOUNT_READONLY]         = "readonly",
+       [NOTIFY_MOUNT_SETATTR]          = "setattr",
+       [NOTIFY_MOUNT_MOVE_FROM]        = "move_from",
+       [NOTIFY_MOUNT_MOVE_TO]          = "move_to",
+};
+
+static void saw_mount_change(struct watch_notification *n, size_t len)
+{
+       struct mount_notification *m = (struct mount_notification *)n;
+
+       if (len != sizeof(struct mount_notification))
+               return;
+
+       printf("MOUNT %08llx change=%u[%s] aux=%llx\n",
+              (unsigned long long)m->triggered_on,
+              n->subtype, mount_subtypes[n->subtype],
+              (unsigned long long)m->auxiliary_mount);
+}
+
 /*
  * Consume and display events.
  */
@@ -134,6 +160,9 @@ static void consumer(int fd)
                        default:
                                printf("other type\n");
                                break;
+                       case WATCH_TYPE_MOUNT_NOTIFY:
+                               saw_mount_change(&n.n, len);
+                               break;
                        }
 
                        p += len;
@@ -142,12 +171,17 @@ static void consumer(int fd)
 }
 
 static struct watch_notification_filter filter = {
-       .nr_filters     = 1,
+       .nr_filters     = 2,
        .filters = {
                [0]     = {
                        .type                   = WATCH_TYPE_KEY_NOTIFY,
                        .subtype_filter[0]      = UINT_MAX,
                },
+               [1] = {
+                       .type                   = WATCH_TYPE_MOUNT_NOTIFY,
+                       // Reject move-from notifications
+                       .subtype_filter[0]      = UINT_MAX & ~(1 << NOTIFY_MOUNT_MOVE_FROM),
+               },
        },
 };
 
@@ -181,6 +215,11 @@ int main(int argc, char **argv)
                exit(1);
        }
 
+       if (syscall(__NR_watch_mount, AT_FDCWD, "/", 0, fd, 0xde) == -1) {
+               perror("watch_mount");
+               exit(1);
+       }
+
        consumer(fd);
        exit(0);
 }