Skip to content

Commit

Permalink
Merge branch 'vfs.blocksize' into vfs.all
Browse files Browse the repository at this point in the history
Signed-off-by: Christian Brauner <[email protected]>
  • Loading branch information
brauner committed Aug 24, 2024
2 parents 8e52f98 + 9b0ebbc commit 2396dcd
Show file tree
Hide file tree
Showing 14 changed files with 347 additions and 85 deletions.
4 changes: 2 additions & 2 deletions fs/iomap/buffered-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -2007,10 +2007,10 @@ iomap_writepages(struct address_space *mapping, struct writeback_control *wbc,
}
EXPORT_SYMBOL_GPL(iomap_writepages);

static int __init iomap_init(void)
static int __init iomap_buffered_init(void)
{
return bioset_init(&iomap_ioend_bioset, 4 * (PAGE_SIZE / SECTOR_SIZE),
offsetof(struct iomap_ioend, io_bio),
BIOSET_NEED_BVECS);
}
fs_initcall(iomap_init);
fs_initcall(iomap_buffered_init);
45 changes: 39 additions & 6 deletions fs/iomap/direct-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/iomap.h>
#include <linux/backing-dev.h>
#include <linux/uio.h>
#include <linux/set_memory.h>
#include <linux/task_io_accounting_ops.h>
#include "trace.h"

Expand All @@ -27,6 +28,13 @@
#define IOMAP_DIO_WRITE (1U << 30)
#define IOMAP_DIO_DIRTY (1U << 31)

/*
* Used for sub block zeroing in iomap_dio_zero()
*/
#define IOMAP_ZERO_PAGE_SIZE (SZ_64K)
#define IOMAP_ZERO_PAGE_ORDER (get_order(IOMAP_ZERO_PAGE_SIZE))
static struct page *zero_page;

struct iomap_dio {
struct kiocb *iocb;
const struct iomap_dio_ops *dops;
Expand Down Expand Up @@ -232,22 +240,30 @@ void iomap_dio_bio_end_io(struct bio *bio)
}
EXPORT_SYMBOL_GPL(iomap_dio_bio_end_io);

static void iomap_dio_zero(const struct iomap_iter *iter, struct iomap_dio *dio,
static int iomap_dio_zero(const struct iomap_iter *iter, struct iomap_dio *dio,
loff_t pos, unsigned len)
{
struct inode *inode = file_inode(dio->iocb->ki_filp);
struct page *page = ZERO_PAGE(0);
struct bio *bio;

if (!len)
return 0;
/*
* Max block size supported is 64k
*/
if (WARN_ON_ONCE(len > IOMAP_ZERO_PAGE_SIZE))
return -EINVAL;

bio = iomap_dio_alloc_bio(iter, dio, 1, REQ_OP_WRITE | REQ_SYNC | REQ_IDLE);
fscrypt_set_bio_crypt_ctx(bio, inode, pos >> inode->i_blkbits,
GFP_KERNEL);
bio->bi_iter.bi_sector = iomap_sector(&iter->iomap, pos);
bio->bi_private = dio;
bio->bi_end_io = iomap_dio_bio_end_io;

__bio_add_page(bio, page, len, 0);
__bio_add_page(bio, zero_page, len, 0);
iomap_dio_submit_bio(iter, dio, bio, pos);
return 0;
}

/*
Expand Down Expand Up @@ -356,8 +372,10 @@ static loff_t iomap_dio_bio_iter(const struct iomap_iter *iter,
if (need_zeroout) {
/* zero out from the start of the block to the write offset */
pad = pos & (fs_block_size - 1);
if (pad)
iomap_dio_zero(iter, dio, pos - pad, pad);

ret = iomap_dio_zero(iter, dio, pos - pad, pad);
if (ret)
goto out;
}

/*
Expand Down Expand Up @@ -431,7 +449,8 @@ static loff_t iomap_dio_bio_iter(const struct iomap_iter *iter,
/* zero out from the end of the write to the end of the block */
pad = pos & (fs_block_size - 1);
if (pad)
iomap_dio_zero(iter, dio, pos, fs_block_size - pad);
ret = iomap_dio_zero(iter, dio, pos,
fs_block_size - pad);
}
out:
/* Undo iter limitation to current extent */
Expand Down Expand Up @@ -753,3 +772,17 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
return iomap_dio_complete(dio);
}
EXPORT_SYMBOL_GPL(iomap_dio_rw);

