mirror of
https://github.com/torvalds/linux
synced 2024-09-21 11:38:48 +00:00
760f991f14
For subpage case, we need to allocate additional memory for each metadata page. So we need to: - Allow attach_extent_buffer_page() to return int to indicate allocation failure - Allow manually pre-allocate subpage memory for alloc_extent_buffer() As we don't want to use GFP_ATOMIC under spinlock, we introduce btrfs_alloc_subpage() and btrfs_free_subpage() functions for this purpose. (The simple wrap for btrfs_free_subpage() is for later convert to kmem_cache. Already internally tested without problem) - Preallocate btrfs_subpage structure for alloc_extent_buffer() We don't want to call memory allocation with spinlock held, so do preallocation before we acquire mapping->private_lock. - Handle subpage and regular case differently in attach_extent_buffer_page() For regular case, no change, just do the usual thing. For subpage case, allocate new memory or use the preallocated memory. For future subpage metadata, we will make use of radix tree to grab extent buffer. Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
44 lines
1.1 KiB
C
44 lines
1.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
#ifndef BTRFS_SUBPAGE_H
|
|
#define BTRFS_SUBPAGE_H
|
|
|
|
#include <linux/spinlock.h>
|
|
|
|
/*
|
|
* Maximum page size we support is 64K, minimum sector size is 4K, u16 bitmap
|
|
* is sufficient. Regular bitmap_* is not used due to size reasons.
|
|
*/
|
|
#define BTRFS_SUBPAGE_BITMAP_SIZE 16
|
|
|
|
/*
|
|
* Structure to trace status of each sector inside a page, attached to
|
|
* page::private for both data and metadata inodes.
|
|
*/
|
|
struct btrfs_subpage {
|
|
/* Common members for both data and metadata pages */
|
|
spinlock_t lock;
|
|
union {
|
|
/* Structures only used by metadata */
|
|
/* Structures only used by data */
|
|
};
|
|
};
|
|
|
|
enum btrfs_subpage_type {
|
|
BTRFS_SUBPAGE_METADATA,
|
|
BTRFS_SUBPAGE_DATA,
|
|
};
|
|
|
|
int btrfs_attach_subpage(const struct btrfs_fs_info *fs_info,
|
|
struct page *page, enum btrfs_subpage_type type);
|
|
void btrfs_detach_subpage(const struct btrfs_fs_info *fs_info,
|
|
struct page *page);
|
|
|
|
/* Allocate additional data where page represents more than one sector */
|
|
int btrfs_alloc_subpage(const struct btrfs_fs_info *fs_info,
|
|
struct btrfs_subpage **ret,
|
|
enum btrfs_subpage_type type);
|
|
void btrfs_free_subpage(struct btrfs_subpage *subpage);
|
|
|
|
#endif
|