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 <[email protected]>
---

 samples/watch_queue/watch_test.c |   44 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/samples/watch_queue/watch_test.c b/samples/watch_queue/watch_test.c
index 46e618a897fe..b526de016de4 100644
--- a/samples/watch_queue/watch_test.c
+++ b/samples/watch_queue/watch_test.c
@@ -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,32 @@ 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 %08x change=%u[%s] aux=%u ctr=%x,%x actr=%x\n",
+              m->triggered_on, n->subtype, mount_subtypes[n->subtype],
+              m->auxiliary_mount,
+              m->topology_changes,
+              m->attr_changes,
+              m->aux_topology_changes);
+
+}
+
 /*
  * Consume and display events.
  */
@@ -134,6 +163,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 +174,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 +218,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);
 }


Reply via email to