static int __init iomap_dio_init(void)
{
zero_page = alloc_pages(GFP_KERNEL | __GFP_ZERO,
IOMAP_ZERO_PAGE_ORDER);

if (!zero_page)
return -ENOMEM;

set_memory_ro((unsigned long)page_address(zero_page),
1U << IOMAP_ZERO_PAGE_ORDER);
return 0;
}
fs_initcall(iomap_dio_init);
15 changes: 6 additions & 9 deletions fs/xfs/libxfs/xfs_attr_leaf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1138,10 +1138,7 @@ xfs_attr3_leaf_to_shortform(

trace_xfs_attr_leaf_to_sf(args);

tmpbuffer = kmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL);
if (!tmpbuffer)
return -ENOMEM;

tmpbuffer = kvmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL);
memcpy(tmpbuffer, bp->b_addr, args->geo->blksize);

leaf = (xfs_attr_leafblock_t *)tmpbuffer;
Expand Down Expand Up @@ -1205,7 +1202,7 @@ xfs_attr3_leaf_to_shortform(
error = 0;

out:
kfree(tmpbuffer);
kvfree(tmpbuffer);
return error;
}

Expand Down Expand Up @@ -1613,7 +1610,7 @@ xfs_attr3_leaf_compact(

trace_xfs_attr_leaf_compact(args);

tmpbuffer = kmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL);
tmpbuffer = kvmalloc(args->geo->blksize, GFP_KERNEL | __GFP_NOFAIL);
memcpy(tmpbuffer, bp->b_addr, args->geo->blksize);
memset(bp->b_addr, 0, args->geo->blksize);
leaf_src = (xfs_attr_leafblock_t *)tmpbuffer;
Expand Down Expand Up @@ -1651,7 +1648,7 @@ xfs_attr3_leaf_compact(
*/
xfs_trans_log_buf(trans, bp, 0, args->geo->blksize - 1);

kfree(tmpbuffer);
kvfree(tmpbuffer);
}

/*
Expand Down Expand Up @@ -2330,7 +2327,7 @@ xfs_attr3_leaf_unbalance(
struct xfs_attr_leafblock *tmp_leaf;
struct xfs_attr3_icleaf_hdr tmphdr;

tmp_leaf = kzalloc(state->args->geo->blksize,
tmp_leaf = kvzalloc(state->args->geo->blksize,
GFP_KERNEL | __GFP_NOFAIL);

/*
Expand Down Expand Up @@ -2371,7 +2368,7 @@ xfs_attr3_leaf_unbalance(
}
memcpy(save_leaf, tmp_leaf, state->args->geo->blksize);
savehdr = tmphdr; /* struct copy */
kfree(tmp_leaf);
kvfree(tmp_leaf);
}

xfs_attr3_leaf_hdr_to_disk(state->args->geo, save_leaf, &savehdr);
Expand Down
5 changes: 5 additions & 0 deletions fs/xfs/libxfs/xfs_ialloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -3033,6 +3033,11 @@ xfs_ialloc_setup_geometry(
igeo->ialloc_align = mp->m_dalign;
else
igeo->ialloc_align = 0;

if (mp->m_sb.sb_blocksize > PAGE_SIZE)
igeo->min_folio_order = mp->m_sb.sb_blocklog - PAGE_SHIFT;
else
igeo->min_folio_order = 0;
}

/* Compute the location of the root directory inode that is laid out by mkfs. */
Expand Down
3 changes: 3 additions & 0 deletions fs/xfs/libxfs/xfs_shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,9 @@ struct xfs_ino_geometry {
/* precomputed value for di_flags2 */
uint64_t new_diflags2;

/* minimum folio order of a page cache allocation */
unsigned int min_folio_order;

};

#endif /* __XFS_SHARED_H__ */
6 changes: 4 additions & 2 deletions fs/xfs/xfs_icache.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ xfs_inode_alloc(

/* VFS doesn't initialise i_mode! */
VFS_I(ip)->i_mode = 0;
mapping_set_large_folios(VFS_I(ip)->i_mapping);
mapping_set_folio_min_order(VFS_I(ip)->i_mapping,
M_IGEO(mp)->min_folio_order);

XFS_STATS_INC(mp, vn_active);
ASSERT(atomic_read(&ip->i_pincount) == 0);
Expand Down Expand Up @@ -325,7 +326,8 @@ xfs_reinit_inode(
inode->i_uid = uid;
inode->i_gid = gid;
inode->i_state = state;
mapping_set_large_folios(inode->i_mapping);
mapping_set_folio_min_order(inode->i_mapping,
M_IGEO(mp)->min_folio_order);
return error;
}

Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/xfs_iops.c
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ xfs_stat_blksize(
return 1U << mp->m_allocsize_log;
}

return PAGE_SIZE;
return max_t(uint32_t, PAGE_SIZE, mp->m_sb.sb_blocksize);
}

