* [PATCH 0/3] ext4: Handle different max offsets for bitmap & extent-based files
@ 2007-12-04 15:55 Eric Sandeen
2007-12-04 15:58 ` [PATCH 1/3] ext4: different maxbytes functions for bitmap & extent files Eric Sandeen
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Eric Sandeen @ 2007-12-04 15:55 UTC (permalink / raw)
To: ext4 development
Basic approach: have both ext4_max_bitmap_size() and ext4_max_size()
functions to compute max offsets for both types of formats.
Use vfs sb->s_maxbytes for the "native" maxbytes, i.e. extent-format files.
Put the smaller bitmap limit in a new sbi->s_bitmap_maxbytes in the ext4
superblock info structure.
Catch bitmap files in ext4_file_write() and ext4_setattr() to limit
extending writes, llseeks, and truncates to too-large offsets which the
VFS let through due to the extent-format maxbytes. On write, allow
writes up to the max, but then stop, by using iov_shorten() to limit the
size of the write to the maximum.
3 patches follow:
ext4_two_maxbytes_functions.patch - differentiate the maxbytes f'ns
ext4_bitmap_maxbytes_vfs.patch - export iov_shorten from kernel
ext4_bitmap_maxbytes.patch - store, and limit to, bitmap_maxbytes
Comments?
Thanks,
-Eric
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 1/3] ext4: different maxbytes functions for bitmap & extent files 2007-12-04 15:55 [PATCH 0/3] ext4: Handle different max offsets for bitmap & extent-based files Eric Sandeen @ 2007-12-04 15:58 ` Eric Sandeen 2007-12-05 23:18 ` Andreas Dilger 2007-12-04 15:59 ` [PATCH 2/3] ext4: export iov_shorten from kernel for ext4's use Eric Sandeen 2007-12-04 16:00 ` [PATCH 3/3] ext4: store maxbytes for bitmapped files and return EFBIG as appropriate Eric Sandeen 2 siblings, 1 reply; 7+ messages in thread From: Eric Sandeen @ 2007-12-04 15:58 UTC (permalink / raw) To: ext4 development use 2 different maxbytes functions for bitmapped & extent-based files. Signed-off-by: Eric Sandeen <sandeen@redhat.com> --- Index: linux-2.6.24-rc3/fs/ext4/super.c =================================================================== --- linux-2.6.24-rc3.orig/fs/ext4/super.c +++ linux-2.6.24-rc3/fs/ext4/super.c @@ -1656,17 +1656,57 @@ static void ext4_orphan_cleanup (struct } /* - * Maximal file size. There is a direct, and {,double-,triple-}indirect + * Maximal extent format file size. + * Resulting logical blkno at s_maxbytes must fit in our on-disk + * extent format containers, within a sector_t, and within i_blocks + * in the vfs. ext4 inode has 48 bits of i_block in fsblock units, + * so that won't be a limiting factor. + * + * Note, this does *not* consider any metadata overhead for vfs i_blocks. + */ +static loff_t ext4_max_size(int blkbits) +{ + loff_t res; + loff_t upper_limit = MAX_LFS_FILESIZE; + + /* small i_blocks in vfs inode? */ + if (sizeof(blkcnt_t) < sizeof(u64)) { + /* + * CONFIG_LSF is not enabled implies the inode + * i_block represent total blocks in 512 bytes + * 32 == size of vfs inode i_blocks * 8 + */ + upper_limit = (1LL << 32) - 1; + + /* total blocks in file system block size */ + upper_limit >>= (blkbits - 9); + upper_limit <<= blkbits; + } + + /* 32-bit extent-start container, ee_block */ + res = 1LL << 32; + res <<= blkbits; + res -= 1; + + /* Sanity check against vm- & vfs- imposed limits */ + if (res > upper_limit) + res = upper_limit; + + return res; +} + +/* + * Maximal bitmap file size. There is a direct, and {,double-,triple-}indirect * block limit, and also a limit of (248 - 1) 512-byte sectors in i_blocks. * We need to be 1 filesystem block less than the 248 sector limit. */ -static loff_t ext4_max_size(int bits) +static loff_t ext4_max_bitmap_size(int bits) { loff_t res = EXT4_NDIR_BLOCKS; int meta_blocks; loff_t upper_limit; /* This is calculated to be the largest file size for a - * dense, file such that the total number of + * dense, bitmapped file such that the total number of * sectors in the file, including data and all indirect blocks, * does not exceed 248 -1 * __u32 i_blocks_lo and _u16 i_blocks_high representing the ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/3] ext4: different maxbytes functions for bitmap & extent files 2007-12-04 15:58 ` [PATCH 1/3] ext4: different maxbytes functions for bitmap & extent files Eric Sandeen @ 2007-12-05 23:18 ` Andreas Dilger 2007-12-05 23:22 ` Eric Sandeen 0 siblings, 1 reply; 7+ messages in thread From: Andreas Dilger @ 2007-12-05 23:18 UTC (permalink / raw) To: Eric Sandeen; +Cc: ext4 development On Dec 04, 2007 09:58 -0600, Eric Sandeen wrote: > +static loff_t ext4_max_size(int blkbits) > +{ > + loff_t res; > + loff_t upper_limit = MAX_LFS_FILESIZE; > + > + /* small i_blocks in vfs inode? */ > + if (sizeof(blkcnt_t) < sizeof(u64)) { It would probably be more future-proof by having a struct inode here and using "if (sizeof(inode->i_blocks) < sizeof(__u64))". > + upper_limit = (1LL << 32) - 1; > + > + /* total blocks in file system block size */ > + upper_limit >>= (blkbits - 9); > + upper_limit <<= blkbits; There is probably a cleaner way to do this, maybe: upper_limit = (1LL << (32 + 9) - 1) & ~((1 << blkbits) - 1); Cheers, Andreas -- Andreas Dilger Sr. Staff Engineer, Lustre Group Sun Microsystems of Canada, Inc. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/3] ext4: different maxbytes functions for bitmap & extent files 2007-12-05 23:18 ` Andreas Dilger @ 2007-12-05 23:22 ` Eric Sandeen 0 siblings, 0 replies; 7+ messages in thread From: Eric Sandeen @ 2007-12-05 23:22 UTC (permalink / raw) To: Eric Sandeen, ext4 development Andreas Dilger wrote: > On Dec 04, 2007 09:58 -0600, Eric Sandeen wrote: >> +static loff_t ext4_max_size(int blkbits) >> +{ >> + loff_t res; >> + loff_t upper_limit = MAX_LFS_FILESIZE; >> + >> + /* small i_blocks in vfs inode? */ >> + if (sizeof(blkcnt_t) < sizeof(u64)) { > > It would probably be more future-proof by having a struct inode here and > using "if (sizeof(inode->i_blocks) < sizeof(__u64))". Ok. Honestly these were both just lifted from the original max_size function for bitmap files :) -Eric >> + upper_limit = (1LL << 32) - 1; >> + >> + /* total blocks in file system block size */ >> + upper_limit >>= (blkbits - 9); >> + upper_limit <<= blkbits; > > There is probably a cleaner way to do this, maybe: > upper_limit = (1LL << (32 + 9) - 1) & ~((1 << blkbits) - 1); > > Cheers, Andreas > -- > Andreas Dilger > Sr. Staff Engineer, Lustre Group > Sun Microsystems of Canada, Inc. > ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/3] ext4: export iov_shorten from kernel for ext4's use 2007-12-04 15:55 [PATCH 0/3] ext4: Handle different max offsets for bitmap & extent-based files Eric Sandeen 2007-12-04 15:58 ` [PATCH 1/3] ext4: different maxbytes functions for bitmap & extent files Eric Sandeen @ 2007-12-04 15:59 ` Eric Sandeen 2007-12-04 16:00 ` [PATCH 3/3] ext4: store maxbytes for bitmapped files and return EFBIG as appropriate Eric Sandeen 2 siblings, 0 replies; 7+ messages in thread From: Eric Sandeen @ 2007-12-04 15:59 UTC (permalink / raw) To: ext4 development Export iov_shorten() from kernel so that ext4 can truncate too-large writes to bitmapped files. Signed-off-by: Eric Sandeen <sandeen@redhat.com> --- Index: linux-2.6.24-rc3/fs/read_write.c =================================================================== --- linux-2.6.24-rc3.orig/fs/read_write.c +++ linux-2.6.24-rc3/fs/read_write.c @@ -451,6 +451,8 @@ unsigned long iov_shorten(struct iovec * return seg; } +EXPORT_SYMBOL(iov_shorten); + ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov, unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn) { ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/3] ext4: store maxbytes for bitmapped files and return EFBIG as appropriate 2007-12-04 15:55 [PATCH 0/3] ext4: Handle different max offsets for bitmap & extent-based files Eric Sandeen 2007-12-04 15:58 ` [PATCH 1/3] ext4: different maxbytes functions for bitmap & extent files Eric Sandeen 2007-12-04 15:59 ` [PATCH 2/3] ext4: export iov_shorten from kernel for ext4's use Eric Sandeen @ 2007-12-04 16:00 ` Eric Sandeen 2007-12-04 19:31 ` [PATCH 3/3] ext4: (V2) " Eric Sandeen 2 siblings, 1 reply; 7+ messages in thread From: Eric Sandeen @ 2007-12-04 16:00 UTC (permalink / raw) To: ext4 development Calculate & store the max offset for bitmapped files, and catch too-large seeks, truncates, and writes in ext4, shortening or rejecting as appropriate. Signed-off-by: Eric Sandeen <sandeen@redhat.com> --- Index: linux-2.6.24-rc3/fs/ext4/super.c =================================================================== --- linux-2.6.24-rc3.orig/fs/ext4/super.c +++ linux-2.6.24-rc3/fs/ext4/super.c @@ -1979,6 +1979,7 @@ static int ext4_fill_super (struct super } } + sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits); sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits); if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) { Index: linux-2.6.24-rc3/fs/ext4/file.c =================================================================== --- linux-2.6.24-rc3.orig/fs/ext4/file.c +++ linux-2.6.24-rc3/fs/ext4/file.c @@ -56,8 +56,25 @@ ext4_file_write(struct kiocb *iocb, cons ssize_t ret; int err; - ret = generic_file_aio_write(iocb, iov, nr_segs, pos); + /* + * If we have encountered a bitmap-format file, the size limit + * is smaller than s_maxbytes, which is for extent-mapped files. + */ + if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) { + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + size_t length = iov_length(iov, nr_segs); + + if (pos > sbi->s_bitmap_maxbytes) + return -EFBIG; + + if (pos + length > sbi->s_bitmap_maxbytes) { + nr_segs = iov_shorten((struct iovec *)iov, nr_segs, + sbi->s_bitmap_maxbytes - pos); + } + } + + ret = generic_file_aio_write(iocb, iov, nr_segs, pos); /* * Skip flushing if there was an error, or if nothing was written. */ Index: linux-2.6.24-rc3/fs/ext4/inode.c =================================================================== --- linux-2.6.24-rc3.orig/fs/ext4/inode.c +++ linux-2.6.24-rc3/fs/ext4/inode.c @@ -309,7 +309,9 @@ static int ext4_block_to_path(struct ino offsets[n++] = i_block & (ptrs - 1); final = ptrs; } else { - ext4_warning(inode->i_sb, "ext4_block_to_path", "block > big"); + ext4_warning(inode->i_sb, "ext4_block_to_path", "block %u > max", + i_block + direct_blocks + + indirect_blocks + double_blocks); } if (boundary) *boundary = final - 1 - (i_block & (ptrs - 1)); @@ -3212,6 +3214,17 @@ int ext4_setattr(struct dentry *dentry, ext4_journal_stop(handle); } + if (attr->ia_valid & ATTR_SIZE) { + if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) { + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + + if (attr->ia_size > sbi->s_bitmap_maxbytes) { + error = -EFBIG; + goto err_out; + } + } + } + if (S_ISREG(inode->i_mode) && attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) { handle_t *handle; Index: linux-2.6.24-rc3/include/linux/ext4_fs_sb.h =================================================================== --- linux-2.6.24-rc3.orig/include/linux/ext4_fs_sb.h +++ linux-2.6.24-rc3/include/linux/ext4_fs_sb.h @@ -38,6 +38,7 @@ struct ext4_sb_info { ext4_group_t s_groups_count; /* Number of groups in the fs */ unsigned long s_overhead_last; /* Last calculated overhead */ unsigned long s_blocks_last; /* Last seen block count */ + loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */ struct buffer_head * s_sbh; /* Buffer containing the super block */ struct ext4_super_block * s_es; /* Pointer to the super block in the buffer */ struct buffer_head ** s_group_desc; ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 3/3] ext4: (V2) store maxbytes for bitmapped files and return EFBIG as appropriate 2007-12-04 16:00 ` [PATCH 3/3] ext4: store maxbytes for bitmapped files and return EFBIG as appropriate Eric Sandeen @ 2007-12-04 19:31 ` Eric Sandeen 0 siblings, 0 replies; 7+ messages in thread From: Eric Sandeen @ 2007-12-04 19:31 UTC (permalink / raw) To: ext4 development Crud, minor off-by-one in ext4_file_write. V2 below: =============================== Calculate & store the max offset for bitmapped files, and catch too-large seeks, truncates, and writes in ext4, shortening or rejecting as appropriate. Signed-off-by: Eric Sandeen <sandeen@redhat.com> --- Index: linux-2.6.24-rc3/fs/ext4/super.c =================================================================== --- linux-2.6.24-rc3.orig/fs/ext4/super.c +++ linux-2.6.24-rc3/fs/ext4/super.c @@ -1979,6 +1979,7 @@ static int ext4_fill_super (struct super } } + sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits); sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits); if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) { Index: linux-2.6.24-rc3/fs/ext4/file.c =================================================================== --- linux-2.6.24-rc3.orig/fs/ext4/file.c +++ linux-2.6.24-rc3/fs/ext4/file.c @@ -56,8 +56,29 @@ ext4_file_write(struct kiocb *iocb, cons ssize_t ret; int err; - ret = generic_file_aio_write(iocb, iov, nr_segs, pos); + /* + * If we have encountered a bitmap-format file, the size limit + * is smaller than s_maxbytes, which is for extent-mapped files. + */ + if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) { + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + size_t length = iov_length(iov, nr_segs); + + if (pos >= sbi->s_bitmap_maxbytes) { + if (length || pos > sbi->s_bitmap_maxbytes) { + return -EFBIG; + } + /* zero-length writes at maxbytes are OK */ + } + + if (pos + length > sbi->s_bitmap_maxbytes) { + nr_segs = iov_shorten((struct iovec *)iov, nr_segs, + sbi->s_bitmap_maxbytes - pos); + } + } + + ret = generic_file_aio_write(iocb, iov, nr_segs, pos); /* * Skip flushing if there was an error, or if nothing was written. */ Index: linux-2.6.24-rc3/fs/ext4/inode.c =================================================================== --- linux-2.6.24-rc3.orig/fs/ext4/inode.c +++ linux-2.6.24-rc3/fs/ext4/inode.c @@ -309,7 +309,9 @@ static int ext4_block_to_path(struct ino offsets[n++] = i_block & (ptrs - 1); final = ptrs; } else { - ext4_warning(inode->i_sb, "ext4_block_to_path", "block > big"); + ext4_warning(inode->i_sb, "ext4_block_to_path", "block %u > max", + i_block + direct_blocks + + indirect_blocks + double_blocks); } if (boundary) *boundary = final - 1 - (i_block & (ptrs - 1)); @@ -3212,6 +3214,17 @@ int ext4_setattr(struct dentry *dentry, ext4_journal_stop(handle); } + if (attr->ia_valid & ATTR_SIZE) { + if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) { + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + + if (attr->ia_size > sbi->s_bitmap_maxbytes) { + error = -EFBIG; + goto err_out; + } + } + } + if (S_ISREG(inode->i_mode) && attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) { handle_t *handle; Index: linux-2.6.24-rc3/include/linux/ext4_fs_sb.h =================================================================== --- linux-2.6.24-rc3.orig/include/linux/ext4_fs_sb.h +++ linux-2.6.24-rc3/include/linux/ext4_fs_sb.h @@ -38,6 +38,7 @@ struct ext4_sb_info { ext4_group_t s_groups_count; /* Number of groups in the fs */ unsigned long s_overhead_last; /* Last calculated overhead */ unsigned long s_blocks_last; /* Last seen block count */ + loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */ struct buffer_head * s_sbh; /* Buffer containing the super block */ struct ext4_super_block * s_es; /* Pointer to the super block in the buffer */ struct buffer_head ** s_group_desc; ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2007-12-05 23:22 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-12-04 15:55 [PATCH 0/3] ext4: Handle different max offsets for bitmap & extent-based files Eric Sandeen 2007-12-04 15:58 ` [PATCH 1/3] ext4: different maxbytes functions for bitmap & extent files Eric Sandeen 2007-12-05 23:18 ` Andreas Dilger 2007-12-05 23:22 ` Eric Sandeen 2007-12-04 15:59 ` [PATCH 2/3] ext4: export iov_shorten from kernel for ext4's use Eric Sandeen 2007-12-04 16:00 ` [PATCH 3/3] ext4: store maxbytes for bitmapped files and return EFBIG as appropriate Eric Sandeen 2007-12-04 19:31 ` [PATCH 3/3] ext4: (V2) " Eric Sandeen
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).