]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
nfsd: allow reaping files still under writeback
authorJeff Layton <jlayton@kernel.org>
Wed, 15 Feb 2023 11:53:54 +0000 (06:53 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 10 Apr 2024 14:19:27 +0000 (16:19 +0200)
[ Upstream commit dcb779fcd4ed5984ad15991d574943d12a8693d1 ]

On most filesystems, there is no reason to delay reaping an nfsd_file
just because its underlying inode is still under writeback. nfsd just
relies on client activity or the local flusher threads to do writeback.

The main exception is NFS, which flushes all of its dirty data on last
close. Add a new EXPORT_OP_FLUSH_ON_CLOSE flag to allow filesystems to
signal that they do this, and only skip closing files under writeback on
such filesystems.

Also, remove a redundant NULL file pointer check in
nfsd_file_check_writeback, and clean up nfs's export op flag
definitions.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Acked-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
[ cel: adjusted to apply to v5.15.y ]
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfs/export.c
fs/nfsd/filecache.c
include/linux/exportfs.h

index 37a1a88df7717e155a6ee50a0108ea05f81ab8e3..eafa9d7b0911b254b1702d14a68abdf2acdee2ed 100644 (file)
@@ -178,7 +178,10 @@ const struct export_operations nfs_export_ops = {
        .fh_to_dentry = nfs_fh_to_dentry,
        .get_parent = nfs_get_parent,
        .fetch_iversion = nfs_fetch_iversion,
-       .flags = EXPORT_OP_NOWCC|EXPORT_OP_NOSUBTREECHK|
-               EXPORT_OP_CLOSE_BEFORE_UNLINK|EXPORT_OP_REMOTE_FS|
-               EXPORT_OP_NOATOMIC_ATTR,
+       .flags = EXPORT_OP_NOWCC                |
+                EXPORT_OP_NOSUBTREECHK         |
+                EXPORT_OP_CLOSE_BEFORE_UNLINK  |
+                EXPORT_OP_REMOTE_FS            |
+                EXPORT_OP_NOATOMIC_ATTR        |
+                EXPORT_OP_FLUSH_ON_CLOSE,
 };
index 1d4c0387c4192fe28df582ff4216f50f1ecb0f7e..080d79654785490c6fa2e3f5e917b287182ecdcb 100644 (file)
@@ -401,13 +401,23 @@ nfsd_file_check_writeback(struct nfsd_file *nf)
        struct file *file = nf->nf_file;
        struct address_space *mapping;
 
-       if (!file || !(file->f_mode & FMODE_WRITE))
+       /* File not open for write? */
+       if (!(file->f_mode & FMODE_WRITE))
                return false;
+
+       /*
+        * Some filesystems (e.g. NFS) flush all dirty data on close.
+        * On others, there is no need to wait for writeback.
+        */
+       if (!(file_inode(file)->i_sb->s_export_op->flags & EXPORT_OP_FLUSH_ON_CLOSE))
+               return false;
+
        mapping = file->f_mapping;
        return mapping_tagged(mapping, PAGECACHE_TAG_DIRTY) ||
                mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK);
 }
 
+
 static bool nfsd_file_lru_add(struct nfsd_file *nf)
 {
        set_bit(NFSD_FILE_REFERENCED, &nf->nf_flags);
index fe848901fcc3acb04a732b82df95c86fbad93ddc..218fc5c54e901c727ac55da4b46668616e47e373 100644 (file)
@@ -221,6 +221,7 @@ struct export_operations {
 #define EXPORT_OP_NOATOMIC_ATTR                (0x10) /* Filesystem cannot supply
                                                  atomic attribute updates
                                                */
+#define EXPORT_OP_FLUSH_ON_CLOSE       (0x20) /* fs flushes file data on close */
        unsigned long   flags;
 };