Actions
Bug #12142
openrmdir on non empty directories triggers FILE_DELETE event even if nothing is deleted
Status:
New
Priority:
Normal
Assignee:
-
Category:
-
Start date:
Due date:
% Done:
0%
Estimated time:
Difficulty:
Medium
Tags:
Gerrit CR:
External Bug:
Description
rmdir on non empty directories triggers FILE_DELETE event even if nothing is deleted.
Here is a test program (test_port.c) for printing events from PORT_SOURCE_FILE.
#include <fcntl.h> #include <port.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> void print_event(port_event_t *pe); int main(int argc, char *argv[]) { if (argc != 2) { printf("usage: port_test path\n"); return -1; } struct stat astat; if (stat(argv[1], &astat)){ perror("stat"); return -1; } /* setup file_obj */ struct file_obj afile_obj; afile_obj.fo_atime = astat.st_atim; afile_obj.fo_mtime = astat.st_mtim; afile_obj.fo_ctime = astat.st_ctim; afile_obj.fo_name = argv[1]; int aport = port_create(); if (aport == -1) { perror("port_create"); return -1; } if (port_associate(aport, PORT_SOURCE_FILE,(uintptr_t) &afile_obj, 0, NULL)) { perror("port_associate"); return -1; } port_event_t pe; if (port_get(aport, &pe, NULL)) { perror("port_get"); return -1; } print_event(&pe); return 0; } void print_event(port_event_t *pe) { struct port_event_name { char *name; int event; }; struct port_event_name penames[11]; penames[0].name = "FILE_ACCESS"; penames[0].event = FILE_ACCESS; penames[1].name = "FILE_MODIFIED"; penames[1].event = FILE_MODIFIED; penames[2].name = "FILE_ATTRIB"; penames[2].event = FILE_ATTRIB; penames[3].name = "FILE_ACCESS"; penames[3].event = FILE_ACCESS; penames[4].name = "FILE_TRUNC"; penames[4].event = FILE_TRUNC; penames[5].name = "FILE_NOFOLLOW"; penames[5].event = FILE_NOFOLLOW; penames[6].name = "FILE_DELETE"; penames[6].event = FILE_DELETE; penames[7].name = "FILE_RENAME_TO"; penames[7].event = FILE_RENAME_TO; penames[8].name = "FILE_RENAME_FROM"; penames[8].event = FILE_RENAME_FROM; penames[9].name = "UNMOUNTED"; penames[9].event = UNMOUNTED; penames[10].name = "MOUNTEDOVER"; penames[10].event = MOUNTEDOVER; printf("|"); for (size_t i = 0; i < sizeof(penames)/sizeof(struct port_event_name); ++i) { if (pe->portev_events & penames[i].event) { printf("%s|", penames[i].name); } } printf("\n"); }
Creating a a directory with a file in it and running the test program:
mkdir /tmp/somedir touch /tmp/somedir/somefile ./port_test /tmp/somedir
Then running "rmdir /tmp/somedir" results in the output
|FILE_DELETE|
even if the directory was not deleted.
I see this as a bug.
Updated by Gergő Mihály Doma almost 4 years ago
Can you test this on filesystems other than ZFS?
Updated by Niclas Rosenvik almost 4 years ago
I tried this on a mounted usb disk with fat32 and it did not occur then.
Updated by John Levon almost 4 years ago
The cause is pretty simple:
2144 static int 2145 zfs_rmdir(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr, 2146 caller_context_t *ct, int flags) 2193 vnevent_rmdir(vp, dvp, name, ct); 2231 error = zfs_link_destroy(dl, zp, tx, zflg, NULL);
So we do the zfs_dirempty() check after sending the event.
The fix might be more complicated though.
Actions