Commit 2775df6e authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'vfs-6.12.folio' of gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs

Pull vfs folio updates from Christian Brauner:
 "This contains work to port write_begin and write_end to rely on folios
  for various filesystems.

  This converts ocfs2, vboxfs, orangefs, jffs2, hostfs, fuse, f2fs,
  ecryptfs, ntfs3, nilfs2, reiserfs, minixfs, qnx6, sysv, ufs, and
  squashfs.

  After this series lands a bunch of the filesystems in this list do not
  mention struct page anymore"

* tag 'vfs-6.12.folio' of gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs: (61 commits)
  Squashfs: Ensure all readahead pages have been used
  Squashfs: Rewrite and update squashfs_readahead_fragment() to not use page->index
  Squashfs: Update squashfs_readpage_block() to not use page->index
  Squashfs: Update squashfs_readahead() to not use page->index
  Squashfs: Update page_actor to not use page->index
  jffs2: Use a folio in jffs2_garbage_collect_dnode()
  jffs2: Convert jffs2_do_readpage_nolock to take a folio
  buffer: Convert __block_write_begin() to take a folio
  ocfs2: Convert ocfs2_write_zero_page to use a folio
  fs: Convert aops->write_begin to take a folio
  fs: Convert aops->write_end to take a folio
  vboxsf: Use a folio in vboxsf_write_end()
  orangefs: Convert orangefs_write_begin() to use a folio
  orangefs: Convert orangefs_write_end() to use a folio
  jffs2: Convert jffs2_write_begin() to use a folio
  jffs2: Convert jffs2_write_end() to use a folio
  hostfs: Convert hostfs_write_end() to use a folio
  fuse: Convert fuse_write_begin() to use a folio
  fuse: Convert fuse_write_end() to use a folio
  f2fs: Convert f2fs_write_begin() to use a folio
  ...
parents 8f72c31f 84e0e03b
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -251,10 +251,10 @@ prototypes::
	void (*readahead)(struct readahead_control *);
	int (*write_begin)(struct file *, struct address_space *mapping,
				loff_t pos, unsigned len,
				struct page **pagep, void **fsdata);
				struct folio **foliop, void **fsdata);
	int (*write_end)(struct file *, struct address_space *mapping,
				loff_t pos, unsigned len, unsigned copied,
				struct page *page, void *fsdata);
				struct folio *folio, void *fsdata);
	sector_t (*bmap)(struct address_space *, sector_t);
	void (*invalidate_folio) (struct folio *, size_t start, size_t len);
	bool (*release_folio)(struct folio *, gfp_t);
@@ -280,7 +280,7 @@ read_folio: yes, unlocks shared
writepages:
dirty_folio:		maybe
readahead:		yes, unlocks				shared
write_begin:		locks the page		 exclusive
write_begin:		locks the folio		 exclusive
write_end:		yes, unlocks		 exclusive
bmap:
invalidate_folio:	yes					exclusive
+6 −6
Original line number Diff line number Diff line
@@ -810,7 +810,7 @@ cache in your filesystem. The following members are defined:
				struct page **pagep, void **fsdata);
		int (*write_end)(struct file *, struct address_space *mapping,
				 loff_t pos, unsigned len, unsigned copied,
				 struct page *page, void *fsdata);
				 struct folio *folio, void *fsdata);
		sector_t (*bmap)(struct address_space *, sector_t);
		void (*invalidate_folio) (struct folio *, size_t start, size_t len);
		bool (*release_folio)(struct folio *, gfp_t);
@@ -926,12 +926,12 @@ cache in your filesystem. The following members are defined:
	(if they haven't been read already) so that the updated blocks
	can be written out properly.

	The filesystem must return the locked pagecache page for the
	specified offset, in ``*pagep``, for the caller to write into.
	The filesystem must return the locked pagecache folio for the
	specified offset, in ``*foliop``, for the caller to write into.

	It must be able to cope with short writes (where the length
	passed to write_begin is greater than the number of bytes copied
	into the page).
	into the folio).

	A void * may be returned in fsdata, which then gets passed into
	write_end.
@@ -944,8 +944,8 @@ cache in your filesystem. The following members are defined:
	called.  len is the original len passed to write_begin, and
	copied is the amount that was able to be copied.

	The filesystem must take care of unlocking the page and
	releasing it refcount, and updating i_size.
	The filesystem must take care of unlocking the folio,
	decrementing its refcount, and updating i_size.

	Returns < 0 on failure, otherwise the number of bytes (<=
	'copied') that were able to be copied into pagecache.
+6 −6
Original line number Diff line number Diff line
@@ -451,20 +451,20 @@ static void blkdev_readahead(struct readahead_control *rac)
}

