|
|
|
@ -56,6 +56,7 @@ |
|
|
|
|
#include "btnode.h" |
|
|
|
|
#include "page.h" |
|
|
|
|
#include "cpfile.h" |
|
|
|
|
#include "sufile.h" /* nilfs_sufile_resize(), nilfs_sufile_set_alloc_range() */ |
|
|
|
|
#include "ifile.h" |
|
|
|
|
#include "dat.h" |
|
|
|
|
#include "segment.h" |
|
|
|
@ -404,6 +405,77 @@ out: |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nilfs_resize_fs - resize the filesystem |
|
|
|
|
* @sb: super block instance |
|
|
|
|
* @newsize: new size of the filesystem (in bytes) |
|
|
|
|
*/ |
|
|
|
|
int nilfs_resize_fs(struct super_block *sb, __u64 newsize) |
|
|
|
|
{ |
|
|
|
|
struct the_nilfs *nilfs = sb->s_fs_info; |
|
|
|
|
struct nilfs_super_block **sbp; |
|
|
|
|
__u64 devsize, newnsegs; |
|
|
|
|
loff_t sb2off; |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
ret = -ERANGE; |
|
|
|
|
devsize = i_size_read(sb->s_bdev->bd_inode); |
|
|
|
|
if (newsize > devsize) |
|
|
|
|
goto out; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Write lock is required to protect some functions depending |
|
|
|
|
* on the number of segments, the number of reserved segments, |
|
|
|
|
* and so forth. |
|
|
|
|
*/ |
|
|
|
|
down_write(&nilfs->ns_segctor_sem); |
|
|
|
|
|
|
|
|
|
sb2off = NILFS_SB2_OFFSET_BYTES(newsize); |
|
|
|
|
newnsegs = sb2off >> nilfs->ns_blocksize_bits; |
|
|
|
|
do_div(newnsegs, nilfs->ns_blocks_per_segment); |
|
|
|
|
|
|
|
|
|
ret = nilfs_sufile_resize(nilfs->ns_sufile, newnsegs); |
|
|
|
|
up_write(&nilfs->ns_segctor_sem); |
|
|
|
|
if (ret < 0) |
|
|
|
|
goto out; |
|
|
|
|
|
|
|
|
|
ret = nilfs_construct_segment(sb); |
|
|
|
|
if (ret < 0) |
|
|
|
|
goto out; |
|
|
|
|
|
|
|
|
|
down_write(&nilfs->ns_sem); |
|
|
|
|
nilfs_move_2nd_super(sb, sb2off); |
|
|
|
|
ret = -EIO; |
|
|
|
|
sbp = nilfs_prepare_super(sb, 0); |
|
|
|
|
if (likely(sbp)) { |
|
|
|
|
nilfs_set_log_cursor(sbp[0], nilfs); |
|
|
|
|
/*
|
|
|
|
|
* Drop NILFS_RESIZE_FS flag for compatibility with |
|
|
|
|
* mount-time resize which may be implemented in a |
|
|
|
|
* future release. |
|
|
|
|
*/ |
|
|
|
|
sbp[0]->s_state = cpu_to_le16(le16_to_cpu(sbp[0]->s_state) & |
|
|
|
|
~NILFS_RESIZE_FS); |
|
|
|
|
sbp[0]->s_dev_size = cpu_to_le64(newsize); |
|
|
|
|
sbp[0]->s_nsegments = cpu_to_le64(nilfs->ns_nsegments); |
|
|
|
|
if (sbp[1]) |
|
|
|
|
memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); |
|
|
|
|
ret = nilfs_commit_super(sb, NILFS_SB_COMMIT_ALL); |
|
|
|
|
} |
|
|
|
|
up_write(&nilfs->ns_sem); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Reset the range of allocatable segments last. This order |
|
|
|
|
* is important in the case of expansion because the secondary |
|
|
|
|
* superblock must be protected from log write until migration |
|
|
|
|
* completes. |
|
|
|
|
*/ |
|
|
|
|
if (!ret) |
|
|
|
|
nilfs_sufile_set_alloc_range(nilfs->ns_sufile, 0, newnsegs - 1); |
|
|
|
|
out: |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void nilfs_put_super(struct super_block *sb) |
|
|
|
|
{ |
|
|
|
|
struct the_nilfs *nilfs = sb->s_fs_info; |
|
|
|
|