diff options
author | Theodore Ts'o <tytso@mit.edu> | 2011-09-09 18:36:51 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2011-09-09 18:36:51 -0400 |
commit | bab08ab9646288f1b0b72a7aaeecdff94bd62c18 (patch) | |
tree | e301377f1ce9093a44b2cfb331439e15d79789ed /fs/ext4 | |
parent | 281b59959707dfae03ce038cdf231bf4904e170c (diff) |
ext4: enforce bigalloc restrictions (e.g., no online resizing, etc.)
At least initially if the bigalloc feature is enabled, we will not
support non-extent mapped inodes, online resizing, online defrag, or
the FITRIM ioctl. This simplifies the initial implementation.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/indirect.c | 7 | ||||
-rw-r--r-- | fs/ext4/inode.c | 5 | ||||
-rw-r--r-- | fs/ext4/ioctl.c | 33 | ||||
-rw-r--r-- | fs/ext4/super.c | 7 |
4 files changed, 48 insertions, 4 deletions
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index ea704dff8669..3cfc73fbca8e 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c | |||
@@ -699,6 +699,13 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, | |||
699 | /* | 699 | /* |
700 | * Okay, we need to do block allocation. | 700 | * Okay, we need to do block allocation. |
701 | */ | 701 | */ |
702 | if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, | ||
703 | EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { | ||
704 | EXT4_ERROR_INODE(inode, "Can't allocate blocks for " | ||
705 | "non-extent mapped inodes with bigalloc"); | ||
706 | return -ENOSPC; | ||
707 | } | ||
708 | |||
702 | goal = ext4_find_goal(inode, map->m_lblk, partial); | 709 | goal = ext4_find_goal(inode, map->m_lblk, partial); |
703 | 710 | ||
704 | /* the number of blocks need to allocate for [d,t]indirect blocks */ | 711 | /* the number of blocks need to allocate for [d,t]indirect blocks */ |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 6ecc93979e48..904a9a623dab 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -3358,6 +3358,11 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length) | |||
3358 | return -ENOTSUPP; | 3358 | return -ENOTSUPP; |
3359 | } | 3359 | } |
3360 | 3360 | ||
3361 | if (EXT4_SB(inode->i_sb)->s_cluster_ratio > 1) { | ||
3362 | /* TODO: Add support for bigalloc file systems */ | ||
3363 | return -ENOTSUPP; | ||
3364 | } | ||
3365 | |||
3361 | return ext4_ext_punch_hole(file, offset, length); | 3366 | return ext4_ext_punch_hole(file, offset, length); |
3362 | } | 3367 | } |
3363 | 3368 | ||
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index f18bfe37aff8..2046d699b4a7 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
@@ -21,6 +21,7 @@ | |||
21 | long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 21 | long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
22 | { | 22 | { |
23 | struct inode *inode = filp->f_dentry->d_inode; | 23 | struct inode *inode = filp->f_dentry->d_inode; |
24 | struct super_block *sb = inode->i_sb; | ||
24 | struct ext4_inode_info *ei = EXT4_I(inode); | 25 | struct ext4_inode_info *ei = EXT4_I(inode); |
25 | unsigned int flags; | 26 | unsigned int flags; |
26 | 27 | ||
@@ -183,7 +184,6 @@ setversion_out: | |||
183 | * Returns 1 if it slept, else zero. | 184 | * Returns 1 if it slept, else zero. |
184 | */ | 185 | */ |
185 | { | 186 | { |
186 | struct super_block *sb = inode->i_sb; | ||
187 | DECLARE_WAITQUEUE(wait, current); | 187 | DECLARE_WAITQUEUE(wait, current); |
188 | int ret = 0; | 188 | int ret = 0; |
189 | 189 | ||
@@ -199,7 +199,6 @@ setversion_out: | |||
199 | #endif | 199 | #endif |
200 | case EXT4_IOC_GROUP_EXTEND: { | 200 | case EXT4_IOC_GROUP_EXTEND: { |
201 | ext4_fsblk_t n_blocks_count; | 201 | ext4_fsblk_t n_blocks_count; |
202 | struct super_block *sb = inode->i_sb; | ||
203 | int err, err2=0; | 202 | int err, err2=0; |
204 | 203 | ||
205 | err = ext4_resize_begin(sb); | 204 | err = ext4_resize_begin(sb); |
@@ -209,6 +208,13 @@ setversion_out: | |||
209 | if (get_user(n_blocks_count, (__u32 __user *)arg)) | 208 | if (get_user(n_blocks_count, (__u32 __user *)arg)) |
210 | return -EFAULT; | 209 | return -EFAULT; |
211 | 210 | ||
211 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | ||
212 | EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { | ||
213 | ext4_msg(sb, KERN_ERR, | ||
214 | "Online resizing not supported with bigalloc"); | ||
215 | return -EOPNOTSUPP; | ||
216 | } | ||
217 | |||
212 | err = mnt_want_write(filp->f_path.mnt); | 218 | err = mnt_want_write(filp->f_path.mnt); |
213 | if (err) | 219 | if (err) |
214 | return err; | 220 | return err; |
@@ -250,6 +256,13 @@ setversion_out: | |||
250 | goto mext_out; | 256 | goto mext_out; |
251 | } | 257 | } |
252 | 258 | ||
259 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | ||
260 | EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { | ||
261 | ext4_msg(sb, KERN_ERR, | ||
262 | "Online defrag not supported with bigalloc"); | ||
263 | return -EOPNOTSUPP; | ||
264 | } | ||
265 | |||
253 | err = mnt_want_write(filp->f_path.mnt); | 266 | err = mnt_want_write(filp->f_path.mnt); |
254 | if (err) | 267 | if (err) |
255 | goto mext_out; | 268 | goto mext_out; |
@@ -270,7 +283,6 @@ mext_out: | |||
270 | 283 | ||
271 | case EXT4_IOC_GROUP_ADD: { | 284 | case EXT4_IOC_GROUP_ADD: { |
272 | struct ext4_new_group_data input; | 285 | struct ext4_new_group_data input; |
273 | struct super_block *sb = inode->i_sb; | ||
274 | int err, err2=0; | 286 | int err, err2=0; |
275 | 287 | ||
276 | err = ext4_resize_begin(sb); | 288 | err = ext4_resize_begin(sb); |
@@ -281,6 +293,13 @@ mext_out: | |||
281 | sizeof(input))) | 293 | sizeof(input))) |
282 | return -EFAULT; | 294 | return -EFAULT; |
283 | 295 | ||
296 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | ||
297 | EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { | ||
298 | ext4_msg(sb, KERN_ERR, | ||
299 | "Online resizing not supported with bigalloc"); | ||
300 | return -EOPNOTSUPP; | ||
301 | } | ||
302 | |||
284 | err = mnt_want_write(filp->f_path.mnt); | 303 | err = mnt_want_write(filp->f_path.mnt); |
285 | if (err) | 304 | if (err) |
286 | return err; | 305 | return err; |
@@ -337,7 +356,6 @@ mext_out: | |||
337 | 356 | ||
338 | case FITRIM: | 357 | case FITRIM: |
339 | { | 358 | { |
340 | struct super_block *sb = inode->i_sb; | ||
341 | struct request_queue *q = bdev_get_queue(sb->s_bdev); | 359 | struct request_queue *q = bdev_get_queue(sb->s_bdev); |
342 | struct fstrim_range range; | 360 | struct fstrim_range range; |
343 | int ret = 0; | 361 | int ret = 0; |
@@ -348,6 +366,13 @@ mext_out: | |||
348 | if (!blk_queue_discard(q)) | 366 | if (!blk_queue_discard(q)) |
349 | return -EOPNOTSUPP; | 367 | return -EOPNOTSUPP; |
350 | 368 | ||
369 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | ||
370 | EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { | ||
371 | ext4_msg(sb, KERN_ERR, | ||
372 | "FITRIM not supported with bigalloc"); | ||
373 | return -EOPNOTSUPP; | ||
374 | } | ||
375 | |||
351 | if (copy_from_user(&range, (struct fstrim_range *)arg, | 376 | if (copy_from_user(&range, (struct fstrim_range *)arg, |
352 | sizeof(range))) | 377 | sizeof(range))) |
353 | return -EFAULT; | 378 | return -EFAULT; |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 823e7d9deee2..25a4bfe3f39f 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -2701,6 +2701,13 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly) | |||
2701 | return 0; | 2701 | return 0; |
2702 | } | 2702 | } |
2703 | } | 2703 | } |
2704 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC) && | ||
2705 | !EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) { | ||
2706 | ext4_msg(sb, KERN_ERR, | ||
2707 | "Can't support bigalloc feature without " | ||
2708 | "extents feature\n"); | ||
2709 | return 0; | ||
2710 | } | ||
2704 | return 1; | 2711 | return 1; |
2705 | } | 2712 | } |
2706 | 2713 | ||