STATIC int
Expand Down
8 changes: 6 additions & 2 deletions fs/xfs/xfs_mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,15 @@ xfs_sb_validate_fsb_count(
xfs_sb_t *sbp,
uint64_t nblocks)
{
ASSERT(PAGE_SHIFT >= sbp->sb_blocklog);
uint64_t max_bytes;

ASSERT(sbp->sb_blocklog >= BBSHIFT);

if (check_shl_overflow(nblocks, sbp->sb_blocklog, &max_bytes))
return -EFBIG;

/* Limited by ULONG_MAX of page cache index */
if (nblocks >> (PAGE_SHIFT - sbp->sb_blocklog) > ULONG_MAX)
if (max_bytes >> PAGE_SHIFT > ULONG_MAX)
return -EFBIG;
return 0;
}
Expand Down
28 changes: 20 additions & 8 deletions fs/xfs/xfs_super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1638,16 +1638,28 @@ xfs_fs_fill_super(
goto out_free_sb;
}

/*
* Until this is fixed only page-sized or smaller data blocks work.
*/
if (mp->m_sb.sb_blocksize > PAGE_SIZE) {
xfs_warn(mp,
"File system with blocksize %d bytes. "
"Only pagesize (%ld) or less will currently work.",
size_t max_folio_size = mapping_max_folio_size_supported();

if (!xfs_has_crc(mp)) {
xfs_warn(mp,
"V4 Filesystem with blocksize %d bytes. Only pagesize (%ld) or less is supported.",
mp->m_sb.sb_blocksize, PAGE_SIZE);
error = -ENOSYS;
goto out_free_sb;
error = -ENOSYS;
goto out_free_sb;
}

if (mp->m_sb.sb_blocksize > max_folio_size) {
xfs_warn(mp,
"block size (%u bytes) not supported; Only block size (%ld) or less is supported",
mp->m_sb.sb_blocksize, max_folio_size);
error = -ENOSYS;
goto out_free_sb;
}

xfs_warn(mp,
"EXPERIMENTAL: V5 Filesystem with Large Block Size (%d bytes) enabled.",
mp->m_sb.sb_blocksize);
}

/* Ensure this filesystem fits in the page cache limits */
Expand Down
14 changes: 10 additions & 4 deletions include/linux/huge_mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ extern struct kobj_attribute thpsize_shmem_enabled_attr;
#define thp_vma_allowable_order(vma, vm_flags, tva_flags, order) \
(!!thp_vma_allowable_orders(vma, vm_flags, tva_flags, BIT(order)))

#define split_folio(f) split_folio_to_list(f, NULL)

#ifdef CONFIG_PGTABLE_HAS_HUGE_LEAVES
#define HPAGE_PMD_SHIFT PMD_SHIFT
#define HPAGE_PUD_SHIFT PUD_SHIFT
Expand Down Expand Up @@ -317,9 +319,10 @@ unsigned long thp_get_unmapped_area_vmflags(struct file *filp, unsigned long add
bool can_split_folio(struct folio *folio, int *pextra_pins);
int split_huge_page_to_list_to_order(struct page *page, struct list_head *list,
unsigned int new_order);
int split_folio_to_list(struct folio *folio, struct list_head *list);
static inline int split_huge_page(struct page *page)
{
return split_huge_page_to_list_to_order(page, NULL, 0);
return split_folio(page_folio(page));
}
void deferred_split_folio(struct folio *folio);

Expand Down Expand Up @@ -484,6 +487,12 @@ static inline int split_huge_page(struct page *page)
{
return 0;
}

static inline int split_folio_to_list(struct folio *folio, struct list_head *list)
{
return 0;
}

static inline void deferred_split_folio(struct folio *folio) {}
#define split_huge_pmd(__vma, __pmd, __address) \
do { } while (0)
Expand Down Expand Up @@ -598,7 +607,4 @@ static inline int split_folio_to_order(struct folio *folio, int new_order)
return split_folio_to_list_to_order(folio, NULL, new_order);
}

#define split_folio_to_list(f, l) split_folio_to_list_to_order(f, l, 0)
#define split_folio(f) split_folio_to_order(f, 0)

#endif /* _LINUX_HUGE_MM_H */
Loading

0 comments on commit 2396dcd

Please sign in to comment.