Reject new watches on deleted inodes
This commit is contained in:
parent
d23d25c552
commit
43b8838d6a
|
|
@ -165,12 +165,20 @@ impl InotifyFile {
|
|||
let subscriber = inotify_subscriber.clone() as Arc<dyn FsEventSubscriber>;
|
||||
|
||||
let inode = path.inode();
|
||||
if inode
|
||||
if !inode
|
||||
.fs_event_publisher_or_init()
|
||||
.add_subscriber(subscriber)
|
||||
{
|
||||
inode.fs().fs_event_subscriber_stats().add_subscriber();
|
||||
// FIXME: This can be triggered by `unlink()` race conditions or
|
||||
// `inotify_add_watch("/proc/self/fd/[fd]")`, where `[fd]` is a file descriptor
|
||||
// pointing to a deleted file. Although Linux allows this, we don't support it, so an
|
||||
// error is returned here.
|
||||
return_errno_with_message!(
|
||||
Errno::ENOENT,
|
||||
"adding an inotify watch to a deleted inode is not supported yet"
|
||||
);
|
||||
}
|
||||
inode.fs().fs_event_subscriber_stats().add_subscriber();
|
||||
|
||||
let wd = inotify_subscriber.wd();
|
||||
let entry = SubscriberEntry {
|
||||
|
|
|
|||
|
|
@ -327,6 +327,7 @@ impl Dentry {
|
|||
let nlinks = child_inode.metadata().nlinks;
|
||||
fs::notify::on_link_count(&child_inode);
|
||||
if nlinks == 0 {
|
||||
// FIXME: `DELETE_SELF` should be generated after closing the last FD.
|
||||
fs::notify::on_inode_removed(&child_inode);
|
||||
}
|
||||
fs::notify::on_delete(self.inode(), &child_inode, || name.to_string());
|
||||
|
|
@ -379,13 +380,14 @@ impl Dentry {
|
|||
|
||||
let nlinks = child_inode.metadata().nlinks;
|
||||
if nlinks == 0 {
|
||||
// FIXME: `DELETE_SELF` should be generated after closing the last FD.
|
||||
fs::notify::on_inode_removed(&child_inode);
|
||||
}
|
||||
fs::notify::on_delete(self.inode(), &child_inode, || name.to_string());
|
||||
if nlinks == 0 {
|
||||
// Ideally, we would use `fs_event_publisher()` here to avoid creating a
|
||||
// `FsEventPublisher` on a dying inode. However, it isn't possible because we need to
|
||||
// disable new subscribers.
|
||||
// `FsEventPublisher` instance on a dying inode. However, it isn't possible because we
|
||||
// need to disable new subscribers.
|
||||
let publisher = child_inode.fs_event_publisher_or_init();
|
||||
let removed_nr_subscribers = publisher.disable_new_and_remove_subscribers();
|
||||
child_inode
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <sys/inotify.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "../test.h"
|
||||
|
||||
#define TEST_FILE "/tmp/test1"
|
||||
|
||||
FN_TEST(unlink_add)
|
||||
{
|
||||
int inotify_fd, fd, wd;
|
||||
|
||||
inotify_fd = TEST_SUCC(inotify_init1(O_NONBLOCK));
|
||||
|
||||
fd = TEST_RES(open(TEST_FILE, O_CREAT | O_WRONLY, 0644), _ret == 4);
|
||||
TEST_SUCC(unlink(TEST_FILE));
|
||||
|
||||
// FIXME: Asterinas currently does not support adding inotify watches
|
||||
// to deleted inodes.
|
||||
#ifdef __asterinas__
|
||||
TEST_ERRNO(inotify_add_watch(inotify_fd, "/proc/self/fd/4",
|
||||
IN_DELETE_SELF),
|
||||
ENOENT);
|
||||
(void)wd;
|
||||
#else
|
||||
wd = TEST_SUCC(inotify_add_watch(inotify_fd, "/proc/self/fd/4",
|
||||
IN_DELETE_SELF));
|
||||
TEST_SUCC(inotify_rm_watch(inotify_fd, wd));
|
||||
#endif
|
||||
|
||||
TEST_SUCC(close(fd));
|
||||
TEST_SUCC(close(inotify_fd));
|
||||
}
|
||||
END_TEST()
|
||||
|
|
@ -32,6 +32,7 @@ hello_pie/hello
|
|||
hello_world/hello_world
|
||||
inotify/inotify_align
|
||||
inotify/inotify_poll
|
||||
inotify/inotify_unlink
|
||||
itimer/setitimer
|
||||
itimer/timer_create
|
||||
mmap/mmap_and_fork
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
InotifyTest.AddRemoveUnlinkDoNotDeadlock
|
||||
# TODO: Due to some FS bugs, they may trigger
|
||||
# "PosixError(errno=28 No space left on device)"
|
||||
# because too many files are created and deleted.
|
||||
InotifyTest.InotifyAndTargetDestructionDoNotDeadlock
|
||||
InotifyTest.NotifyNoDeadlock
|
||||
InotifyTest.InotifyAndTargetDestructionDoNotDeadlock_NoRandomSave
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
# Nothing here. Pipe files are supported by the ext2 file system.
|
||||
#
|
||||
# This file is kept to ensure that the `blocklists.ext2` directory
|
||||
# is not empty, as it may become useful in the future.
|
||||
|
|
@ -1,5 +1,13 @@
|
|||
# TODO: Generate `DELETE_SELF`/`IGNORED` after closing the last FD.
|
||||
Inotify.DupFD
|
||||
Inotify.IncludeUnlinkedFile
|
||||
Inotify.IncludeUnlinkedFile_NoRandomSave
|
||||
|
||||
# Symbolic links to the busybox binary does not work:
|
||||
# "gvisor_test_temp_1103_1767603858010282988: applet not found"
|
||||
Inotify.Exec
|
||||
|
||||
# TODO: Support the `EXCL_UNLINK` flag.
|
||||
Inotify.ExcludeUnlink
|
||||
Inotify.ExcludeUnlink_NoRandomSave
|
||||
Inotify.ExcludeUnlinkDirectory
|
||||
|
|
@ -8,16 +16,17 @@ Inotify.ExcludeUnlinkInodeEvents
|
|||
Inotify.ExcludeUnlinkInodeEvents_NoRandomSave
|
||||
Inotify.ExcludeUnlinkMultipleChildren
|
||||
Inotify.ExcludeUnlinkMultipleChildren_NoRandomSave
|
||||
Inotify.IncludeUnlinkedFile
|
||||
Inotify.IncludeUnlinkedFile_NoRandomSave
|
||||
|
||||
# TODO: Report `MOVE_*` events at the `rename()` system call.
|
||||
Inotify.MoveGeneratesEvents
|
||||
Inotify.MoveWatchedTargetGeneratesEvents
|
||||
|
||||
# TODO: Support the `ONESHOT` flag.
|
||||
Inotify.OneShot
|
||||
|
||||
# TODO: Support the `splice()` system call.
|
||||
Inotify.SpliceOnInotifyFD
|
||||
Inotify.SpliceOnWatchTarget
|
||||
Inotify.Utimensat
|
||||
|
||||
InotifyTest.AddRemoveUnlinkDoNotDeadlock
|
||||
InotifyTest.InotifyAndTargetDestructionDoNotDeadlock
|
||||
InotifyTest.InotifyAndTargetDestructionDoNotDeadlock_NoRandomSave
|
||||
InotifyTest.NotifyNoDeadlock
|
||||
# TODO: Correct event generation at the `untimensat()` system call.
|
||||
Inotify.Utimensat
|
||||
|
|
|
|||
Loading…
Reference in New Issue