All of lore.kernel.org
 help / color / mirror / Atom feed
* [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

* [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

* 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

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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.