// SPDX-License-Identifier: GPL-2.0-only
/*
 * Complete scope from Linux v6.18 fs/buffer.c.
 * Source: https://github.com/torvalds/linux/blob/v6.18/fs/buffer.c
 * Copyright (C) 1991, 1992, 2002  Linus Torvalds
 * Kernel excerpt; not a standalone program.
 * The book's exact source tag is not asserted.
 */

int block_write_end(loff_t pos, unsigned len, unsigned copied,
		struct folio *folio)
{
	size_t start = pos - folio_pos(folio);

	if (unlikely(copied < len)) {
		/*
		 * The buffers that were written will now be uptodate, so
		 * we don't have to worry about a read_folio reading them
		 * and overwriting a partial write. However if we have
		 * encountered a short write and only partially written
		 * into a buffer, it will not be marked uptodate, so a
		 * read_folio might come in and destroy our partial write.
		 *
		 * Do the simplest thing, and just treat any short write to a
		 * non uptodate folio as a zero-length write, and force the
		 * caller to redo the whole thing.
		 */
		if (!folio_test_uptodate(folio))
			copied = 0;

		folio_zero_new_buffers(folio, start+copied, start+len);
	}
	flush_dcache_folio(folio);

	/* This could be a short (even 0-length) commit */
	block_commit_write(folio, start, start + copied);

	return copied;
}
