From b3f6e55fd37e330bfa59461a8414a4f7990c45c4 Mon Sep 17 00:00:00 2001 From: Michal Lenc Date: Mon, 7 Oct 2024 10:49:01 +0200 Subject: [PATCH 1/3] fs_truncate: provide inotify call for truncate IN_MODIFY event should occur on file modification, which includes truncate. This is consistent with the inotify usage on Linux. Signed-off-by: Michal Lenc --- fs/vfs/fs_truncate.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/vfs/fs_truncate.c b/fs/vfs/fs_truncate.c index 827070774c9dd..d6dc7dfb6a48c 100644 --- a/fs/vfs/fs_truncate.c +++ b/fs/vfs/fs_truncate.c @@ -32,6 +32,7 @@ #include +#include "notify/notify.h" #include "inode/inode.h" /**************************************************************************** @@ -180,6 +181,9 @@ int ftruncate(int fd, off_t length) fs_putfilep(filep); if (ret >= 0) { +#ifdef CONFIG_FS_NOTIFY + notify_write(filep); +#endif return 0; } From 963fe89c8465eb2fcf5a680458bb5d9c3a3eda39 Mon Sep 17 00:00:00 2001 From: Michal Lenc Date: Mon, 7 Oct 2024 10:55:43 +0200 Subject: [PATCH 2/3] fs_close: provide inotify call for close Close operation on file should lead to IN_CLOSE_WRITE or IN_CLOSE_NOWRITE notifications. This commits adds the notification support. Notifying on close is a little bit trickier as a lower layer may not have the full file path after successful close and inode release. Calling notification before close is not a solution since close might not end successfully. The solution is to obtain and buffer the path before calling close and then pass the buffered path to the notify_close. This required the change in notify_close function arguments: filep is no longer required, path and oflags are passed instead. Signed-off-by: Michal Lenc --- fs/notify/inotify.c | 8 ++++---- fs/notify/notify.h | 2 +- fs/vfs/fs_close.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/fs/notify/inotify.c b/fs/notify/inotify.c index f7e34bd34ec45..5b47bc54e8493 100644 --- a/fs/notify/inotify.c +++ b/fs/notify/inotify.c @@ -1342,15 +1342,15 @@ void notify_open(FAR const char *path, int oflags) * ****************************************************************************/ -void notify_close(FAR struct file *filep) +void notify_close(FAR const char *path, int oflags) { - if (filep->f_oflags & O_WROK) + if (oflags & O_WROK) { - notify_queue_filep_event(filep, IN_CLOSE_WRITE); + notify_queue_path_event(path, IN_CLOSE_WRITE); } else { - notify_queue_filep_event(filep, IN_CLOSE_NOWRITE); + notify_queue_path_event(path, IN_CLOSE_NOWRITE); } } diff --git a/fs/notify/notify.h b/fs/notify/notify.h index 4a0fc11b0281e..dad750513fa7d 100644 --- a/fs/notify/notify.h +++ b/fs/notify/notify.h @@ -42,7 +42,7 @@ /* These are internal OS interface and are not available to applications */ void notify_open(FAR const char *path, int oflags); -void notify_close(FAR struct file *filep); +void notify_close(FAR const char *path, int oflags); void notify_close2(FAR struct inode *inode); void notify_read(FAR struct file *filep); void notify_write(FAR struct file *filep); diff --git a/fs/vfs/fs_close.c b/fs/vfs/fs_close.c index 52924030df279..514a8bf71a6e0 100644 --- a/fs/vfs/fs_close.c +++ b/fs/vfs/fs_close.c @@ -36,6 +36,33 @@ #include "inode/inode.h" #include "vfs/lock.h" +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_FS_NOTIFY +static FAR char *file_get_path(FAR struct file *filep) +{ + FAR char *pathbuffer; + int ret; + + pathbuffer = lib_get_pathbuffer(); + if (pathbuffer == NULL) + { + return NULL; + } + + ret = file_fcntl(filep, F_GETPATH, pathbuffer); + if (ret < 0) + { + lib_put_pathbuffer(pathbuffer); + return NULL; + } + + return pathbuffer; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -60,11 +87,22 @@ int file_close_without_clear(FAR struct file *filep) { struct inode *inode; +#ifdef CONFIG_FS_NOTIFY + FAR char *path; +#endif int ret = OK; DEBUGASSERT(filep != NULL); inode = filep->f_inode; +#ifdef CONFIG_FS_NOTIFY + /* We lose the path and inode during close and release, so obtain it + * in advance. Then we pass it to notify_close function. + */ + + path = file_get_path(filep); +#endif + /* Check if the struct file is open (i.e., assigned an inode) */ if (inode) @@ -84,6 +122,14 @@ int file_close_without_clear(FAR struct file *filep) if (ret >= 0) { +#ifdef CONFIG_FS_NOTIFY + if (path != NULL) + { + notify_close(path, filep->f_oflags); + lib_put_pathbuffer(path); + } +#endif + inode_release(inode); } } From 8ba363c9d4666ff726dd7a9d2e9a1ba464b47253 Mon Sep 17 00:00:00 2001 From: Michal Lenc Date: Mon, 7 Oct 2024 11:38:31 +0200 Subject: [PATCH 3/3] documentation/inotify: add newly supported events IN_CLOSE_WRITE and IN_CLOSE_NOWRITE are now supported and IN_MODIFY can be used for truncate as well. Signed-off-by: Michal Lenc --- Documentation/components/filesystem/inotify.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/components/filesystem/inotify.rst b/Documentation/components/filesystem/inotify.rst index 2fb37863b3f27..cab61b4a8814a 100644 --- a/Documentation/components/filesystem/inotify.rst +++ b/Documentation/components/filesystem/inotify.rst @@ -90,12 +90,16 @@ calling inotify_add_watch and may be returned in the mask field returned by re **IN_ACCESS** :File was accessed - **IN_MODIFY** :File was modified + **IN_MODIFY** :File was modified (``write()`` or ``truncate()``) **IN_ATTRIB** :Metadata changed **IN_OPEN** :File was opened + **IN_CLOSE_WRITE** :File opened for writing was closed + + **IN_CLOSE_NOWRITE** : File not opened for writing was closed + **IN_MOVED_FROM** :File was moved from X **IN_MOVED_TO** :File was moved to Y