Skip to contentSkip to conversation

Patch "fs: move kiocb_start_write() into vfs_iocb_iter_write()" has been added to the 6.6-stable tree

DISCUSSION Amir Goldstein 1 participant 1 message May 31, 2024 1 message not in the archive Stable branch

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

#1 lore raw
Quoted 29 lines · Sasha Levin

This is a note to let you know that I've just added the patch titled

fs: move kiocb_start_write() into vfs_iocb_iter_write()

to the 6.6-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
fs-move-kiocb_start_write-into-vfs_iocb_iter_write.patch
and it can be found in the queue-6.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

commit 17f38d69e7960a2b346db04750b0e4ba867c0b83

Author: Amir Goldstein <[email protected]>
Date:   Wed Nov 22 14:27:12 2023 +0200

fs: move kiocb_start_write() into vfs_iocb_iter_write()

[ Upstream commit 6ae654392bb516a0baa47fed1f085d84e8cad739 ]

In vfs code, sb_start_write() is usually called after the permission hook in rw_verify_area(). vfs_iocb_iter_write() is an exception to this rule, where kiocb_start_write() is called by its callers.

Quoted 8 lines

Move kiocb_start_write() from the callers into vfs_iocb_iter_write() after the rw_verify_area() checks, to make them "start-write-safe".

The semantics of vfs_iocb_iter_write() is changed, so that the caller is responsible for calling kiocb_end_write() on completion only if async iocb was queued. The completion handlers of both callers were adapted to this semantic change.

This comment about semantics change looks like a clue from my past self that backporting this commit as standalone is risky.

This commit was part of a pretty big shuffle in splice and ovl code. I'd feel much more comfortable with backporting the entire ovl series 14ab6d425e8067..5b02bfc1e7e3 and splice series v6.7..6ae654392bb51 than just 3 individual commits in the middle.

Thanks,
Amir.

Quoted 95 lines

This is needed for fanotify "pre content" events.

Stable-dep-of: 7c98f7cb8fda ("remove call_{read,write}_iter() functions")

fs/cachefiles/io.c +2 -3
index 009d23cd435b5..5857241c59181 100644
@@ -259,7 +259,8 @@ static void cachefiles_write_complete(struct kiocb *iocb, long ret)
 
        _enter("%ld", ret);
 
-       kiocb_end_write(iocb);
+       if (ki->was_async)
+               kiocb_end_write(iocb);
 
        if (ret < 0)
                trace_cachefiles_io_error(object, inode, ret,
@@ -319,8 +320,6 @@ int __cachefiles_write(struct cachefiles_object *object,
                ki->iocb.ki_complete = cachefiles_write_complete;
        atomic_long_add(ki->b_writing, &cache->b_writing);
 
-       kiocb_start_write(&ki->iocb);
-
        get_file(ki->iocb.ki_filp);
        cachefiles_grab_object(object, cachefiles_obj_get_ioreq);
 
fs/overlayfs/file.c +4 -4
index 9fd88579bfbfb..a1c64c2b8e204 100644
@@ -295,10 +295,8 @@ static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req)
        struct kiocb *iocb = &aio_req->iocb;
        struct kiocb *orig_iocb = aio_req->orig_iocb;
 
-       if (iocb->ki_flags & IOCB_WRITE) {
-               kiocb_end_write(iocb);
+       if (iocb->ki_flags & IOCB_WRITE)
                ovl_file_modified(orig_iocb->ki_filp);
-       }
 
        orig_iocb->ki_pos = iocb->ki_pos;
        ovl_aio_put(aio_req);
@@ -310,6 +308,9 @@ static void ovl_aio_rw_complete(struct kiocb *iocb, long res)
                                                   struct ovl_aio_req, iocb);
        struct kiocb *orig_iocb = aio_req->orig_iocb;
 
+       if (iocb->ki_flags & IOCB_WRITE)
+               kiocb_end_write(iocb);
+
        ovl_aio_cleanup_handler(aio_req);
        orig_iocb->ki_complete(orig_iocb, res);
 }
@@ -421,7 +422,6 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
                aio_req->iocb.ki_flags = ifl;
                aio_req->iocb.ki_complete = ovl_aio_rw_complete;
                refcount_set(&aio_req->ref, 2);
-               kiocb_start_write(&aio_req->iocb);
                ret = vfs_iocb_iter_write(real.file, &aio_req->iocb, iter);
                ovl_aio_put(aio_req);
                if (ret != -EIOCBQUEUED)
fs/read_write.c +7 -0
index 4771701c896ba..9a56949f3b8d1 100644
@@ -865,6 +865,10 @@ static ssize_t do_iter_write(struct file *file, struct iov_iter *iter,
        return ret;
 }
 
+/*
+ * Caller is responsible for calling kiocb_end_write() on completion
+ * if async iocb was queued.
+ */
 ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb,
                            struct iov_iter *iter)
 {
@@ -885,7 +889,10 @@ ssize_t vfs_iocb_iter_write(struct file *file, struct kiocb *iocb,
        if (ret < 0)
                return ret;
 
+       kiocb_start_write(iocb);
        ret = call_write_iter(file, iocb, iter);
+       if (ret != -EIOCBQUEUED)
+               kiocb_end_write(iocb);
        if (ret > 0)
                fsnotify_modify(file);