nfsd: allow reaping files still under writeback
authorJeff Layton <jlayton@kernel.org>
Wed, 15 Feb 2023 11:53:54 +0000 (06:53 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Wed, 26 Apr 2023 13:04:59 +0000 (09:04 -0400)
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>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfs/export.c
fs/nfsd/filecache.c
include/linux/exportfs.h

index d6a6d1ebb8fd0b1081a7509631de2a19591c0e85..be686b8e0c5465621b4036c7a06b5bb307a70730 100644 (file)
@@ -149,7 +149,10 @@ const struct export_operations nfs_export_ops = {
        .encode_fh = nfs_encode_fh,
        .fh_to_dentry = nfs_fh_to_dentry,
        .get_parent = nfs_get_parent,
-       .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 9b7082fdd21159f7ea3b4fb0421ab58b97b5d655..a6fa6e98027721695ac29b30a8182e7eab35b105 100644 (file)
@@ -402,13 +402,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 601700fedc91c54e9a7fabc4249b4b0d14ddcf48..9edb29101ec87608c18540a32d7ddf36d83554c6 100644 (file)
@@ -220,6 +220,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;
 };