static int blkdev_write_begin(struct file *file, struct address_space *mapping,
		loff_t pos, unsigned len, struct page **pagep, void **fsdata)
		loff_t pos, unsigned len, struct folio **foliop, void **fsdata)
{
	return block_write_begin(mapping, pos, len, pagep, blkdev_get_block);
	return block_write_begin(mapping, pos, len, foliop, blkdev_get_block);
}

static int blkdev_write_end(struct file *file, struct address_space *mapping,
		loff_t pos, unsigned len, unsigned copied, struct page *page,
		loff_t pos, unsigned len, unsigned copied, struct folio *folio,
		void *fsdata)
{
	int ret;
	ret = block_write_end(file, mapping, pos, len, copied, page, fsdata);
	ret = block_write_end(file, mapping, pos, len, copied, folio, fsdata);

	unlock_page(page);
	put_page(page);
	folio_unlock(folio);
	folio_put(folio);

	return ret;
}
+22 −25
Original line number Diff line number Diff line
@@ -424,7 +424,8 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
	struct address_space *mapping = obj->base.filp->f_mapping;
	const struct address_space_operations *aops = mapping->a_ops;
	char __user *user_data = u64_to_user_ptr(arg->data_ptr);
	u64 remain, offset;
	u64 remain;
	loff_t pos;
	unsigned int pg;

	/* Caller already validated user args */
@@ -457,12 +458,12 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
	 */

	remain = arg->size;
	offset = arg->offset;
	pg = offset_in_page(offset);
	pos = arg->offset;
	pg = offset_in_page(pos);

	do {
		unsigned int len, unwritten;
		struct page *page;
		struct folio *folio;
		void *data, *vaddr;
		int err;
		char __maybe_unused c;
@@ -480,21 +481,19 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
		if (err)
			return err;

		err = aops->write_begin(obj->base.filp, mapping, offset, len,
					&page, &data);
		err = aops->write_begin(obj->base.filp, mapping, pos, len,
					&folio, &data);
		if (err < 0)
			return err;

		vaddr = kmap_local_page(page);
		vaddr = kmap_local_folio(folio, offset_in_folio(folio, pos));
		pagefault_disable();
		unwritten = __copy_from_user_inatomic(vaddr + pg,
						      user_data,
						      len);
		unwritten = __copy_from_user_inatomic(vaddr, user_data, len);
		pagefault_enable();
		kunmap_local(vaddr);

		err = aops->write_end(obj->base.filp, mapping, offset, len,
				      len - unwritten, page, data);
		err = aops->write_end(obj->base.filp, mapping, pos, len,
				      len - unwritten, folio, data);
		if (err < 0)
			return err;

@@ -504,7 +503,7 @@ shmem_pwrite(struct drm_i915_gem_object *obj,

		remain -= len;
		user_data += len;
		offset += len;
		pos += len;
		pg = 0;
	} while (remain);

@@ -660,7 +659,7 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *i915,
	struct drm_i915_gem_object *obj;
	struct file *file;
	const struct address_space_operations *aops;
	resource_size_t offset;
	loff_t pos;
	int err;

	GEM_WARN_ON(IS_DGFX(i915));
@@ -672,29 +671,27 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *i915,

	file = obj->base.filp;
	aops = file->f_mapping->a_ops;
	offset = 0;
	pos = 0;
	do {
		unsigned int len = min_t(typeof(size), size, PAGE_SIZE);
		struct page *page;
		void *pgdata, *vaddr;
		struct folio *folio;
		void *fsdata;

		err = aops->write_begin(file, file->f_mapping, offset, len,
					&page, &pgdata);
		err = aops->write_begin(file, file->f_mapping, pos, len,
					&folio, &fsdata);
		if (err < 0)
			goto fail;

		vaddr = kmap(page);
		memcpy(vaddr, data, len);
		kunmap(page);
		memcpy_to_folio(folio, offset_in_folio(folio, pos), data, len);

		err = aops->write_end(file, file->f_mapping, offset, len, len,
				      page, pgdata);
		err = aops->write_end(file, file->f_mapping, pos, len, len,
				      folio, fsdata);
		if (err < 0)
			goto fail;

		size -= len;
		data += len;
		offset += len;
		pos += len;
	} while (size);

	return obj;
+2 −3
Original line number Diff line number Diff line
@@ -55,12 +55,11 @@ static void adfs_write_failed(struct address_space *mapping, loff_t to)

static int adfs_write_begin(struct file *file, struct address_space *mapping,
			loff_t pos, unsigned len,
			struct page **pagep, void **fsdata)
			struct folio **foliop, void **fsdata)
{
	int ret;

	*pagep = NULL;
	ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata,
	ret = cont_write_begin(file, mapping, pos, len, foliop, fsdata,
				adfs_get_block,
				&ADFS_I(mapping->host)->mmu_private);
	if (unlikely(ret))
Loading