2009-03-30 22:02:44 +04:00
/*
2005-04-17 02:20:36 +04:00
* Copyright 2000 by Hans Reiser , licensing governed by reiserfs / README
*/
2005-07-13 07:21:28 +04:00
2009-03-30 22:02:44 +04:00
/*
2005-04-17 02:20:36 +04:00
* Written by Alexander Zarochentcev .
*
* The kernel part of the ( on - line ) reiserfs resizer .
*/
# include <linux/kernel.h>
# include <linux/mm.h>
# include <linux/vmalloc.h>
# include <linux/string.h>
# include <linux/errno.h>
2012-03-17 09:16:43 +04:00
# include "reiserfs.h"
2005-04-17 02:20:36 +04:00
# include <linux/buffer_head.h>
2005-07-13 07:21:28 +04:00
int reiserfs_resize ( struct super_block * s , unsigned long block_count_new )
2005-04-17 02:20:36 +04:00
{
2005-07-13 07:21:28 +04:00
int err = 0 ;
struct reiserfs_super_block * sb ;
struct reiserfs_bitmap_info * bitmap ;
2006-10-01 10:28:42 +04:00
struct reiserfs_bitmap_info * info ;
2005-04-17 02:20:36 +04:00
struct reiserfs_bitmap_info * old_bitmap = SB_AP_BITMAP ( s ) ;
2005-07-13 07:21:28 +04:00
struct buffer_head * bh ;
2005-04-17 02:20:36 +04:00
struct reiserfs_transaction_handle th ;
unsigned int bmap_nr_new , bmap_nr ;
unsigned int block_r_new , block_r ;
2005-07-13 07:21:28 +04:00
struct reiserfs_list_bitmap * jb ;
2005-04-17 02:20:36 +04:00
struct reiserfs_list_bitmap jbitmap [ JOURNAL_NUM_BITMAPS ] ;
2005-07-13 07:21:28 +04:00
2005-04-17 02:20:36 +04:00
unsigned long int block_count , free_blocks ;
int i ;
2005-07-13 07:21:28 +04:00
int copy_size ;
2013-08-09 01:34:46 +04:00
int depth ;
2005-04-17 02:20:36 +04:00
sb = SB_DISK_SUPER_BLOCK ( s ) ;
if ( SB_BLOCK_COUNT ( s ) > = block_count_new ) {
printk ( " can \' t shrink filesystem on-line \n " ) ;
return - EINVAL ;
}
/* check the device size */
2013-08-09 01:34:46 +04:00
depth = reiserfs_write_unlock_nested ( s ) ;
2005-04-17 02:20:36 +04:00
bh = sb_bread ( s , block_count_new - 1 ) ;
2013-08-09 01:34:46 +04:00
reiserfs_write_lock_nested ( s , depth ) ;
2005-04-17 02:20:36 +04:00
if ( ! bh ) {
printk ( " reiserfs_resize: can \' t read last block \n " ) ;
return - EINVAL ;
2005-07-13 07:21:28 +04:00
}
2005-04-17 02:20:36 +04:00
bforget ( bh ) ;
2014-04-23 18:00:36 +04:00
/*
* old disk layout detection ; those partitions can be mounted , but
* cannot be resized
*/
2005-07-13 07:21:28 +04:00
if ( SB_BUFFER_WITH_SB ( s ) - > b_blocknr * SB_BUFFER_WITH_SB ( s ) - > b_size
! = REISERFS_DISK_OFFSET_IN_BYTES ) {
printk
( " reiserfs_resize: unable to resize a reiserfs without distributed bitmap (fs version < 3.5.12) \n " ) ;
2005-04-17 02:20:36 +04:00
return - ENOTSUPP ;
}
2005-07-13 07:21:28 +04:00
2005-04-17 02:20:36 +04:00
/* count used bits in last bitmap block */
2007-10-19 10:39:27 +04:00
block_r = SB_BLOCK_COUNT ( s ) -
( reiserfs_bmap_count ( s ) - 1 ) * s - > s_blocksize * 8 ;
2005-07-13 07:21:28 +04:00
2005-04-17 02:20:36 +04:00
/* count bitmap blocks in new fs */
2005-07-13 07:21:28 +04:00
bmap_nr_new = block_count_new / ( s - > s_blocksize * 8 ) ;
2005-04-17 02:20:36 +04:00
block_r_new = block_count_new - bmap_nr_new * s - > s_blocksize * 8 ;
2005-07-13 07:21:28 +04:00
if ( block_r_new )
2005-04-17 02:20:36 +04:00
bmap_nr_new + + ;
else
block_r_new = s - > s_blocksize * 8 ;
/* save old values */
block_count = SB_BLOCK_COUNT ( s ) ;
2007-10-19 10:39:27 +04:00
bmap_nr = reiserfs_bmap_count ( s ) ;
2005-04-17 02:20:36 +04:00
/* resizing of reiserfs bitmaps (journal and real), if needed */
2005-07-13 07:21:28 +04:00
if ( bmap_nr_new > bmap_nr ) {
/* reallocate journal bitmaps */
if ( reiserfs_allocate_list_bitmaps ( s , jbitmap , bmap_nr_new ) < 0 ) {
printk
( " reiserfs_resize: unable to allocate memory for journal bitmaps \n " ) ;
return - ENOMEM ;
}
2014-04-23 18:00:36 +04:00
/*
* the new journal bitmaps are zero filled , now we copy i
* the bitmap node pointers from the old journal bitmap
* structs , and then transfer the new data structures
* into the journal struct .
*
* using the copy_size var below allows this code to work for
* both shrinking and expanding the FS .
2005-07-13 07:21:28 +04:00
*/
copy_size = bmap_nr_new < bmap_nr ? bmap_nr_new : bmap_nr ;
copy_size =
copy_size * sizeof ( struct reiserfs_list_bitmap_node * ) ;
for ( i = 0 ; i < JOURNAL_NUM_BITMAPS ; i + + ) {
struct reiserfs_bitmap_node * * node_tmp ;
jb = SB_JOURNAL ( s ) - > j_list_bitmap + i ;
memcpy ( jbitmap [ i ] . bitmaps , jb - > bitmaps , copy_size ) ;
2014-04-23 18:00:36 +04:00
/*
* just in case vfree schedules on us , copy the new
* pointer into the journal struct before freeing the
* old one
2005-07-13 07:21:28 +04:00
*/
node_tmp = jb - > bitmaps ;
jb - > bitmaps = jbitmap [ i ] . bitmaps ;
vfree ( node_tmp ) ;
}
2014-04-23 18:00:36 +04:00
/*
* allocate additional bitmap blocks , reallocate
* array of bitmap block pointers
*/
2005-07-13 07:21:28 +04:00
bitmap =
treewide: Use array_size() in vzalloc()
The vzalloc() function has no 2-factor argument form, so multiplication
factors need to be wrapped in array_size(). This patch replaces cases of:
vzalloc(a * b)
with:
vzalloc(array_size(a, b))
as well as handling cases of:
vzalloc(a * b * c)
with:
vzalloc(array3_size(a, b, c))
This does, however, attempt to ignore constant size factors like:
vzalloc(4 * 1024)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
vzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
vzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
vzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
vzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
vzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
vzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
vzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
vzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
vzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
vzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
vzalloc(
- sizeof(TYPE) * (COUNT_ID)
+ array_size(COUNT_ID, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(TYPE) * COUNT_ID
+ array_size(COUNT_ID, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(TYPE) * (COUNT_CONST)
+ array_size(COUNT_CONST, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(TYPE) * COUNT_CONST
+ array_size(COUNT_CONST, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(THING) * (COUNT_ID)
+ array_size(COUNT_ID, sizeof(THING))
, ...)
|
vzalloc(
- sizeof(THING) * COUNT_ID
+ array_size(COUNT_ID, sizeof(THING))
, ...)
|
vzalloc(
- sizeof(THING) * (COUNT_CONST)
+ array_size(COUNT_CONST, sizeof(THING))
, ...)
|
vzalloc(
- sizeof(THING) * COUNT_CONST
+ array_size(COUNT_CONST, sizeof(THING))
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
vzalloc(
- SIZE * COUNT
+ array_size(COUNT, SIZE)
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
vzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
vzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
vzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
vzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
vzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
vzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
vzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
vzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
vzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
vzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
vzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
vzalloc(C1 * C2 * C3, ...)
|
vzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants.
@@
expression E1, E2;
constant C1, C2;
@@
(
vzalloc(C1 * C2, ...)
|
vzalloc(
- E1 * E2
+ array_size(E1, E2)
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:27:37 +03:00
vzalloc ( array_size ( bmap_nr_new ,
sizeof ( struct reiserfs_bitmap_info ) ) ) ;
2005-07-13 07:21:28 +04:00
if ( ! bitmap ) {
2014-04-23 18:00:36 +04:00
/*
* Journal bitmaps are still supersized , but the
* memory isn ' t leaked , so I guess it ' s ok
*/
2005-07-13 07:21:28 +04:00
printk ( " reiserfs_resize: unable to allocate memory. \n " ) ;
return - ENOMEM ;
}
for ( i = 0 ; i < bmap_nr ; i + + )
bitmap [ i ] = old_bitmap [ i ] ;
2014-04-23 18:00:36 +04:00
/*
* This doesn ' t go through the journal , but it doesn ' t have to .
* The changes are still atomic : We ' re synced up when the
* journal transaction begins , and the new bitmaps don ' t
* matter if the transaction fails .
*/
2005-07-13 07:21:28 +04:00
for ( i = bmap_nr ; i < bmap_nr_new ; i + + ) {
2013-08-09 01:34:46 +04:00
int depth ;
2014-04-23 18:00:36 +04:00
/*
* don ' t use read_bitmap_block since it will cache
* the uninitialized bitmap
*/
2013-08-09 01:34:46 +04:00
depth = reiserfs_write_unlock_nested ( s ) ;
2006-10-01 10:28:44 +04:00
bh = sb_bread ( s , i * s - > s_blocksize * 8 ) ;
2013-08-09 01:34:46 +04:00
reiserfs_write_lock_nested ( s , depth ) ;
2007-05-08 11:24:37 +04:00
if ( ! bh ) {
vfree ( bitmap ) ;
return - EIO ;
}
2006-10-01 10:28:42 +04:00
memset ( bh - > b_data , 0 , sb_blocksize ( sb ) ) ;
2011-07-26 04:13:37 +04:00
reiserfs_set_le_bit ( 0 , bh - > b_data ) ;
2006-10-01 10:28:43 +04:00
reiserfs_cache_bitmap_metadata ( s , bh , bitmap + i ) ;
2006-10-01 10:28:42 +04:00
set_buffer_uptodate ( bh ) ;
mark_buffer_dirty ( bh ) ;
2013-08-09 01:34:46 +04:00
depth = reiserfs_write_unlock_nested ( s ) ;
2006-10-01 10:28:42 +04:00
sync_dirty_buffer ( bh ) ;
2013-08-09 01:34:46 +04:00
reiserfs_write_lock_nested ( s , depth ) ;
2014-04-23 18:00:36 +04:00
/* update bitmap_info stuff */
2005-07-13 07:21:28 +04:00
bitmap [ i ] . free_count = sb_blocksize ( sb ) * 8 - 1 ;
2006-10-01 10:28:42 +04:00
brelse ( bh ) ;
2005-07-13 07:21:28 +04:00
}
/* free old bitmap blocks array */
SB_AP_BITMAP ( s ) = bitmap ;
vfree ( old_bitmap ) ;
2005-04-17 02:20:36 +04:00
}
2005-07-13 07:21:28 +04:00
2014-04-23 18:00:36 +04:00
/*
* begin transaction , if there was an error , it ' s fine . Yes , we have
2005-04-17 02:20:36 +04:00
* incorrect bitmaps now , but none of it is ever going to touch the
2014-04-23 18:00:36 +04:00
* disk anyway .
*/
2005-04-17 02:20:36 +04:00
err = journal_begin ( & th , s , 10 ) ;
if ( err )
2005-07-13 07:21:28 +04:00
return err ;
2005-04-17 02:20:36 +04:00
2006-10-01 10:28:42 +04:00
/* Extend old last bitmap block - new blocks have been made available */
info = SB_AP_BITMAP ( s ) + bmap_nr - 1 ;
2006-10-01 10:28:44 +04:00
bh = reiserfs_read_bitmap_block ( s , bmap_nr - 1 ) ;
if ( ! bh ) {
2014-04-23 18:00:38 +04:00
int jerr = journal_end ( & th ) ;
2006-10-01 10:28:44 +04:00
if ( jerr )
return jerr ;
return - EIO ;
}
2006-10-01 10:28:42 +04:00
reiserfs_prepare_for_journal ( s , bh , 1 ) ;
2005-04-17 02:20:36 +04:00
for ( i = block_r ; i < s - > s_blocksize * 8 ; i + + )
2011-07-26 04:13:37 +04:00
reiserfs_clear_le_bit ( i , bh - > b_data ) ;
2006-10-01 10:28:42 +04:00
info - > free_count + = s - > s_blocksize * 8 - block_r ;
2014-04-23 18:00:39 +04:00
journal_mark_dirty ( & th , bh ) ;
2006-10-01 10:28:42 +04:00
brelse ( bh ) ;
2005-04-17 02:20:36 +04:00
2006-10-01 10:28:42 +04:00
/* Correct new last bitmap block - It may not be full */
info = SB_AP_BITMAP ( s ) + bmap_nr_new - 1 ;
2006-10-01 10:28:44 +04:00
bh = reiserfs_read_bitmap_block ( s , bmap_nr_new - 1 ) ;
if ( ! bh ) {
2014-04-23 18:00:38 +04:00
int jerr = journal_end ( & th ) ;
2006-10-01 10:28:44 +04:00
if ( jerr )
return jerr ;
return - EIO ;
}
2005-04-17 02:20:36 +04:00
2006-10-01 10:28:42 +04:00
reiserfs_prepare_for_journal ( s , bh , 1 ) ;
2005-04-17 02:20:36 +04:00
for ( i = block_r_new ; i < s - > s_blocksize * 8 ; i + + )
2011-07-26 04:13:37 +04:00
reiserfs_set_le_bit ( i , bh - > b_data ) ;
2014-04-23 18:00:39 +04:00
journal_mark_dirty ( & th , bh ) ;
2006-10-01 10:28:42 +04:00
brelse ( bh ) ;
2005-07-13 07:21:28 +04:00
2006-10-01 10:28:42 +04:00
info - > free_count - = s - > s_blocksize * 8 - block_r_new ;
2005-07-13 07:21:28 +04:00
/* update super */
reiserfs_prepare_for_journal ( s , SB_BUFFER_WITH_SB ( s ) , 1 ) ;
2005-04-17 02:20:36 +04:00
free_blocks = SB_FREE_BLOCKS ( s ) ;
2005-07-13 07:21:28 +04:00
PUT_SB_FREE_BLOCKS ( s ,
free_blocks + ( block_count_new - block_count -
( bmap_nr_new - bmap_nr ) ) ) ;
2005-04-17 02:20:36 +04:00
PUT_SB_BLOCK_COUNT ( s , block_count_new ) ;
2007-10-19 10:39:27 +04:00
PUT_SB_BMAP_NR ( s , bmap_would_wrap ( bmap_nr_new ) ? : bmap_nr_new ) ;
2005-04-17 02:20:36 +04:00
2014-04-23 18:00:39 +04:00
journal_mark_dirty ( & th , SB_BUFFER_WITH_SB ( s ) ) ;
2005-07-13 07:21:28 +04:00
2005-04-17 02:20:36 +04:00
SB_JOURNAL ( s ) - > j_must_wait = 1 ;
2014-04-23 18:00:38 +04:00
return journal_end ( & th ) ;
2005-04-17 02:20:36 +04:00
}