On Tue, 2024-12-24 at 10:09 -0500, James Bottomley wrote: > On Tue, 2024-12-24 at 08:07 -0500, James Bottomley wrote: > [...] > > > On the other hand the most intuitive thing would be to remove zero > > length files on last close, not first, so if you have a thought on > > how to do that easily, I'm all ears. > > I could do this by adding an open_count to the i_private data struct > efivar_entry and reimplementing simple_open as an efivarfs specific > open that increments this count and decrementing it in ->release(). > That's still somewhat adding "more convoluted crap", though ... There being no other suggestions as to how the vfs might do this; this is a sketch of the additional code needed to do it within efivarfs. As you can see, it's not actually that much. If this is OK with everyone I'll fold it in and post a v2. Since all simple_open really does is copy i_private to file->private_data, there's really not a lot of duplication in the attached. Regards, James --- diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c index 0e545c8be173..cf0179d84bc5 100644 --- a/fs/efivarfs/file.c +++ b/fs/efivarfs/file.c @@ -121,14 +121,34 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, static int efivarfs_file_release(struct inode *inode, struct file *file) { - if (i_size_read(inode) == 0) + bool release; + struct efivar_entry *var = inode->i_private; + + inode_lock(inode); + release = (--var->open_count == 0 && i_size_read(inode) == 0); + inode_unlock(inode); + + if (release) simple_recursive_removal(file->f_path.dentry, NULL); return 0; } +static int efivarfs_file_open(struct inode *inode, struct file *file) +{ + struct efivar_entry *entry = inode->i_private; + + file->private_data = entry; + + inode_lock(inode); + entry->open_count++; + inode_unlock(inode); + + return 0; +} + const struct file_operations efivarfs_file_operations = { - .open = simple_open, + .open = efivarfs_file_open, .read = efivarfs_file_read, .write = efivarfs_file_write, .release = efivarfs_file_release, diff --git a/fs/efivarfs/internal.h b/fs/efivarfs/internal.h index 18a600f80992..32b83f644798 100644 --- a/fs/efivarfs/internal.h +++ b/fs/efivarfs/internal.h @@ -26,6 +26,7 @@ struct efi_variable { struct efivar_entry { struct efi_variable var; + unsigned long open_count; }; int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *),