* [f2fs-dev] [PATCH 1/3] fs/dcache: Add d_clear_dir_neg_dentries()
@ 2021-03-28 14:43 ` André Almeida
0 siblings, 0 replies; 18+ messages in thread
From: André Almeida @ 2021-03-28 14:43 UTC (permalink / raw)
To: Alexander Viro, Theodore Ts'o, Andreas Dilger, Jaegeuk Kim,
Chao Yu
Cc: kernel, Daniel Rosenberg, linux-kernel, linux-f2fs-devel,
André Almeida, linux-fsdevel, linux-ext4, krisman
For directories with negative dentries that are becoming case-insensitive
dirs, we need to remove all those negative dentries, otherwise they will
become dangling dentries. During the creation of a new file, if a d_hash
collision happens and the names match in a case-insensitive way, the name
of the file will be the name defined at the negative dentry, that may be
different from the specified by the user. To prevent this from
happening, we need to remove all dentries in a directory. Given that the
directory must be empty before we call this function we are sure that
all dentries there will be negative.
Create a function to remove all negative dentries from a directory, to
be used as explained above by filesystems that support case-insensitive
lookups.
Signed-off-by: André Almeida <andrealmeid@collabora.com>
---
fs/dcache.c | 27 +++++++++++++++++++++++++++
include/linux/dcache.h | 1 +
2 files changed, 28 insertions(+)
diff --git a/fs/dcache.c b/fs/dcache.c
index 7d24ff7eb206..fafb3016d6fd 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1723,6 +1723,33 @@ void d_invalidate(struct dentry *dentry)
}
EXPORT_SYMBOL(d_invalidate);
+/**
+ * d_clear_dir_neg_dentries - Remove negative dentries in an inode
+ * @dir: Directory to clear negative dentries
+ *
+ * For directories with negative dentries that are becoming case-insensitive
+ * dirs, we need to remove all those negative dentries, otherwise they will
+ * become dangling dentries. During the creation of a new file, if a d_hash
+ * collision happens and the names match in a case-insensitive, the name of
+ * the file will be the name defined at the negative dentry, that can be
+ * different from the specified by the user. To prevent this from happening, we
+ * need to remove all dentries in a directory. Given that the directory must be
+ * empty before we call this function we are sure that all dentries there will
+ * be negative.
+ */
+void d_clear_dir_neg_dentries(struct inode *dir)
+{
+ struct dentry *alias, *dentry;
+
+ hlist_for_each_entry(alias, &dir->i_dentry, d_u.d_alias) {
+ list_for_each_entry(dentry, &alias->d_subdirs, d_child) {
+ d_drop(dentry);
+ dput(dentry);
+ }
+ }
+}
+EXPORT_SYMBOL(d_clear_dir_neg_dentries);
+
/**
* __d_alloc - allocate a dcache entry
* @sb: filesystem it will belong to
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index c1e48014106f..c43cd0be077f 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -250,6 +250,7 @@ extern void shrink_dcache_sb(struct super_block *);
extern void shrink_dcache_parent(struct dentry *);
extern void shrink_dcache_for_umount(struct super_block *);
extern void d_invalidate(struct dentry *);
+extern void d_clear_dir_neg_dentries(struct inode *);
/* only used at mount-time */
extern struct dentry * d_make_root(struct inode *);
--
2.31.0
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH 1/3] fs/dcache: Add d_clear_dir_neg_dentries()
2021-03-28 14:43 ` [f2fs-dev] " André Almeida
@ 2021-03-28 15:07 ` Matthew Wilcox
-1 siblings, 0 replies; 18+ messages in thread
From: Matthew Wilcox @ 2021-03-28 15:07 UTC (permalink / raw)
To: André Almeida
Cc: Alexander Viro, Theodore Ts'o, Andreas Dilger, Jaegeuk Kim,
Chao Yu, krisman, kernel, linux-fsdevel, linux-kernel, linux-ext4,
linux-f2fs-devel, Daniel Rosenberg, Chao Yu
On Sun, Mar 28, 2021 at 11:43:54AM -0300, André Almeida wrote:
> +/**
> + * d_clear_dir_neg_dentries - Remove negative dentries in an inode
> + * @dir: Directory to clear negative dentries
> + *
> + * For directories with negative dentries that are becoming case-insensitive
> + * dirs, we need to remove all those negative dentries, otherwise they will
> + * become dangling dentries. During the creation of a new file, if a d_hash
> + * collision happens and the names match in a case-insensitive, the name of
> + * the file will be the name defined at the negative dentry, that can be
> + * different from the specified by the user. To prevent this from happening, we
> + * need to remove all dentries in a directory. Given that the directory must be
> + * empty before we call this function we are sure that all dentries there will
> + * be negative.
> + */
This is quite the landmine of a function. It _assumes_ that the directory
is empty, and clears all dentries in it.
> +void d_clear_dir_neg_dentries(struct inode *dir)
> +{
> + struct dentry *alias, *dentry;
> +
> + hlist_for_each_entry(alias, &dir->i_dentry, d_u.d_alias) {
> + list_for_each_entry(dentry, &alias->d_subdirs, d_child) {
> + d_drop(dentry);
> + dput(dentry);
> + }
I would be happier if it included a check for negativity. d_is_negative()
or maybe this newfangled d_really_is_negative() (i haven't stayed up
to speed on the precise difference between the two)
> + }
> +}
> +EXPORT_SYMBOL(d_clear_dir_neg_dentries);
I'd rather see this _GPL for such an internal thing.
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [f2fs-dev] [PATCH 1/3] fs/dcache: Add d_clear_dir_neg_dentries()
@ 2021-03-28 15:07 ` Matthew Wilcox
0 siblings, 0 replies; 18+ messages in thread
From: Matthew Wilcox @ 2021-03-28 15:07 UTC (permalink / raw)
To: André Almeida
Cc: linux-ext4, Theodore Ts'o, Daniel Rosenberg, linux-kernel,
linux-f2fs-devel, Andreas Dilger, Alexander Viro, linux-fsdevel,
Jaegeuk Kim, kernel, krisman
On Sun, Mar 28, 2021 at 11:43:54AM -0300, André Almeida wrote:
> +/**
> + * d_clear_dir_neg_dentries - Remove negative dentries in an inode
> + * @dir: Directory to clear negative dentries
> + *
> + * For directories with negative dentries that are becoming case-insensitive
> + * dirs, we need to remove all those negative dentries, otherwise they will
> + * become dangling dentries. During the creation of a new file, if a d_hash
> + * collision happens and the names match in a case-insensitive, the name of
> + * the file will be the name defined at the negative dentry, that can be
> + * different from the specified by the user. To prevent this from happening, we
> + * need to remove all dentries in a directory. Given that the directory must be
> + * empty before we call this function we are sure that all dentries there will
> + * be negative.
> + */
This is quite the landmine of a function. It _assumes_ that the directory
is empty, and clears all dentries in it.
> +void d_clear_dir_neg_dentries(struct inode *dir)
> +{
> + struct dentry *alias, *dentry;
> +
> + hlist_for_each_entry(alias, &dir->i_dentry, d_u.d_alias) {
> + list_for_each_entry(dentry, &alias->d_subdirs, d_child) {
> + d_drop(dentry);
> + dput(dentry);
> + }
I would be happier if it included a check for negativity. d_is_negative()
or maybe this newfangled d_really_is_negative() (i haven't stayed up
to speed on the precise difference between the two)
> + }
> +}
> +EXPORT_SYMBOL(d_clear_dir_neg_dentries);
I'd rather see this _GPL for such an internal thing.
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH 1/3] fs/dcache: Add d_clear_dir_neg_dentries()
2021-03-28 15:07 ` [f2fs-dev] " Matthew Wilcox
@ 2021-03-28 15:49 ` André Almeida
-1 siblings, 0 replies; 18+ messages in thread
From: André Almeida @ 2021-03-28 15:49 UTC (permalink / raw)
To: Matthew Wilcox
Cc: Alexander Viro, Theodore Ts'o, Andreas Dilger, Jaegeuk Kim,
Chao Yu, krisman, kernel, linux-fsdevel, linux-kernel, linux-ext4,
linux-f2fs-devel, Daniel Rosenberg, Chao Yu
Às 12:07 de 28/03/21, Matthew Wilcox escreveu:
> On Sun, Mar 28, 2021 at 11:43:54AM -0300, André Almeida wrote:
>> +/**
>> + * d_clear_dir_neg_dentries - Remove negative dentries in an inode
>> + * @dir: Directory to clear negative dentries
>> + *
>> + * For directories with negative dentries that are becoming case-insensitive
>> + * dirs, we need to remove all those negative dentries, otherwise they will
>> + * become dangling dentries. During the creation of a new file, if a d_hash
>> + * collision happens and the names match in a case-insensitive, the name of
>> + * the file will be the name defined at the negative dentry, that can be
>> + * different from the specified by the user. To prevent this from happening, we
>> + * need to remove all dentries in a directory. Given that the directory must be
>> + * empty before we call this function we are sure that all dentries there will
>> + * be negative.
>> + */
>
> This is quite the landmine of a function. It _assumes_ that the directory
> is empty, and clears all dentries in it.
>
>> +void d_clear_dir_neg_dentries(struct inode *dir)
>> +{
>> + struct dentry *alias, *dentry;
>> +
>> + hlist_for_each_entry(alias, &dir->i_dentry, d_u.d_alias) {
>> + list_for_each_entry(dentry, &alias->d_subdirs, d_child) {
>> + d_drop(dentry);
>> + dput(dentry);
>> + }
>
> I would be happier if it included a check for negativity. d_is_negative()
> or maybe this newfangled d_really_is_negative() (i haven't stayed up
> to speed on the precise difference between the two)
>
Makes sense. And given that this only makes sense if the directory is
empty, if it founds a non-negative dentry, it should return some error
right?
>> + }
>> +}
>> +EXPORT_SYMBOL(d_clear_dir_neg_dentries);
>
> I'd rather see this _GPL for such an internal thing.
>
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [f2fs-dev] [PATCH 1/3] fs/dcache: Add d_clear_dir_neg_dentries()
@ 2021-03-28 15:49 ` André Almeida
0 siblings, 0 replies; 18+ messages in thread
From: André Almeida @ 2021-03-28 15:49 UTC (permalink / raw)
To: Matthew Wilcox
Cc: linux-ext4, Theodore Ts'o, Daniel Rosenberg, linux-kernel,
linux-f2fs-devel, Andreas Dilger, Alexander Viro, linux-fsdevel,
Jaegeuk Kim, kernel, krisman
Às 12:07 de 28/03/21, Matthew Wilcox escreveu:
> On Sun, Mar 28, 2021 at 11:43:54AM -0300, André Almeida wrote:
>> +/**
>> + * d_clear_dir_neg_dentries - Remove negative dentries in an inode
>> + * @dir: Directory to clear negative dentries
>> + *
>> + * For directories with negative dentries that are becoming case-insensitive
>> + * dirs, we need to remove all those negative dentries, otherwise they will
>> + * become dangling dentries. During the creation of a new file, if a d_hash
>> + * collision happens and the names match in a case-insensitive, the name of
>> + * the file will be the name defined at the negative dentry, that can be
>> + * different from the specified by the user. To prevent this from happening, we
>> + * need to remove all dentries in a directory. Given that the directory must be
>> + * empty before we call this function we are sure that all dentries there will
>> + * be negative.
>> + */
>
> This is quite the landmine of a function. It _assumes_ that the directory
> is empty, and clears all dentries in it.
>
>> +void d_clear_dir_neg_dentries(struct inode *dir)
>> +{
>> + struct dentry *alias, *dentry;
>> +
>> + hlist_for_each_entry(alias, &dir->i_dentry, d_u.d_alias) {
>> + list_for_each_entry(dentry, &alias->d_subdirs, d_child) {
>> + d_drop(dentry);
>> + dput(dentry);
>> + }
>
> I would be happier if it included a check for negativity. d_is_negative()
> or maybe this newfangled d_really_is_negative() (i haven't stayed up
> to speed on the precise difference between the two)
>
Makes sense. And given that this only makes sense if the directory is
empty, if it founds a non-negative dentry, it should return some error
right?
>> + }
>> +}
>> +EXPORT_SYMBOL(d_clear_dir_neg_dentries);
>
> I'd rather see this _GPL for such an internal thing.
>
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/3] fs/dcache: Add d_clear_dir_neg_dentries()
2021-03-28 14:43 ` [f2fs-dev] " André Almeida
@ 2021-03-28 17:39 ` Al Viro
-1 siblings, 0 replies; 18+ messages in thread
From: Al Viro @ 2021-03-28 17:39 UTC (permalink / raw)
To: André Almeida
Cc: Theodore Ts'o, Andreas Dilger, Jaegeuk Kim, Chao Yu, krisman,
kernel, linux-fsdevel, linux-kernel, linux-ext4, linux-f2fs-devel,
Daniel Rosenberg, Chao Yu
On Sun, Mar 28, 2021 at 11:43:54AM -0300, André Almeida wrote:
> +/**
> + * d_clear_dir_neg_dentries - Remove negative dentries in an inode
> + * @dir: Directory to clear negative dentries
> + *
> + * For directories with negative dentries that are becoming case-insensitive
> + * dirs, we need to remove all those negative dentries, otherwise they will
> + * become dangling dentries. During the creation of a new file, if a d_hash
> + * collision happens and the names match in a case-insensitive, the name of
> + * the file will be the name defined at the negative dentry, that can be
> + * different from the specified by the user. To prevent this from happening, we
> + * need to remove all dentries in a directory. Given that the directory must be
> + * empty before we call this function we are sure that all dentries there will
> + * be negative.
> + */
> +void d_clear_dir_neg_dentries(struct inode *dir)
> +{
> + struct dentry *alias, *dentry;
> +
> + hlist_for_each_entry(alias, &dir->i_dentry, d_u.d_alias) {
> + list_for_each_entry(dentry, &alias->d_subdirs, d_child) {
> + d_drop(dentry);
> + dput(dentry);
> + }
> + }
> +}
That makes no sense whatsoever.
1) directories can never have more than one alias
2) what the hell are you doing to refcounts on those children?
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [f2fs-dev] [PATCH 1/3] fs/dcache: Add d_clear_dir_neg_dentries()
@ 2021-03-28 17:39 ` Al Viro
0 siblings, 0 replies; 18+ messages in thread
From: Al Viro @ 2021-03-28 17:39 UTC (permalink / raw)
To: André Almeida
Cc: linux-ext4, Theodore Ts'o, Daniel Rosenberg, linux-kernel,
linux-f2fs-devel, Andreas Dilger, linux-fsdevel, Jaegeuk Kim,
kernel, krisman
On Sun, Mar 28, 2021 at 11:43:54AM -0300, André Almeida wrote:
> +/**
> + * d_clear_dir_neg_dentries - Remove negative dentries in an inode
> + * @dir: Directory to clear negative dentries
> + *
> + * For directories with negative dentries that are becoming case-insensitive
> + * dirs, we need to remove all those negative dentries, otherwise they will
> + * become dangling dentries. During the creation of a new file, if a d_hash
> + * collision happens and the names match in a case-insensitive, the name of
> + * the file will be the name defined at the negative dentry, that can be
> + * different from the specified by the user. To prevent this from happening, we
> + * need to remove all dentries in a directory. Given that the directory must be
> + * empty before we call this function we are sure that all dentries there will
> + * be negative.
> + */
> +void d_clear_dir_neg_dentries(struct inode *dir)
> +{
> + struct dentry *alias, *dentry;
> +
> + hlist_for_each_entry(alias, &dir->i_dentry, d_u.d_alias) {
> + list_for_each_entry(dentry, &alias->d_subdirs, d_child) {
> + d_drop(dentry);
> + dput(dentry);
> + }
> + }
> +}
That makes no sense whatsoever.
1) directories can never have more than one alias
2) what the hell are you doing to refcounts on those children?
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/3] fs/dcache: Add d_clear_dir_neg_dentries()
2021-03-28 14:43 ` [f2fs-dev] " André Almeida
@ 2021-03-30 1:48 ` Eric Biggers
-1 siblings, 0 replies; 18+ messages in thread
From: Eric Biggers @ 2021-03-30 1:48 UTC (permalink / raw)
To: André Almeida
Cc: Alexander Viro, Theodore Ts'o, Andreas Dilger, Jaegeuk Kim,
Chao Yu, kernel, Daniel Rosenberg, linux-kernel, linux-f2fs-devel,
linux-fsdevel, linux-ext4, krisman
On Sun, Mar 28, 2021 at 11:43:54AM -0300, André Almeida wrote:
> For directories with negative dentries that are becoming case-insensitive
> dirs, we need to remove all those negative dentries, otherwise they will
> become dangling dentries. During the creation of a new file, if a d_hash
> collision happens and the names match in a case-insensitive way, the name
> of the file will be the name defined at the negative dentry, that may be
> different from the specified by the user. To prevent this from
> happening, we need to remove all dentries in a directory. Given that the
> directory must be empty before we call this function we are sure that
> all dentries there will be negative.
>
> Create a function to remove all negative dentries from a directory, to
> be used as explained above by filesystems that support case-insensitive
> lookups.
>
> Signed-off-by: André Almeida <andrealmeid@collabora.com>
> ---
> fs/dcache.c | 27 +++++++++++++++++++++++++++
> include/linux/dcache.h | 1 +
> 2 files changed, 28 insertions(+)
>
> diff --git a/fs/dcache.c b/fs/dcache.c
> index 7d24ff7eb206..fafb3016d6fd 100644
> --- a/fs/dcache.c
> +++ b/fs/dcache.c
> @@ -1723,6 +1723,33 @@ void d_invalidate(struct dentry *dentry)
> }
> EXPORT_SYMBOL(d_invalidate);
>
> +/**
> + * d_clear_dir_neg_dentries - Remove negative dentries in an inode
> + * @dir: Directory to clear negative dentries
> + *
> + * For directories with negative dentries that are becoming case-insensitive
> + * dirs, we need to remove all those negative dentries, otherwise they will
> + * become dangling dentries. During the creation of a new file, if a d_hash
> + * collision happens and the names match in a case-insensitive, the name of
> + * the file will be the name defined at the negative dentry, that can be
> + * different from the specified by the user. To prevent this from happening, we
> + * need to remove all dentries in a directory. Given that the directory must be
> + * empty before we call this function we are sure that all dentries there will
> + * be negative.
> + */
> +void d_clear_dir_neg_dentries(struct inode *dir)
> +{
> + struct dentry *alias, *dentry;
> +
> + hlist_for_each_entry(alias, &dir->i_dentry, d_u.d_alias) {
> + list_for_each_entry(dentry, &alias->d_subdirs, d_child) {
> + d_drop(dentry);
> + dput(dentry);
> + }
> + }
> +}
> +EXPORT_SYMBOL(d_clear_dir_neg_dentries);
As Al already pointed out, this doesn't work as intended, for a number of
different reasons.
Did you consider just using shrink_dcache_parent()? That already does what you
are trying to do here, I think.
The harder part (which I don't think you've considered) is how to ensure that
all negative dentries really get invalidated even if there are lookups of them
happening concurrently. Concurrent lookups can take temporary references to the
negative dentries, preventing them from being invalidated.
- Eric
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [f2fs-dev] [PATCH 1/3] fs/dcache: Add d_clear_dir_neg_dentries()
@ 2021-03-30 1:48 ` Eric Biggers
0 siblings, 0 replies; 18+ messages in thread
From: Eric Biggers @ 2021-03-30 1:48 UTC (permalink / raw)
To: André Almeida
Cc: linux-ext4, Theodore Ts'o, Daniel Rosenberg, linux-kernel,
linux-f2fs-devel, Andreas Dilger, Alexander Viro, linux-fsdevel,
Jaegeuk Kim, kernel, krisman
On Sun, Mar 28, 2021 at 11:43:54AM -0300, André Almeida wrote:
> For directories with negative dentries that are becoming case-insensitive
> dirs, we need to remove all those negative dentries, otherwise they will
> become dangling dentries. During the creation of a new file, if a d_hash
> collision happens and the names match in a case-insensitive way, the name
> of the file will be the name defined at the negative dentry, that may be
> different from the specified by the user. To prevent this from
> happening, we need to remove all dentries in a directory. Given that the
> directory must be empty before we call this function we are sure that
> all dentries there will be negative.
>
> Create a function to remove all negative dentries from a directory, to
> be used as explained above by filesystems that support case-insensitive
> lookups.
>
> Signed-off-by: André Almeida <andrealmeid@collabora.com>
> ---
> fs/dcache.c | 27 +++++++++++++++++++++++++++
> include/linux/dcache.h | 1 +
> 2 files changed, 28 insertions(+)
>
> diff --git a/fs/dcache.c b/fs/dcache.c
> index 7d24ff7eb206..fafb3016d6fd 100644
> --- a/fs/dcache.c
> +++ b/fs/dcache.c
> @@ -1723,6 +1723,33 @@ void d_invalidate(struct dentry *dentry)
> }
> EXPORT_SYMBOL(d_invalidate);
>
> +/**
> + * d_clear_dir_neg_dentries - Remove negative dentries in an inode
> + * @dir: Directory to clear negative dentries
> + *
> + * For directories with negative dentries that are becoming case-insensitive
> + * dirs, we need to remove all those negative dentries, otherwise they will
> + * become dangling dentries. During the creation of a new file, if a d_hash
> + * collision happens and the names match in a case-insensitive, the name of
> + * the file will be the name defined at the negative dentry, that can be
> + * different from the specified by the user. To prevent this from happening, we
> + * need to remove all dentries in a directory. Given that the directory must be
> + * empty before we call this function we are sure that all dentries there will
> + * be negative.
> + */
> +void d_clear_dir_neg_dentries(struct inode *dir)
> +{
> + struct dentry *alias, *dentry;
> +
> + hlist_for_each_entry(alias, &dir->i_dentry, d_u.d_alias) {
> + list_for_each_entry(dentry, &alias->d_subdirs, d_child) {
> + d_drop(dentry);
> + dput(dentry);
> + }
> + }
> +}
> +EXPORT_SYMBOL(d_clear_dir_neg_dentries);
As Al already pointed out, this doesn't work as intended, for a number of
different reasons.
Did you consider just using shrink_dcache_parent()? That already does what you
are trying to do here, I think.
The harder part (which I don't think you've considered) is how to ensure that
all negative dentries really get invalidated even if there are lookups of them
happening concurrently. Concurrent lookups can take temporary references to the
negative dentries, preventing them from being invalidated.
- Eric
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH 1/3] fs/dcache: Add d_clear_dir_neg_dentries()
2021-03-30 1:48 ` [f2fs-dev] " Eric Biggers
@ 2021-03-30 12:54 ` André Almeida
-1 siblings, 0 replies; 18+ messages in thread
From: André Almeida @ 2021-03-30 12:54 UTC (permalink / raw)
To: Eric Biggers
Cc: Alexander Viro, Theodore Ts'o, Andreas Dilger, Jaegeuk Kim,
Chao Yu, kernel, Daniel Rosenberg, linux-kernel, linux-f2fs-devel,
linux-fsdevel, linux-ext4, krisman
Hi Eric,
Às 22:48 de 29/03/21, Eric Biggers escreveu:
> On Sun, Mar 28, 2021 at 11:43:54AM -0300, André Almeida wrote:
>> For directories with negative dentries that are becoming case-insensitive
>> dirs, we need to remove all those negative dentries, otherwise they will
>> become dangling dentries. During the creation of a new file, if a d_hash
>> collision happens and the names match in a case-insensitive way, the name
>> of the file will be the name defined at the negative dentry, that may be
>> different from the specified by the user. To prevent this from
>> happening, we need to remove all dentries in a directory. Given that the
>> directory must be empty before we call this function we are sure that
>> all dentries there will be negative.
>>
>> Create a function to remove all negative dentries from a directory, to
>> be used as explained above by filesystems that support case-insensitive
>> lookups.
>>
>> Signed-off-by: André Almeida <andrealmeid@collabora.com>
>> ---
>> fs/dcache.c | 27 +++++++++++++++++++++++++++
>> include/linux/dcache.h | 1 +
>> 2 files changed, 28 insertions(+)
>>
>> diff --git a/fs/dcache.c b/fs/dcache.c
>> index 7d24ff7eb206..fafb3016d6fd 100644
>> --- a/fs/dcache.c
>> +++ b/fs/dcache.c
>> @@ -1723,6 +1723,33 @@ void d_invalidate(struct dentry *dentry)
>> }
>> EXPORT_SYMBOL(d_invalidate);
>>
>> +/**
>> + * d_clear_dir_neg_dentries - Remove negative dentries in an inode
>> + * @dir: Directory to clear negative dentries
>> + *
>> + * For directories with negative dentries that are becoming case-insensitive
>> + * dirs, we need to remove all those negative dentries, otherwise they will
>> + * become dangling dentries. During the creation of a new file, if a d_hash
>> + * collision happens and the names match in a case-insensitive, the name of
>> + * the file will be the name defined at the negative dentry, that can be
>> + * different from the specified by the user. To prevent this from happening, we
>> + * need to remove all dentries in a directory. Given that the directory must be
>> + * empty before we call this function we are sure that all dentries there will
>> + * be negative.
>> + */
>> +void d_clear_dir_neg_dentries(struct inode *dir)
>> +{
>> + struct dentry *alias, *dentry;
>> +
>> + hlist_for_each_entry(alias, &dir->i_dentry, d_u.d_alias) {
>> + list_for_each_entry(dentry, &alias->d_subdirs, d_child) {
>> + d_drop(dentry);
>> + dput(dentry);
>> + }
>> + }
>> +}
>> +EXPORT_SYMBOL(d_clear_dir_neg_dentries);
>
> As Al already pointed out, this doesn't work as intended, for a number of
> different reasons.
>
> Did you consider just using shrink_dcache_parent()? That already does what you
> are trying to do here, I think.
When I wrote this patch, I didn't know it, but after Al Viro comments I
get back to the code and found it, and it seems do do what I intend
indeed, and my test is happy as well.
>
> The harder part (which I don't think you've considered) is how to ensure that
> all negative dentries really get invalidated even if there are lookups of them
> happening concurrently. Concurrent lookups can take temporary references to the
> negative dentries, preventing them from being invalidated.
>
I didn't consider that, thanks for the feedback. So this means that
those lookups will increase the refcount of the dentry, and it will only
get really invalidated when refcount reaches 0? Or do would I need to
call d_invalidate() again, until I succeed?
> - Eric
>
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [f2fs-dev] [PATCH 1/3] fs/dcache: Add d_clear_dir_neg_dentries()
@ 2021-03-30 12:54 ` André Almeida
0 siblings, 0 replies; 18+ messages in thread
From: André Almeida @ 2021-03-30 12:54 UTC (permalink / raw)
To: Eric Biggers
Cc: linux-ext4, Theodore Ts'o, Daniel Rosenberg, linux-kernel,
linux-f2fs-devel, Andreas Dilger, Alexander Viro, linux-fsdevel,
Jaegeuk Kim, kernel, krisman
Hi Eric,
Às 22:48 de 29/03/21, Eric Biggers escreveu:
> On Sun, Mar 28, 2021 at 11:43:54AM -0300, André Almeida wrote:
>> For directories with negative dentries that are becoming case-insensitive
>> dirs, we need to remove all those negative dentries, otherwise they will
>> become dangling dentries. During the creation of a new file, if a d_hash
>> collision happens and the names match in a case-insensitive way, the name
>> of the file will be the name defined at the negative dentry, that may be
>> different from the specified by the user. To prevent this from
>> happening, we need to remove all dentries in a directory. Given that the
>> directory must be empty before we call this function we are sure that
>> all dentries there will be negative.
>>
>> Create a function to remove all negative dentries from a directory, to
>> be used as explained above by filesystems that support case-insensitive
>> lookups.
>>
>> Signed-off-by: André Almeida <andrealmeid@collabora.com>
>> ---
>> fs/dcache.c | 27 +++++++++++++++++++++++++++
>> include/linux/dcache.h | 1 +
>> 2 files changed, 28 insertions(+)
>>
>> diff --git a/fs/dcache.c b/fs/dcache.c
>> index 7d24ff7eb206..fafb3016d6fd 100644
>> --- a/fs/dcache.c
>> +++ b/fs/dcache.c
>> @@ -1723,6 +1723,33 @@ void d_invalidate(struct dentry *dentry)
>> }
>> EXPORT_SYMBOL(d_invalidate);
>>
>> +/**
>> + * d_clear_dir_neg_dentries - Remove negative dentries in an inode
>> + * @dir: Directory to clear negative dentries
>> + *
>> + * For directories with negative dentries that are becoming case-insensitive
>> + * dirs, we need to remove all those negative dentries, otherwise they will
>> + * become dangling dentries. During the creation of a new file, if a d_hash
>> + * collision happens and the names match in a case-insensitive, the name of
>> + * the file will be the name defined at the negative dentry, that can be
>> + * different from the specified by the user. To prevent this from happening, we
>> + * need to remove all dentries in a directory. Given that the directory must be
>> + * empty before we call this function we are sure that all dentries there will
>> + * be negative.
>> + */
>> +void d_clear_dir_neg_dentries(struct inode *dir)
>> +{
>> + struct dentry *alias, *dentry;
>> +
>> + hlist_for_each_entry(alias, &dir->i_dentry, d_u.d_alias) {
>> + list_for_each_entry(dentry, &alias->d_subdirs, d_child) {
>> + d_drop(dentry);
>> + dput(dentry);
>> + }
>> + }
>> +}
>> +EXPORT_SYMBOL(d_clear_dir_neg_dentries);
>
> As Al already pointed out, this doesn't work as intended, for a number of
> different reasons.
>
> Did you consider just using shrink_dcache_parent()? That already does what you
> are trying to do here, I think.
When I wrote this patch, I didn't know it, but after Al Viro comments I
get back to the code and found it, and it seems do do what I intend
indeed, and my test is happy as well.
>
> The harder part (which I don't think you've considered) is how to ensure that
> all negative dentries really get invalidated even if there are lookups of them
> happening concurrently. Concurrent lookups can take temporary references to the
> negative dentries, preventing them from being invalidated.
>
I didn't consider that, thanks for the feedback. So this means that
those lookups will increase the refcount of the dentry, and it will only
get really invalidated when refcount reaches 0? Or do would I need to
call d_invalidate() again, until I succeed?
> - Eric
>
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 18+ messages in thread