···581581 behaviour may change in the future as it is582582 not necessary and has been done this way only583583 for sake of simplicity.584584+585585+ EXT4_IOC_RESIZE_FS Resize the filesystem to a new size. The number586586+ of blocks of resized filesystem is passed in via587587+ 64 bit integer argument. The kernel allocates588588+ bitmaps and inode table, the userspace tool thus589589+ just passes the new number of blocks.590590+584591..............................................................................585592586593References
+3-1
fs/ext4/balloc.c
···23232424#include <trace/events/ext4.h>25252626+static unsigned ext4_num_base_meta_clusters(struct super_block *sb,2727+ ext4_group_t block_group);2628/*2729 * balloc.c contains the blocks allocation and deallocation routines2830 */···670668 * This function returns the number of file system metadata clusters at671669 * the beginning of a block group, including the reserved gdt blocks.672670 */673673-unsigned ext4_num_base_meta_clusters(struct super_block *sb,671671+static unsigned ext4_num_base_meta_clusters(struct super_block *sb,674672 ext4_group_t block_group)675673{676674 struct ext4_sb_info *sbi = EXT4_SB(sb);
+17-12
fs/ext4/ext4.h
···511511 __u32 free_blocks_count;512512};513513514514+/* Indexes used to index group tables in ext4_new_group_data */515515+enum {516516+ BLOCK_BITMAP = 0, /* block bitmap */517517+ INODE_BITMAP, /* inode bitmap */518518+ INODE_TABLE, /* inode tables */519519+ GROUP_TABLE_COUNT,520520+};521521+514522/*515523 * Flags used by ext4_map_blocks()516524 */···583575 /* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */584576#define EXT4_IOC_ALLOC_DA_BLKS _IO('f', 12)585577#define EXT4_IOC_MOVE_EXT _IOWR('f', 15, struct move_extent)578578+#define EXT4_IOC_RESIZE_FS _IOW('f', 16, __u64)586579587580#if defined(__KERNEL__) && defined(CONFIG_COMPAT)588581/*···966957#define test_opt2(sb, opt) (EXT4_SB(sb)->s_mount_opt2 & \967958 EXT4_MOUNT2_##opt)968959969969-#define ext4_set_bit __test_and_set_bit_le960960+#define ext4_test_and_set_bit __test_and_set_bit_le961961+#define ext4_set_bit __set_bit_le970962#define ext4_set_bit_atomic ext2_set_bit_atomic971971-#define ext4_clear_bit __test_and_clear_bit_le963963+#define ext4_test_and_clear_bit __test_and_clear_bit_le964964+#define ext4_clear_bit __clear_bit_le972965#define ext4_clear_bit_atomic ext2_clear_bit_atomic973966#define ext4_test_bit test_bit_le974974-#define ext4_find_first_zero_bit find_first_zero_bit_le975967#define ext4_find_next_zero_bit find_next_zero_bit_le976968#define ext4_find_next_bit find_next_bit_le977969···14071397#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x004014081398#define EXT4_FEATURE_RO_COMPAT_QUOTA 0x010014091399#define EXT4_FEATURE_RO_COMPAT_BIGALLOC 0x020014001400+#define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x04001410140114111402#define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x000114121403#define EXT4_FEATURE_INCOMPAT_FILETYPE 0x0002···14201409#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x020014211410#define EXT4_FEATURE_INCOMPAT_EA_INODE 0x0400 /* EA in inode */14221411#define EXT4_FEATURE_INCOMPAT_DIRDATA 0x1000 /* data in dirent */14121412+#define EXT4_FEATURE_INCOMPAT_INLINEDATA 0x2000 /* data in inode */14131413+#define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3-lvl htree */1423141414241415#define EXT2_FEATURE_COMPAT_SUPP EXT4_FEATURE_COMPAT_EXT_ATTR14251416#define EXT2_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \···18031790extern unsigned ext4_free_clusters_after_init(struct super_block *sb,18041791 ext4_group_t block_group,18051792 struct ext4_group_desc *gdp);18061806-extern unsigned ext4_num_base_meta_clusters(struct super_block *sb,18071807- ext4_group_t block_group);18081793extern unsigned ext4_num_overhead_clusters(struct super_block *sb,18091794 ext4_group_t block_group,18101795 struct ext4_group_desc *gdp);···18911880extern void ext4_set_aops(struct inode *inode);18921881extern int ext4_writepage_trans_blocks(struct inode *);18931882extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks);18941894-extern int ext4_block_truncate_page(handle_t *handle,18951895- struct address_space *mapping, loff_t from);18961896-extern int ext4_block_zero_page_range(handle_t *handle,18971897- struct address_space *mapping, loff_t from, loff_t length);18981883extern int ext4_discard_partial_page_buffers(handle_t *handle,18991884 struct address_space *mapping, loff_t from,19001900- loff_t length, int flags);19011901-extern int ext4_discard_partial_page_buffers_no_lock(handle_t *handle,19021902- struct inode *inode, struct page *page, loff_t from,19031885 loff_t length, int flags);19041886extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);19051887extern qsize_t *ext4_get_reserved_space(struct inode *inode);···19281924extern int ext4_group_extend(struct super_block *sb,19291925 struct ext4_super_block *es,19301926 ext4_fsblk_t n_blocks_count);19271927+extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);1931192819321929/* super.c */19331930extern void *ext4_kvmalloc(size_t size, gfp_t flags);
+6-4
fs/ext4/extents.c
···32803280 ext4_lblk_t i, pg_lblk;32813281 pgoff_t index;3282328232833283+ if (!test_opt(inode->i_sb, DELALLOC))32843284+ return 0;32853285+32833286 /* reverse search wont work if fs block size is less than page size */32843287 if (inode->i_blkbits < PAGE_CACHE_SHIFT)32853288 search_hint_reverse = 0;···34553452 int err = 0;34563453 ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio;3457345434583458- ext_debug("ext4_ext_handle_uninitialized_extents: inode %lu, logical"34593459- "block %llu, max_blocks %u, flags %d, allocated %u",34553455+ ext_debug("ext4_ext_handle_uninitialized_extents: inode %lu, logical "34563456+ "block %llu, max_blocks %u, flags %x, allocated %u\n",34603457 inode->i_ino, (unsigned long long)map->m_lblk, map->m_len,34613458 flags, allocated);34623459 ext4_ext_show_leaf(inode, path);···36273624 struct ext4_sb_info *sbi = EXT4_SB(sb);36283625 ext4_lblk_t c_offset = map->m_lblk & (sbi->s_cluster_ratio-1);36293626 ext4_lblk_t ex_cluster_start, ex_cluster_end;36303630- ext4_lblk_t rr_cluster_start, rr_cluster_end;36273627+ ext4_lblk_t rr_cluster_start;36313628 ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block);36323629 ext4_fsblk_t ee_start = ext4_ext_pblock(ex);36333630 unsigned short ee_len = ext4_ext_get_actual_len(ex);···3638363536393636 /* The requested region passed into ext4_map_blocks() */36403637 rr_cluster_start = EXT4_B2C(sbi, map->m_lblk);36413641- rr_cluster_end = EXT4_B2C(sbi, map->m_lblk + map->m_len - 1);3642363836433639 if ((rr_cluster_start == ex_cluster_end) ||36443640 (rr_cluster_start == ex_cluster_start)) {
+11-7
fs/ext4/ialloc.c
···252252 fatal = ext4_journal_get_write_access(handle, bh2);253253 }254254 ext4_lock_group(sb, block_group);255255- cleared = ext4_clear_bit(bit, bitmap_bh->b_data);255255+ cleared = ext4_test_and_clear_bit(bit, bitmap_bh->b_data);256256 if (fatal || !cleared) {257257 ext4_unlock_group(sb, block_group);258258 goto out;···358358 struct ext4_sb_info *sbi = EXT4_SB(sb);359359 ext4_group_t real_ngroups = ext4_get_groups_count(sb);360360 int inodes_per_group = EXT4_INODES_PER_GROUP(sb);361361- unsigned int freei, avefreei;361361+ unsigned int freei, avefreei, grp_free;362362 ext4_fsblk_t freeb, avefreec;363363 unsigned int ndirs;364364 int max_dirs, min_inodes;···477477 for (i = 0; i < ngroups; i++) {478478 grp = (parent_group + i) % ngroups;479479 desc = ext4_get_group_desc(sb, grp, NULL);480480- if (desc && ext4_free_inodes_count(sb, desc) &&481481- ext4_free_inodes_count(sb, desc) >= avefreei) {480480+ grp_free = ext4_free_inodes_count(sb, desc);481481+ if (desc && grp_free && grp_free >= avefreei) {482482 *group = grp;483483 return 0;484484 }···618618 */619619 down_read(&grp->alloc_sem);620620 ext4_lock_group(sb, group);621621- if (ext4_set_bit(ino, inode_bitmap_bh->b_data)) {621621+ if (ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data)) {622622 /* not a free inode */623623 retval = 1;624624 goto err_ret;···885885 if (IS_DIRSYNC(inode))886886 ext4_handle_sync(handle);887887 if (insert_inode_locked(inode) < 0) {888888- err = -EINVAL;889889- goto fail_drop;888888+ /*889889+ * Likely a bitmap corruption causing inode to be allocated890890+ * twice.891891+ */892892+ err = -EIO;893893+ goto fail;890894 }891895 spin_lock(&sbi->s_next_gen_lock);892896 inode->i_generation = sbi->s_next_generation++;
+19-124
fs/ext4/inode.c
···7171static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate);7272static int __ext4_journalled_writepage(struct page *page, unsigned int len);7373static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh);7474+static int ext4_discard_partial_page_buffers_no_lock(handle_t *handle,7575+ struct inode *inode, struct page *page, loff_t from,7676+ loff_t length, int flags);74777578/*7679 * Test whether an inode is a fast symlink.···27622759 if (!io_end || !size)27632760 goto out;2764276127652765- ext_debug("ext4_end_io_dio(): io_end 0x%p"27622762+ ext_debug("ext4_end_io_dio(): io_end 0x%p "27662763 "for inode %lu, iocb 0x%p, offset %llu, size %llu\n",27672764 iocb->private, io_end->inode->i_ino, iocb, offset,27682765 size);···31633160 *31643161 * Returns zero on sucess or negative on failure.31653162 */31663166-int ext4_discard_partial_page_buffers_no_lock(handle_t *handle,31633163+static int ext4_discard_partial_page_buffers_no_lock(handle_t *handle,31673164 struct inode *inode, struct page *page, loff_t from,31683165 loff_t length, int flags)31693166{···33003297 pos += range_to_discard;33013298 }3302329933033303- return err;33043304-}33053305-33063306-/*33073307- * ext4_block_truncate_page() zeroes out a mapping from file offset `from'33083308- * up to the end of the block which corresponds to `from'.33093309- * This required during truncate. We need to physically zero the tail end33103310- * of that block so it doesn't yield old data if the file is later grown.33113311- */33123312-int ext4_block_truncate_page(handle_t *handle,33133313- struct address_space *mapping, loff_t from)33143314-{33153315- unsigned offset = from & (PAGE_CACHE_SIZE-1);33163316- unsigned length;33173317- unsigned blocksize;33183318- struct inode *inode = mapping->host;33193319-33203320- blocksize = inode->i_sb->s_blocksize;33213321- length = blocksize - (offset & (blocksize - 1));33223322-33233323- return ext4_block_zero_page_range(handle, mapping, from, length);33243324-}33253325-33263326-/*33273327- * ext4_block_zero_page_range() zeros out a mapping of length 'length'33283328- * starting from file offset 'from'. The range to be zero'd must33293329- * be contained with in one block. If the specified range exceeds33303330- * the end of the block it will be shortened to end of the block33313331- * that cooresponds to 'from'33323332- */33333333-int ext4_block_zero_page_range(handle_t *handle,33343334- struct address_space *mapping, loff_t from, loff_t length)33353335-{33363336- ext4_fsblk_t index = from >> PAGE_CACHE_SHIFT;33373337- unsigned offset = from & (PAGE_CACHE_SIZE-1);33383338- unsigned blocksize, max, pos;33393339- ext4_lblk_t iblock;33403340- struct inode *inode = mapping->host;33413341- struct buffer_head *bh;33423342- struct page *page;33433343- int err = 0;33443344-33453345- page = find_or_create_page(mapping, from >> PAGE_CACHE_SHIFT,33463346- mapping_gfp_mask(mapping) & ~__GFP_FS);33473347- if (!page)33483348- return -ENOMEM;33493349-33503350- blocksize = inode->i_sb->s_blocksize;33513351- max = blocksize - (offset & (blocksize - 1));33523352-33533353- /*33543354- * correct length if it does not fall between33553355- * 'from' and the end of the block33563356- */33573357- if (length > max || length < 0)33583358- length = max;33593359-33603360- iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);33613361-33623362- if (!page_has_buffers(page))33633363- create_empty_buffers(page, blocksize, 0);33643364-33653365- /* Find the buffer that contains "offset" */33663366- bh = page_buffers(page);33673367- pos = blocksize;33683368- while (offset >= pos) {33693369- bh = bh->b_this_page;33703370- iblock++;33713371- pos += blocksize;33723372- }33733373-33743374- err = 0;33753375- if (buffer_freed(bh)) {33763376- BUFFER_TRACE(bh, "freed: skip");33773377- goto unlock;33783378- }33793379-33803380- if (!buffer_mapped(bh)) {33813381- BUFFER_TRACE(bh, "unmapped");33823382- ext4_get_block(inode, iblock, bh, 0);33833383- /* unmapped? It's a hole - nothing to do */33843384- if (!buffer_mapped(bh)) {33853385- BUFFER_TRACE(bh, "still unmapped");33863386- goto unlock;33873387- }33883388- }33893389-33903390- /* Ok, it's mapped. Make sure it's up-to-date */33913391- if (PageUptodate(page))33923392- set_buffer_uptodate(bh);33933393-33943394- if (!buffer_uptodate(bh)) {33953395- err = -EIO;33963396- ll_rw_block(READ, 1, &bh);33973397- wait_on_buffer(bh);33983398- /* Uhhuh. Read error. Complain and punt. */33993399- if (!buffer_uptodate(bh))34003400- goto unlock;34013401- }34023402-34033403- if (ext4_should_journal_data(inode)) {34043404- BUFFER_TRACE(bh, "get write access");34053405- err = ext4_journal_get_write_access(handle, bh);34063406- if (err)34073407- goto unlock;34083408- }34093409-34103410- zero_user(page, offset, length);34113411-34123412- BUFFER_TRACE(bh, "zeroed end of block");34133413-34143414- err = 0;34153415- if (ext4_should_journal_data(inode)) {34163416- err = ext4_handle_dirty_metadata(handle, inode, bh);34173417- } else34183418- mark_buffer_dirty(bh);34193419-34203420-unlock:34213421- unlock_page(page);34223422- page_cache_release(page);34233300 return err;34243301}34253302···45294646 return 0;45304647 if (is_journal_aborted(journal))45314648 return -EROFS;46494649+ /* We have to allocate physical blocks for delalloc blocks46504650+ * before flushing journal. otherwise delalloc blocks can not46514651+ * be allocated any more. even more truncate on delalloc blocks46524652+ * could trigger BUG by flushing delalloc blocks in journal.46534653+ * There is no delalloc block in non-journal data mode.46544654+ */46554655+ if (val && test_opt(inode->i_sb, DELALLOC)) {46564656+ err = ext4_alloc_da_blocks(inode);46574657+ if (err < 0)46584658+ return err;46594659+ }4532466045334661 jbd2_journal_lock_updates(journal);45344534- jbd2_journal_flush(journal);4535466245364663 /*45374664 * OK, there are no updates running now, and all cached data is···4553466045544661 if (val)45554662 ext4_set_inode_flag(inode, EXT4_INODE_JOURNAL_DATA);45564556- else46634663+ else {46644664+ jbd2_journal_flush(journal);45574665 ext4_clear_inode_flag(inode, EXT4_INODE_JOURNAL_DATA);46664666+ }45584667 ext4_set_aops(inode);4559466845604669 jbd2_journal_unlock_updates(journal);
+74-12
fs/ext4/ioctl.c
···1818#include "ext4_jbd2.h"1919#include "ext4.h"20202121+#define MAX_32_NUM ((((unsigned long long) 1) << 32) - 1)2222+2123long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)2224{2325 struct inode *inode = filp->f_dentry->d_inode;···188186 if (err)189187 return err;190188191191- if (get_user(n_blocks_count, (__u32 __user *)arg))192192- return -EFAULT;189189+ if (get_user(n_blocks_count, (__u32 __user *)arg)) {190190+ err = -EFAULT;191191+ goto group_extend_out;192192+ }193193194194 if (EXT4_HAS_RO_COMPAT_FEATURE(sb,195195 EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {196196 ext4_msg(sb, KERN_ERR,197197 "Online resizing not supported with bigalloc");198198- return -EOPNOTSUPP;198198+ err = -EOPNOTSUPP;199199+ goto group_extend_out;199200 }200201201202 err = mnt_want_write_file(filp);202203 if (err)203203- return err;204204+ goto group_extend_out;204205205206 err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count);206207 if (EXT4_SB(sb)->s_journal) {···214209 if (err == 0)215210 err = err2;216211 mnt_drop_write_file(filp);212212+group_extend_out:217213 ext4_resize_end(sb);218218-219214 return err;220215 }221216···256251 err = ext4_move_extents(filp, donor_filp, me.orig_start,257252 me.donor_start, me.len, &me.moved_len);258253 mnt_drop_write_file(filp);259259- if (me.moved_len > 0)260260- file_remove_suid(donor_filp);254254+ mnt_drop_write(filp->f_path.mnt);261255262256 if (copy_to_user((struct move_extent __user *)arg,263257 &me, sizeof(me)))···275271 return err;276272277273 if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg,278278- sizeof(input)))279279- return -EFAULT;274274+ sizeof(input))) {275275+ err = -EFAULT;276276+ goto group_add_out;277277+ }280278281279 if (EXT4_HAS_RO_COMPAT_FEATURE(sb,282280 EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {283281 ext4_msg(sb, KERN_ERR,284282 "Online resizing not supported with bigalloc");285285- return -EOPNOTSUPP;283283+ err = -EOPNOTSUPP;284284+ goto group_add_out;286285 }287286288287 err = mnt_want_write_file(filp);289288 if (err)290290- return err;289289+ goto group_add_out;291290292291 err = ext4_group_add(sb, &input);293292 if (EXT4_SB(sb)->s_journal) {···301294 if (err == 0)302295 err = err2;303296 mnt_drop_write_file(filp);297297+group_add_out:304298 ext4_resize_end(sb);305305-306299 return err;307300 }308301···339332 return err;340333 err = ext4_alloc_da_blocks(inode);341334 mnt_drop_write_file(filp);335335+ return err;336336+ }337337+338338+ case EXT4_IOC_RESIZE_FS: {339339+ ext4_fsblk_t n_blocks_count;340340+ struct super_block *sb = inode->i_sb;341341+ int err = 0, err2 = 0;342342+343343+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb,344344+ EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {345345+ ext4_msg(sb, KERN_ERR,346346+ "Online resizing not (yet) supported with bigalloc");347347+ return -EOPNOTSUPP;348348+ }349349+350350+ if (EXT4_HAS_INCOMPAT_FEATURE(sb,351351+ EXT4_FEATURE_INCOMPAT_META_BG)) {352352+ ext4_msg(sb, KERN_ERR,353353+ "Online resizing not (yet) supported with meta_bg");354354+ return -EOPNOTSUPP;355355+ }356356+357357+ if (copy_from_user(&n_blocks_count, (__u64 __user *)arg,358358+ sizeof(__u64))) {359359+ return -EFAULT;360360+ }361361+362362+ if (n_blocks_count > MAX_32_NUM &&363363+ !EXT4_HAS_INCOMPAT_FEATURE(sb,364364+ EXT4_FEATURE_INCOMPAT_64BIT)) {365365+ ext4_msg(sb, KERN_ERR,366366+ "File system only supports 32-bit block numbers");367367+ return -EOPNOTSUPP;368368+ }369369+370370+ err = ext4_resize_begin(sb);371371+ if (err)372372+ return err;373373+374374+ err = mnt_want_write(filp->f_path.mnt);375375+ if (err)376376+ goto resizefs_out;377377+378378+ err = ext4_resize_fs(sb, n_blocks_count);379379+ if (EXT4_SB(sb)->s_journal) {380380+ jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);381381+ err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);382382+ jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);383383+ }384384+ if (err == 0)385385+ err = err2;386386+ mnt_drop_write(filp->f_path.mnt);387387+resizefs_out:388388+ ext4_resize_end(sb);342389 return err;343390 }344391···494433 }495434 case EXT4_IOC_MOVE_EXT:496435 case FITRIM:436436+ case EXT4_IOC_RESIZE_FS:497437 break;498438 default:499439 return -ENOIOCTLCMD;
···134134 return err;135135}136136137137+/*138138+ * ext4_new_flex_group_data is used by 64bit-resize interface to add a flex139139+ * group each time.140140+ */141141+struct ext4_new_flex_group_data {142142+ struct ext4_new_group_data *groups; /* new_group_data for groups143143+ in the flex group */144144+ __u16 *bg_flags; /* block group flags of groups145145+ in @groups */146146+ ext4_group_t count; /* number of groups in @groups147147+ */148148+};149149+150150+/*151151+ * alloc_flex_gd() allocates a ext4_new_flex_group_data with size of152152+ * @flexbg_size.153153+ *154154+ * Returns NULL on failure otherwise address of the allocated structure.155155+ */156156+static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned long flexbg_size)157157+{158158+ struct ext4_new_flex_group_data *flex_gd;159159+160160+ flex_gd = kmalloc(sizeof(*flex_gd), GFP_NOFS);161161+ if (flex_gd == NULL)162162+ goto out3;163163+164164+ flex_gd->count = flexbg_size;165165+166166+ flex_gd->groups = kmalloc(sizeof(struct ext4_new_group_data) *167167+ flexbg_size, GFP_NOFS);168168+ if (flex_gd->groups == NULL)169169+ goto out2;170170+171171+ flex_gd->bg_flags = kmalloc(flexbg_size * sizeof(__u16), GFP_NOFS);172172+ if (flex_gd->bg_flags == NULL)173173+ goto out1;174174+175175+ return flex_gd;176176+177177+out1:178178+ kfree(flex_gd->groups);179179+out2:180180+ kfree(flex_gd);181181+out3:182182+ return NULL;183183+}184184+185185+static void free_flex_gd(struct ext4_new_flex_group_data *flex_gd)186186+{187187+ kfree(flex_gd->bg_flags);188188+ kfree(flex_gd->groups);189189+ kfree(flex_gd);190190+}191191+192192+/*193193+ * ext4_alloc_group_tables() allocates block bitmaps, inode bitmaps194194+ * and inode tables for a flex group.195195+ *196196+ * This function is used by 64bit-resize. Note that this function allocates197197+ * group tables from the 1st group of groups contained by @flexgd, which may198198+ * be a partial of a flex group.199199+ *200200+ * @sb: super block of fs to which the groups belongs201201+ */202202+static void ext4_alloc_group_tables(struct super_block *sb,203203+ struct ext4_new_flex_group_data *flex_gd,204204+ int flexbg_size)205205+{206206+ struct ext4_new_group_data *group_data = flex_gd->groups;207207+ struct ext4_super_block *es = EXT4_SB(sb)->s_es;208208+ ext4_fsblk_t start_blk;209209+ ext4_fsblk_t last_blk;210210+ ext4_group_t src_group;211211+ ext4_group_t bb_index = 0;212212+ ext4_group_t ib_index = 0;213213+ ext4_group_t it_index = 0;214214+ ext4_group_t group;215215+ ext4_group_t last_group;216216+ unsigned overhead;217217+218218+ BUG_ON(flex_gd->count == 0 || group_data == NULL);219219+220220+ src_group = group_data[0].group;221221+ last_group = src_group + flex_gd->count - 1;222222+223223+ BUG_ON((flexbg_size > 1) && ((src_group & ~(flexbg_size - 1)) !=224224+ (last_group & ~(flexbg_size - 1))));225225+next_group:226226+ group = group_data[0].group;227227+ start_blk = ext4_group_first_block_no(sb, src_group);228228+ last_blk = start_blk + group_data[src_group - group].blocks_count;229229+230230+ overhead = ext4_bg_has_super(sb, src_group) ?231231+ (1 + ext4_bg_num_gdb(sb, src_group) +232232+ le16_to_cpu(es->s_reserved_gdt_blocks)) : 0;233233+234234+ start_blk += overhead;235235+236236+ BUG_ON(src_group >= group_data[0].group + flex_gd->count);237237+ /* We collect contiguous blocks as much as possible. */238238+ src_group++;239239+ for (; src_group <= last_group; src_group++)240240+ if (!ext4_bg_has_super(sb, src_group))241241+ last_blk += group_data[src_group - group].blocks_count;242242+ else243243+ break;244244+245245+ /* Allocate block bitmaps */246246+ for (; bb_index < flex_gd->count; bb_index++) {247247+ if (start_blk >= last_blk)248248+ goto next_group;249249+ group_data[bb_index].block_bitmap = start_blk++;250250+ ext4_get_group_no_and_offset(sb, start_blk - 1, &group, NULL);251251+ group -= group_data[0].group;252252+ group_data[group].free_blocks_count--;253253+ if (flexbg_size > 1)254254+ flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT;255255+ }256256+257257+ /* Allocate inode bitmaps */258258+ for (; ib_index < flex_gd->count; ib_index++) {259259+ if (start_blk >= last_blk)260260+ goto next_group;261261+ group_data[ib_index].inode_bitmap = start_blk++;262262+ ext4_get_group_no_and_offset(sb, start_blk - 1, &group, NULL);263263+ group -= group_data[0].group;264264+ group_data[group].free_blocks_count--;265265+ if (flexbg_size > 1)266266+ flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT;267267+ }268268+269269+ /* Allocate inode tables */270270+ for (; it_index < flex_gd->count; it_index++) {271271+ if (start_blk + EXT4_SB(sb)->s_itb_per_group > last_blk)272272+ goto next_group;273273+ group_data[it_index].inode_table = start_blk;274274+ ext4_get_group_no_and_offset(sb, start_blk, &group, NULL);275275+ group -= group_data[0].group;276276+ group_data[group].free_blocks_count -=277277+ EXT4_SB(sb)->s_itb_per_group;278278+ if (flexbg_size > 1)279279+ flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT;280280+281281+ start_blk += EXT4_SB(sb)->s_itb_per_group;282282+ }283283+284284+ if (test_opt(sb, DEBUG)) {285285+ int i;286286+ group = group_data[0].group;287287+288288+ printk(KERN_DEBUG "EXT4-fs: adding a flex group with "289289+ "%d groups, flexbg size is %d:\n", flex_gd->count,290290+ flexbg_size);291291+292292+ for (i = 0; i < flex_gd->count; i++) {293293+ printk(KERN_DEBUG "adding %s group %u: %u "294294+ "blocks (%d free)\n",295295+ ext4_bg_has_super(sb, group + i) ? "normal" :296296+ "no-super", group + i,297297+ group_data[i].blocks_count,298298+ group_data[i].free_blocks_count);299299+ }300300+ }301301+}302302+137303static struct buffer_head *bclean(handle_t *handle, struct super_block *sb,138304 ext4_fsblk_t blk)139305{···345179}346180347181/*348348- * Set up the block and inode bitmaps, and the inode table for the new group.182182+ * set_flexbg_block_bitmap() mark @count blocks starting from @block used.183183+ *184184+ * Helper function for ext4_setup_new_group_blocks() which set .185185+ *186186+ * @sb: super block187187+ * @handle: journal handle188188+ * @flex_gd: flex group data189189+ */190190+static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle,191191+ struct ext4_new_flex_group_data *flex_gd,192192+ ext4_fsblk_t block, ext4_group_t count)193193+{194194+ ext4_group_t count2;195195+196196+ ext4_debug("mark blocks [%llu/%u] used\n", block, count);197197+ for (count2 = count; count > 0; count -= count2, block += count2) {198198+ ext4_fsblk_t start;199199+ struct buffer_head *bh;200200+ ext4_group_t group;201201+ int err;202202+203203+ ext4_get_group_no_and_offset(sb, block, &group, NULL);204204+ start = ext4_group_first_block_no(sb, group);205205+ group -= flex_gd->groups[0].group;206206+207207+ count2 = sb->s_blocksize * 8 - (block - start);208208+ if (count2 > count)209209+ count2 = count;210210+211211+ if (flex_gd->bg_flags[group] & EXT4_BG_BLOCK_UNINIT) {212212+ BUG_ON(flex_gd->count > 1);213213+ continue;214214+ }215215+216216+ err = extend_or_restart_transaction(handle, 1);217217+ if (err)218218+ return err;219219+220220+ bh = sb_getblk(sb, flex_gd->groups[group].block_bitmap);221221+ if (!bh)222222+ return -EIO;223223+224224+ err = ext4_journal_get_write_access(handle, bh);225225+ if (err)226226+ return err;227227+ ext4_debug("mark block bitmap %#04llx (+%llu/%u)\n", block,228228+ block - start, count2);229229+ ext4_set_bits(bh->b_data, block - start, count2);230230+231231+ err = ext4_handle_dirty_metadata(handle, NULL, bh);232232+ if (unlikely(err))233233+ return err;234234+ brelse(bh);235235+ }236236+237237+ return 0;238238+}239239+240240+/*241241+ * Set up the block and inode bitmaps, and the inode table for the new groups.349242 * This doesn't need to be part of the main transaction, since we are only350243 * changing blocks outside the actual filesystem. We still do journaling to351244 * ensure the recovery is correct in case of a failure just after resize.352245 * If any part of this fails, we simply abort the resize.246246+ *247247+ * setup_new_flex_group_blocks handles a flex group as follow:248248+ * 1. copy super block and GDT, and initialize group tables if necessary.249249+ * In this step, we only set bits in blocks bitmaps for blocks taken by250250+ * super block and GDT.251251+ * 2. allocate group tables in block bitmaps, that is, set bits in block252252+ * bitmap for blocks taken by group tables.353253 */354354-static int setup_new_group_blocks(struct super_block *sb,355355- struct ext4_new_group_data *input)254254+static int setup_new_flex_group_blocks(struct super_block *sb,255255+ struct ext4_new_flex_group_data *flex_gd)356256{357357- struct ext4_sb_info *sbi = EXT4_SB(sb);358358- ext4_fsblk_t start = ext4_group_first_block_no(sb, input->group);359359- int reserved_gdb = ext4_bg_has_super(sb, input->group) ?360360- le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) : 0;361361- unsigned long gdblocks = ext4_bg_num_gdb(sb, input->group);362362- struct buffer_head *bh;363363- handle_t *handle;257257+ int group_table_count[] = {1, 1, EXT4_SB(sb)->s_itb_per_group};258258+ ext4_fsblk_t start;364259 ext4_fsblk_t block;365365- ext4_grpblk_t bit;366366- int i;367367- int err = 0, err2;260260+ struct ext4_sb_info *sbi = EXT4_SB(sb);261261+ struct ext4_super_block *es = sbi->s_es;262262+ struct ext4_new_group_data *group_data = flex_gd->groups;263263+ __u16 *bg_flags = flex_gd->bg_flags;264264+ handle_t *handle;265265+ ext4_group_t group, count;266266+ struct buffer_head *bh = NULL;267267+ int reserved_gdb, i, j, err = 0, err2;268268+269269+ BUG_ON(!flex_gd->count || !group_data ||270270+ group_data[0].group != sbi->s_groups_count);271271+272272+ reserved_gdb = le16_to_cpu(es->s_reserved_gdt_blocks);368273369274 /* This transaction may be extended/restarted along the way */370275 handle = ext4_journal_start_sb(sb, EXT4_MAX_TRANS_DATA);371371-372276 if (IS_ERR(handle))373277 return PTR_ERR(handle);374278375375- BUG_ON(input->group != sbi->s_groups_count);279279+ group = group_data[0].group;280280+ for (i = 0; i < flex_gd->count; i++, group++) {281281+ unsigned long gdblocks;376282377377- /* Copy all of the GDT blocks into the backup in this group */378378- for (i = 0, bit = 1, block = start + 1;379379- i < gdblocks; i++, block++, bit++) {380380- struct buffer_head *gdb;283283+ gdblocks = ext4_bg_num_gdb(sb, group);284284+ start = ext4_group_first_block_no(sb, group);381285382382- ext4_debug("update backup group %#04llx (+%d)\n", block, bit);286286+ /* Copy all of the GDT blocks into the backup in this group */287287+ for (j = 0, block = start + 1; j < gdblocks; j++, block++) {288288+ struct buffer_head *gdb;289289+290290+ ext4_debug("update backup group %#04llx\n", block);291291+ err = extend_or_restart_transaction(handle, 1);292292+ if (err)293293+ goto out;294294+295295+ gdb = sb_getblk(sb, block);296296+ if (!gdb) {297297+ err = -EIO;298298+ goto out;299299+ }300300+301301+ err = ext4_journal_get_write_access(handle, gdb);302302+ if (err) {303303+ brelse(gdb);304304+ goto out;305305+ }306306+ memcpy(gdb->b_data, sbi->s_group_desc[j]->b_data,307307+ gdb->b_size);308308+ set_buffer_uptodate(gdb);309309+310310+ err = ext4_handle_dirty_metadata(handle, NULL, gdb);311311+ if (unlikely(err)) {312312+ brelse(gdb);313313+ goto out;314314+ }315315+ brelse(gdb);316316+ }317317+318318+ /* Zero out all of the reserved backup group descriptor319319+ * table blocks320320+ */321321+ if (ext4_bg_has_super(sb, group)) {322322+ err = sb_issue_zeroout(sb, gdblocks + start + 1,323323+ reserved_gdb, GFP_NOFS);324324+ if (err)325325+ goto out;326326+ }327327+328328+ /* Initialize group tables of the grop @group */329329+ if (!(bg_flags[i] & EXT4_BG_INODE_ZEROED))330330+ goto handle_bb;331331+332332+ /* Zero out all of the inode table blocks */333333+ block = group_data[i].inode_table;334334+ ext4_debug("clear inode table blocks %#04llx -> %#04lx\n",335335+ block, sbi->s_itb_per_group);336336+ err = sb_issue_zeroout(sb, block, sbi->s_itb_per_group,337337+ GFP_NOFS);338338+ if (err)339339+ goto out;340340+341341+handle_bb:342342+ if (bg_flags[i] & EXT4_BG_BLOCK_UNINIT)343343+ goto handle_ib;344344+345345+ /* Initialize block bitmap of the @group */346346+ block = group_data[i].block_bitmap;383347 err = extend_or_restart_transaction(handle, 1);384348 if (err)385385- goto exit_journal;349349+ goto out;386350387387- gdb = sb_getblk(sb, block);388388- if (!gdb) {389389- err = -EIO;390390- goto exit_journal;351351+ bh = bclean(handle, sb, block);352352+ if (IS_ERR(bh)) {353353+ err = PTR_ERR(bh);354354+ goto out;391355 }392392- if ((err = ext4_journal_get_write_access(handle, gdb))) {393393- brelse(gdb);394394- goto exit_journal;356356+ if (ext4_bg_has_super(sb, group)) {357357+ ext4_debug("mark backup superblock %#04llx (+0)\n",358358+ start);359359+ ext4_set_bits(bh->b_data, 0, gdblocks + reserved_gdb +360360+ 1);395361 }396396- memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, gdb->b_size);397397- set_buffer_uptodate(gdb);398398- err = ext4_handle_dirty_metadata(handle, NULL, gdb);399399- if (unlikely(err)) {400400- brelse(gdb);401401- goto exit_journal;362362+ ext4_mark_bitmap_end(group_data[i].blocks_count,363363+ sb->s_blocksize * 8, bh->b_data);364364+ err = ext4_handle_dirty_metadata(handle, NULL, bh);365365+ if (err)366366+ goto out;367367+ brelse(bh);368368+369369+handle_ib:370370+ if (bg_flags[i] & EXT4_BG_INODE_UNINIT)371371+ continue;372372+373373+ /* Initialize inode bitmap of the @group */374374+ block = group_data[i].inode_bitmap;375375+ err = extend_or_restart_transaction(handle, 1);376376+ if (err)377377+ goto out;378378+ /* Mark unused entries in inode bitmap used */379379+ bh = bclean(handle, sb, block);380380+ if (IS_ERR(bh)) {381381+ err = PTR_ERR(bh);382382+ goto out;402383 }403403- brelse(gdb);384384+385385+ ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb),386386+ sb->s_blocksize * 8, bh->b_data);387387+ err = ext4_handle_dirty_metadata(handle, NULL, bh);388388+ if (err)389389+ goto out;390390+ brelse(bh);391391+ }392392+ bh = NULL;393393+394394+ /* Mark group tables in block bitmap */395395+ for (j = 0; j < GROUP_TABLE_COUNT; j++) {396396+ count = group_table_count[j];397397+ start = (&group_data[0].block_bitmap)[j];398398+ block = start;399399+ for (i = 1; i < flex_gd->count; i++) {400400+ block += group_table_count[j];401401+ if (block == (&group_data[i].block_bitmap)[j]) {402402+ count += group_table_count[j];403403+ continue;404404+ }405405+ err = set_flexbg_block_bitmap(sb, handle,406406+ flex_gd, start, count);407407+ if (err)408408+ goto out;409409+ count = group_table_count[j];410410+ start = group_data[i].block_bitmap;411411+ block = start;412412+ }413413+414414+ if (count) {415415+ err = set_flexbg_block_bitmap(sb, handle,416416+ flex_gd, start, count);417417+ if (err)418418+ goto out;419419+ }404420 }405421406406- /* Zero out all of the reserved backup group descriptor table blocks */407407- ext4_debug("clear inode table blocks %#04llx -> %#04lx\n",408408- block, sbi->s_itb_per_group);409409- err = sb_issue_zeroout(sb, gdblocks + start + 1, reserved_gdb,410410- GFP_NOFS);411411- if (err)412412- goto exit_journal;413413-414414- err = extend_or_restart_transaction(handle, 2);415415- if (err)416416- goto exit_journal;417417-418418- bh = bclean(handle, sb, input->block_bitmap);419419- if (IS_ERR(bh)) {420420- err = PTR_ERR(bh);421421- goto exit_journal;422422- }423423-424424- if (ext4_bg_has_super(sb, input->group)) {425425- ext4_debug("mark backup group tables %#04llx (+0)\n", start);426426- ext4_set_bits(bh->b_data, 0, gdblocks + reserved_gdb + 1);427427- }428428-429429- ext4_debug("mark block bitmap %#04llx (+%llu)\n", input->block_bitmap,430430- input->block_bitmap - start);431431- ext4_set_bit(input->block_bitmap - start, bh->b_data);432432- ext4_debug("mark inode bitmap %#04llx (+%llu)\n", input->inode_bitmap,433433- input->inode_bitmap - start);434434- ext4_set_bit(input->inode_bitmap - start, bh->b_data);435435-436436- /* Zero out all of the inode table blocks */437437- block = input->inode_table;438438- ext4_debug("clear inode table blocks %#04llx -> %#04lx\n",439439- block, sbi->s_itb_per_group);440440- err = sb_issue_zeroout(sb, block, sbi->s_itb_per_group, GFP_NOFS);441441- if (err)442442- goto exit_bh;443443- ext4_set_bits(bh->b_data, input->inode_table - start,444444- sbi->s_itb_per_group);445445-446446-447447- ext4_mark_bitmap_end(input->blocks_count, sb->s_blocksize * 8,448448- bh->b_data);449449- err = ext4_handle_dirty_metadata(handle, NULL, bh);450450- if (unlikely(err)) {451451- ext4_std_error(sb, err);452452- goto exit_bh;453453- }422422+out:454423 brelse(bh);455455- /* Mark unused entries in inode bitmap used */456456- ext4_debug("clear inode bitmap %#04llx (+%llu)\n",457457- input->inode_bitmap, input->inode_bitmap - start);458458- if (IS_ERR(bh = bclean(handle, sb, input->inode_bitmap))) {459459- err = PTR_ERR(bh);460460- goto exit_journal;461461- }462462-463463- ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8,464464- bh->b_data);465465- err = ext4_handle_dirty_metadata(handle, NULL, bh);466466- if (unlikely(err))467467- ext4_std_error(sb, err);468468-exit_bh:469469- brelse(bh);470470-471471-exit_journal:472472- if ((err2 = ext4_journal_stop(handle)) && !err)424424+ err2 = ext4_journal_stop(handle);425425+ if (err2 && !err)473426 err = err2;474427475428 return err;···636351 * groups in current filesystem that have BACKUPS, or -ve error code.637352 */638353static int verify_reserved_gdb(struct super_block *sb,354354+ ext4_group_t end,639355 struct buffer_head *primary)640356{641357 const ext4_fsblk_t blk = primary->b_blocknr;642642- const ext4_group_t end = EXT4_SB(sb)->s_groups_count;643358 unsigned three = 1;644359 unsigned five = 5;645360 unsigned seven = 7;···714429 if (!gdb_bh)715430 return -EIO;716431717717- gdbackups = verify_reserved_gdb(sb, gdb_bh);432432+ gdbackups = verify_reserved_gdb(sb, group, gdb_bh);718433 if (gdbackups < 0) {719434 err = gdbackups;720435 goto exit_bh;···877592 err = -EIO;878593 goto exit_bh;879594 }880880- if ((gdbackups = verify_reserved_gdb(sb, primary[res])) < 0) {595595+ gdbackups = verify_reserved_gdb(sb, group, primary[res]);596596+ if (gdbackups < 0) {881597 brelse(primary[res]);882598 err = gdbackups;883599 goto exit_bh;···1021735 }1022736}1023737738738+/*739739+ * ext4_add_new_descs() adds @count group descriptor of groups740740+ * starting at @group741741+ *742742+ * @handle: journal handle743743+ * @sb: super block744744+ * @group: the group no. of the first group desc to be added745745+ * @resize_inode: the resize inode746746+ * @count: number of group descriptors to be added747747+ */748748+static int ext4_add_new_descs(handle_t *handle, struct super_block *sb,749749+ ext4_group_t group, struct inode *resize_inode,750750+ ext4_group_t count)751751+{752752+ struct ext4_sb_info *sbi = EXT4_SB(sb);753753+ struct ext4_super_block *es = sbi->s_es;754754+ struct buffer_head *gdb_bh;755755+ int i, gdb_off, gdb_num, err = 0;756756+757757+ for (i = 0; i < count; i++, group++) {758758+ int reserved_gdb = ext4_bg_has_super(sb, group) ?759759+ le16_to_cpu(es->s_reserved_gdt_blocks) : 0;760760+761761+ gdb_off = group % EXT4_DESC_PER_BLOCK(sb);762762+ gdb_num = group / EXT4_DESC_PER_BLOCK(sb);763763+764764+ /*765765+ * We will only either add reserved group blocks to a backup group766766+ * or remove reserved blocks for the first group in a new group block.767767+ * Doing both would be mean more complex code, and sane people don't768768+ * use non-sparse filesystems anymore. This is already checked above.769769+ */770770+ if (gdb_off) {771771+ gdb_bh = sbi->s_group_desc[gdb_num];772772+ err = ext4_journal_get_write_access(handle, gdb_bh);773773+774774+ if (!err && reserved_gdb && ext4_bg_num_gdb(sb, group))775775+ err = reserve_backup_gdb(handle, resize_inode, group);776776+ } else777777+ err = add_new_gdb(handle, resize_inode, group);778778+ if (err)779779+ break;780780+ }781781+ return err;782782+}783783+784784+/*785785+ * ext4_setup_new_descs() will set up the group descriptor descriptors of a flex bg786786+ */787787+static int ext4_setup_new_descs(handle_t *handle, struct super_block *sb,788788+ struct ext4_new_flex_group_data *flex_gd)789789+{790790+ struct ext4_new_group_data *group_data = flex_gd->groups;791791+ struct ext4_group_desc *gdp;792792+ struct ext4_sb_info *sbi = EXT4_SB(sb);793793+ struct buffer_head *gdb_bh;794794+ ext4_group_t group;795795+ __u16 *bg_flags = flex_gd->bg_flags;796796+ int i, gdb_off, gdb_num, err = 0;797797+798798+799799+ for (i = 0; i < flex_gd->count; i++, group_data++, bg_flags++) {800800+ group = group_data->group;801801+802802+ gdb_off = group % EXT4_DESC_PER_BLOCK(sb);803803+ gdb_num = group / EXT4_DESC_PER_BLOCK(sb);804804+805805+ /*806806+ * get_write_access() has been called on gdb_bh by ext4_add_new_desc().807807+ */808808+ gdb_bh = sbi->s_group_desc[gdb_num];809809+ /* Update group descriptor block for new group */810810+ gdp = (struct ext4_group_desc *)((char *)gdb_bh->b_data +811811+ gdb_off * EXT4_DESC_SIZE(sb));812812+813813+ memset(gdp, 0, EXT4_DESC_SIZE(sb));814814+ ext4_block_bitmap_set(sb, gdp, group_data->block_bitmap);815815+ ext4_inode_bitmap_set(sb, gdp, group_data->inode_bitmap);816816+ ext4_inode_table_set(sb, gdp, group_data->inode_table);817817+ ext4_free_group_clusters_set(sb, gdp,818818+ EXT4_B2C(sbi, group_data->free_blocks_count));819819+ ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb));820820+ gdp->bg_flags = cpu_to_le16(*bg_flags);821821+ gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp);822822+823823+ err = ext4_handle_dirty_metadata(handle, NULL, gdb_bh);824824+ if (unlikely(err)) {825825+ ext4_std_error(sb, err);826826+ break;827827+ }828828+829829+ /*830830+ * We can allocate memory for mb_alloc based on the new group831831+ * descriptor832832+ */833833+ err = ext4_mb_add_groupinfo(sb, group, gdp);834834+ if (err)835835+ break;836836+ }837837+ return err;838838+}839839+840840+/*841841+ * ext4_update_super() updates the super block so that the newly added842842+ * groups can be seen by the filesystem.843843+ *844844+ * @sb: super block845845+ * @flex_gd: new added groups846846+ */847847+static void ext4_update_super(struct super_block *sb,848848+ struct ext4_new_flex_group_data *flex_gd)849849+{850850+ ext4_fsblk_t blocks_count = 0;851851+ ext4_fsblk_t free_blocks = 0;852852+ ext4_fsblk_t reserved_blocks = 0;853853+ struct ext4_new_group_data *group_data = flex_gd->groups;854854+ struct ext4_sb_info *sbi = EXT4_SB(sb);855855+ struct ext4_super_block *es = sbi->s_es;856856+ int i;857857+858858+ BUG_ON(flex_gd->count == 0 || group_data == NULL);859859+ /*860860+ * Make the new blocks and inodes valid next. We do this before861861+ * increasing the group count so that once the group is enabled,862862+ * all of its blocks and inodes are already valid.863863+ *864864+ * We always allocate group-by-group, then block-by-block or865865+ * inode-by-inode within a group, so enabling these866866+ * blocks/inodes before the group is live won't actually let us867867+ * allocate the new space yet.868868+ */869869+ for (i = 0; i < flex_gd->count; i++) {870870+ blocks_count += group_data[i].blocks_count;871871+ free_blocks += group_data[i].free_blocks_count;872872+ }873873+874874+ reserved_blocks = ext4_r_blocks_count(es) * 100;875875+ do_div(reserved_blocks, ext4_blocks_count(es));876876+ reserved_blocks *= blocks_count;877877+ do_div(reserved_blocks, 100);878878+879879+ ext4_blocks_count_set(es, ext4_blocks_count(es) + blocks_count);880880+ le32_add_cpu(&es->s_inodes_count, EXT4_INODES_PER_GROUP(sb) *881881+ flex_gd->count);882882+883883+ /*884884+ * We need to protect s_groups_count against other CPUs seeing885885+ * inconsistent state in the superblock.886886+ *887887+ * The precise rules we use are:888888+ *889889+ * * Writers must perform a smp_wmb() after updating all890890+ * dependent data and before modifying the groups count891891+ *892892+ * * Readers must perform an smp_rmb() after reading the groups893893+ * count and before reading any dependent data.894894+ *895895+ * NB. These rules can be relaxed when checking the group count896896+ * while freeing data, as we can only allocate from a block897897+ * group after serialising against the group count, and we can898898+ * only then free after serialising in turn against that899899+ * allocation.900900+ */901901+ smp_wmb();902902+903903+ /* Update the global fs size fields */904904+ sbi->s_groups_count += flex_gd->count;905905+906906+ /* Update the reserved block counts only once the new group is907907+ * active. */908908+ ext4_r_blocks_count_set(es, ext4_r_blocks_count(es) +909909+ reserved_blocks);910910+911911+ /* Update the free space counts */912912+ percpu_counter_add(&sbi->s_freeclusters_counter,913913+ EXT4_B2C(sbi, free_blocks));914914+ percpu_counter_add(&sbi->s_freeinodes_counter,915915+ EXT4_INODES_PER_GROUP(sb) * flex_gd->count);916916+917917+ if (EXT4_HAS_INCOMPAT_FEATURE(sb,918918+ EXT4_FEATURE_INCOMPAT_FLEX_BG) &&919919+ sbi->s_log_groups_per_flex) {920920+ ext4_group_t flex_group;921921+ flex_group = ext4_flex_group(sbi, group_data[0].group);922922+ atomic_add(EXT4_B2C(sbi, free_blocks),923923+ &sbi->s_flex_groups[flex_group].free_clusters);924924+ atomic_add(EXT4_INODES_PER_GROUP(sb) * flex_gd->count,925925+ &sbi->s_flex_groups[flex_group].free_inodes);926926+ }927927+928928+ if (test_opt(sb, DEBUG))929929+ printk(KERN_DEBUG "EXT4-fs: added group %u:"930930+ "%llu blocks(%llu free %llu reserved)\n", flex_gd->count,931931+ blocks_count, free_blocks, reserved_blocks);932932+}933933+934934+/* Add a flex group to an fs. Ensure we handle all possible error conditions935935+ * _before_ we start modifying the filesystem, because we cannot abort the936936+ * transaction and not have it write the data to disk.937937+ */938938+static int ext4_flex_group_add(struct super_block *sb,939939+ struct inode *resize_inode,940940+ struct ext4_new_flex_group_data *flex_gd)941941+{942942+ struct ext4_sb_info *sbi = EXT4_SB(sb);943943+ struct ext4_super_block *es = sbi->s_es;944944+ ext4_fsblk_t o_blocks_count;945945+ ext4_grpblk_t last;946946+ ext4_group_t group;947947+ handle_t *handle;948948+ unsigned reserved_gdb;949949+ int err = 0, err2 = 0, credit;950950+951951+ BUG_ON(!flex_gd->count || !flex_gd->groups || !flex_gd->bg_flags);952952+953953+ reserved_gdb = le16_to_cpu(es->s_reserved_gdt_blocks);954954+ o_blocks_count = ext4_blocks_count(es);955955+ ext4_get_group_no_and_offset(sb, o_blocks_count, &group, &last);956956+ BUG_ON(last);957957+958958+ err = setup_new_flex_group_blocks(sb, flex_gd);959959+ if (err)960960+ goto exit;961961+ /*962962+ * We will always be modifying at least the superblock and GDT963963+ * block. If we are adding a group past the last current GDT block,964964+ * we will also modify the inode and the dindirect block. If we965965+ * are adding a group with superblock/GDT backups we will also966966+ * modify each of the reserved GDT dindirect blocks.967967+ */968968+ credit = flex_gd->count * 4 + reserved_gdb;969969+ handle = ext4_journal_start_sb(sb, credit);970970+ if (IS_ERR(handle)) {971971+ err = PTR_ERR(handle);972972+ goto exit;973973+ }974974+975975+ err = ext4_journal_get_write_access(handle, sbi->s_sbh);976976+ if (err)977977+ goto exit_journal;978978+979979+ group = flex_gd->groups[0].group;980980+ BUG_ON(group != EXT4_SB(sb)->s_groups_count);981981+ err = ext4_add_new_descs(handle, sb, group,982982+ resize_inode, flex_gd->count);983983+ if (err)984984+ goto exit_journal;985985+986986+ err = ext4_setup_new_descs(handle, sb, flex_gd);987987+ if (err)988988+ goto exit_journal;989989+990990+ ext4_update_super(sb, flex_gd);991991+992992+ err = ext4_handle_dirty_super(handle, sb);993993+994994+exit_journal:995995+ err2 = ext4_journal_stop(handle);996996+ if (!err)997997+ err = err2;998998+999999+ if (!err) {10001000+ int i;10011001+ update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es,10021002+ sizeof(struct ext4_super_block));10031003+ for (i = 0; i < flex_gd->count; i++, group++) {10041004+ struct buffer_head *gdb_bh;10051005+ int gdb_num;10061006+ gdb_num = group / EXT4_BLOCKS_PER_GROUP(sb);10071007+ gdb_bh = sbi->s_group_desc[gdb_num];10081008+ update_backups(sb, gdb_bh->b_blocknr, gdb_bh->b_data,10091009+ gdb_bh->b_size);10101010+ }10111011+ }10121012+exit:10131013+ return err;10141014+}10151015+10161016+static int ext4_setup_next_flex_gd(struct super_block *sb,10171017+ struct ext4_new_flex_group_data *flex_gd,10181018+ ext4_fsblk_t n_blocks_count,10191019+ unsigned long flexbg_size)10201020+{10211021+ struct ext4_super_block *es = EXT4_SB(sb)->s_es;10221022+ struct ext4_new_group_data *group_data = flex_gd->groups;10231023+ ext4_fsblk_t o_blocks_count;10241024+ ext4_group_t n_group;10251025+ ext4_group_t group;10261026+ ext4_group_t last_group;10271027+ ext4_grpblk_t last;10281028+ ext4_grpblk_t blocks_per_group;10291029+ unsigned long i;10301030+10311031+ blocks_per_group = EXT4_BLOCKS_PER_GROUP(sb);10321032+10331033+ o_blocks_count = ext4_blocks_count(es);10341034+10351035+ if (o_blocks_count == n_blocks_count)10361036+ return 0;10371037+10381038+ ext4_get_group_no_and_offset(sb, o_blocks_count, &group, &last);10391039+ BUG_ON(last);10401040+ ext4_get_group_no_and_offset(sb, n_blocks_count - 1, &n_group, &last);10411041+10421042+ last_group = group | (flexbg_size - 1);10431043+ if (last_group > n_group)10441044+ last_group = n_group;10451045+10461046+ flex_gd->count = last_group - group + 1;10471047+10481048+ for (i = 0; i < flex_gd->count; i++) {10491049+ int overhead;10501050+10511051+ group_data[i].group = group + i;10521052+ group_data[i].blocks_count = blocks_per_group;10531053+ overhead = ext4_bg_has_super(sb, group + i) ?10541054+ (1 + ext4_bg_num_gdb(sb, group + i) +10551055+ le16_to_cpu(es->s_reserved_gdt_blocks)) : 0;10561056+ group_data[i].free_blocks_count = blocks_per_group - overhead;10571057+ if (EXT4_HAS_RO_COMPAT_FEATURE(sb,10581058+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM))10591059+ flex_gd->bg_flags[i] = EXT4_BG_BLOCK_UNINIT |10601060+ EXT4_BG_INODE_UNINIT;10611061+ else10621062+ flex_gd->bg_flags[i] = EXT4_BG_INODE_ZEROED;10631063+ }10641064+10651065+ if (last_group == n_group &&10661066+ EXT4_HAS_RO_COMPAT_FEATURE(sb,10671067+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM))10681068+ /* We need to initialize block bitmap of last group. */10691069+ flex_gd->bg_flags[i - 1] &= ~EXT4_BG_BLOCK_UNINIT;10701070+10711071+ if ((last_group == n_group) && (last != blocks_per_group - 1)) {10721072+ group_data[i - 1].blocks_count = last + 1;10731073+ group_data[i - 1].free_blocks_count -= blocks_per_group-10741074+ last - 1;10751075+ }10761076+10771077+ return 1;10781078+}10791079+10241080/* Add group descriptor data to an existing or new group descriptor block.10251081 * Ensure we handle all possible error conditions _before_ we start modifying10261082 * the filesystem, because we cannot abort the transaction and not have it···1378750 */1379751int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)1380752{753753+ struct ext4_new_flex_group_data flex_gd;1381754 struct ext4_sb_info *sbi = EXT4_SB(sb);1382755 struct ext4_super_block *es = sbi->s_es;1383756 int reserved_gdb = ext4_bg_has_super(sb, input->group) ?1384757 le16_to_cpu(es->s_reserved_gdt_blocks) : 0;13851385- struct buffer_head *primary = NULL;13861386- struct ext4_group_desc *gdp;1387758 struct inode *inode = NULL;13881388- handle_t *handle;1389759 int gdb_off, gdb_num;13901390- int err, err2;760760+ int err;761761+ __u16 bg_flags = 0;13917621392763 gdb_num = input->group / EXT4_DESC_PER_BLOCK(sb);1393764 gdb_off = input->group % EXT4_DESC_PER_BLOCK(sb);···1425798 }1426799142780014281428- if ((err = verify_group_input(sb, input)))14291429- goto exit_put;14301430-14311431- if ((err = setup_new_group_blocks(sb, input)))14321432- goto exit_put;14331433-14341434- /*14351435- * We will always be modifying at least the superblock and a GDT14361436- * block. If we are adding a group past the last current GDT block,14371437- * we will also modify the inode and the dindirect block. If we14381438- * are adding a group with superblock/GDT backups we will also14391439- * modify each of the reserved GDT dindirect blocks.14401440- */14411441- handle = ext4_journal_start_sb(sb,14421442- ext4_bg_has_super(sb, input->group) ?14431443- 3 + reserved_gdb : 4);14441444- if (IS_ERR(handle)) {14451445- err = PTR_ERR(handle);14461446- goto exit_put;14471447- }14481448-14491449- if ((err = ext4_journal_get_write_access(handle, sbi->s_sbh)))14501450- goto exit_journal;14511451-14521452- /*14531453- * We will only either add reserved group blocks to a backup group14541454- * or remove reserved blocks for the first group in a new group block.14551455- * Doing both would be mean more complex code, and sane people don't14561456- * use non-sparse filesystems anymore. This is already checked above.14571457- */14581458- if (gdb_off) {14591459- primary = sbi->s_group_desc[gdb_num];14601460- if ((err = ext4_journal_get_write_access(handle, primary)))14611461- goto exit_journal;14621462-14631463- if (reserved_gdb && ext4_bg_num_gdb(sb, input->group)) {14641464- err = reserve_backup_gdb(handle, inode, input->group);14651465- if (err)14661466- goto exit_journal;14671467- }14681468- } else {14691469- /*14701470- * Note that we can access new group descriptor block safely14711471- * only if add_new_gdb() succeeds.14721472- */14731473- err = add_new_gdb(handle, inode, input->group);14741474- if (err)14751475- goto exit_journal;14761476- primary = sbi->s_group_desc[gdb_num];14771477- }14781478-14791479- /*14801480- * OK, now we've set up the new group. Time to make it active.14811481- *14821482- * so we have to be safe wrt. concurrent accesses the group14831483- * data. So we need to be careful to set all of the relevant14841484- * group descriptor data etc. *before* we enable the group.14851485- *14861486- * The key field here is sbi->s_groups_count: as long as14871487- * that retains its old value, nobody is going to access the new14881488- * group.14891489- *14901490- * So first we update all the descriptor metadata for the new14911491- * group; then we update the total disk blocks count; then we14921492- * update the groups count to enable the group; then finally we14931493- * update the free space counts so that the system can start14941494- * using the new disk blocks.14951495- */14961496-14971497- /* Update group descriptor block for new group */14981498- gdp = (struct ext4_group_desc *)((char *)primary->b_data +14991499- gdb_off * EXT4_DESC_SIZE(sb));15001500-15011501- memset(gdp, 0, EXT4_DESC_SIZE(sb));15021502- ext4_block_bitmap_set(sb, gdp, input->block_bitmap); /* LV FIXME */15031503- ext4_inode_bitmap_set(sb, gdp, input->inode_bitmap); /* LV FIXME */15041504- ext4_inode_table_set(sb, gdp, input->inode_table); /* LV FIXME */15051505- ext4_free_group_clusters_set(sb, gdp, input->free_blocks_count);15061506- ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb));15071507- gdp->bg_flags = cpu_to_le16(EXT4_BG_INODE_ZEROED);15081508- gdp->bg_checksum = ext4_group_desc_csum(sbi, input->group, gdp);15091509-15101510- /*15111511- * We can allocate memory for mb_alloc based on the new group15121512- * descriptor15131513- */15141514- err = ext4_mb_add_groupinfo(sb, input->group, gdp);801801+ err = verify_group_input(sb, input);1515802 if (err)15161516- goto exit_journal;803803+ goto out;151780415181518- /*15191519- * Make the new blocks and inodes valid next. We do this before15201520- * increasing the group count so that once the group is enabled,15211521- * all of its blocks and inodes are already valid.15221522- *15231523- * We always allocate group-by-group, then block-by-block or15241524- * inode-by-inode within a group, so enabling these15251525- * blocks/inodes before the group is live won't actually let us15261526- * allocate the new space yet.15271527- */15281528- ext4_blocks_count_set(es, ext4_blocks_count(es) +15291529- input->blocks_count);15301530- le32_add_cpu(&es->s_inodes_count, EXT4_INODES_PER_GROUP(sb));15311531-15321532- /*15331533- * We need to protect s_groups_count against other CPUs seeing15341534- * inconsistent state in the superblock.15351535- *15361536- * The precise rules we use are:15371537- *15381538- * * Writers must perform a smp_wmb() after updating all dependent15391539- * data and before modifying the groups count15401540- *15411541- * * Readers must perform an smp_rmb() after reading the groups count15421542- * and before reading any dependent data.15431543- *15441544- * NB. These rules can be relaxed when checking the group count15451545- * while freeing data, as we can only allocate from a block15461546- * group after serialising against the group count, and we can15471547- * only then free after serialising in turn against that15481548- * allocation.15491549- */15501550- smp_wmb();15511551-15521552- /* Update the global fs size fields */15531553- sbi->s_groups_count++;15541554-15551555- err = ext4_handle_dirty_metadata(handle, NULL, primary);15561556- if (unlikely(err)) {15571557- ext4_std_error(sb, err);15581558- goto exit_journal;15591559- }15601560-15611561- /* Update the reserved block counts only once the new group is15621562- * active. */15631563- ext4_r_blocks_count_set(es, ext4_r_blocks_count(es) +15641564- input->reserved_blocks);15651565-15661566- /* Update the free space counts */15671567- percpu_counter_add(&sbi->s_freeclusters_counter,15681568- EXT4_B2C(sbi, input->free_blocks_count));15691569- percpu_counter_add(&sbi->s_freeinodes_counter,15701570- EXT4_INODES_PER_GROUP(sb));15711571-15721572- if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG) &&15731573- sbi->s_log_groups_per_flex) {15741574- ext4_group_t flex_group;15751575- flex_group = ext4_flex_group(sbi, input->group);15761576- atomic_add(EXT4_B2C(sbi, input->free_blocks_count),15771577- &sbi->s_flex_groups[flex_group].free_clusters);15781578- atomic_add(EXT4_INODES_PER_GROUP(sb),15791579- &sbi->s_flex_groups[flex_group].free_inodes);15801580- }15811581-15821582- ext4_handle_dirty_super(handle, sb);15831583-15841584-exit_journal:15851585- if ((err2 = ext4_journal_stop(handle)) && !err)15861586- err = err2;15871587- if (!err && primary) {15881588- update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es,15891589- sizeof(struct ext4_super_block));15901590- update_backups(sb, primary->b_blocknr, primary->b_data,15911591- primary->b_size);15921592- }15931593-exit_put:805805+ flex_gd.count = 1;806806+ flex_gd.groups = input;807807+ flex_gd.bg_flags = &bg_flags;808808+ err = ext4_flex_group_add(sb, inode, &flex_gd);809809+out:1594810 iput(inode);1595811 return err;1596812} /* ext4_group_add */813813+814814+/*815815+ * extend a group without checking assuming that checking has been done.816816+ */817817+static int ext4_group_extend_no_check(struct super_block *sb,818818+ ext4_fsblk_t o_blocks_count, ext4_grpblk_t add)819819+{820820+ struct ext4_super_block *es = EXT4_SB(sb)->s_es;821821+ handle_t *handle;822822+ int err = 0, err2;823823+824824+ /* We will update the superblock, one block bitmap, and825825+ * one group descriptor via ext4_group_add_blocks().826826+ */827827+ handle = ext4_journal_start_sb(sb, 3);828828+ if (IS_ERR(handle)) {829829+ err = PTR_ERR(handle);830830+ ext4_warning(sb, "error %d on journal start", err);831831+ return err;832832+ }833833+834834+ err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);835835+ if (err) {836836+ ext4_warning(sb, "error %d on journal write access", err);837837+ goto errout;838838+ }839839+840840+ ext4_blocks_count_set(es, o_blocks_count + add);841841+ ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count,842842+ o_blocks_count + add);843843+ /* We add the blocks to the bitmap and set the group need init bit */844844+ err = ext4_group_add_blocks(handle, sb, o_blocks_count, add);845845+ if (err)846846+ goto errout;847847+ ext4_handle_dirty_super(handle, sb);848848+ ext4_debug("freed blocks %llu through %llu\n", o_blocks_count,849849+ o_blocks_count + add);850850+errout:851851+ err2 = ext4_journal_stop(handle);852852+ if (err2 && !err)853853+ err = err2;854854+855855+ if (!err) {856856+ if (test_opt(sb, DEBUG))857857+ printk(KERN_DEBUG "EXT4-fs: extended group to %llu "858858+ "blocks\n", ext4_blocks_count(es));859859+ update_backups(sb, EXT4_SB(sb)->s_sbh->b_blocknr, (char *)es,860860+ sizeof(struct ext4_super_block));861861+ }862862+ return err;863863+}15978641598865/*1599866 * Extend the filesystem to the new number of blocks specified. This entry···1506985 ext4_grpblk_t last;1507986 ext4_grpblk_t add;1508987 struct buffer_head *bh;15091509- handle_t *handle;15101510- int err, err2;988988+ int err;1511989 ext4_group_t group;15129901513991 o_blocks_count = ext4_blocks_count(es);···15621042 }15631043 brelse(bh);1564104415651565- /* We will update the superblock, one block bitmap, and15661566- * one group descriptor via ext4_free_blocks().15671567- */15681568- handle = ext4_journal_start_sb(sb, 3);15691569- if (IS_ERR(handle)) {15701570- err = PTR_ERR(handle);15711571- ext4_warning(sb, "error %d on journal start", err);15721572- goto exit_put;15731573- }15741574-15751575- if ((err = ext4_journal_get_write_access(handle,15761576- EXT4_SB(sb)->s_sbh))) {15771577- ext4_warning(sb, "error %d on journal write access", err);15781578- ext4_journal_stop(handle);15791579- goto exit_put;15801580- }15811581- ext4_blocks_count_set(es, o_blocks_count + add);15821582- ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count,15831583- o_blocks_count + add);15841584- /* We add the blocks to the bitmap and set the group need init bit */15851585- err = ext4_group_add_blocks(handle, sb, o_blocks_count, add);15861586- ext4_handle_dirty_super(handle, sb);15871587- ext4_debug("freed blocks %llu through %llu\n", o_blocks_count,15881588- o_blocks_count + add);15891589- err2 = ext4_journal_stop(handle);15901590- if (!err && err2)15911591- err = err2;15921592-15931593- if (err)15941594- goto exit_put;15951595-15961596- if (test_opt(sb, DEBUG))15971597- printk(KERN_DEBUG "EXT4-fs: extended group to %llu blocks\n",15981598- ext4_blocks_count(es));15991599- update_backups(sb, EXT4_SB(sb)->s_sbh->b_blocknr, (char *)es,16001600- sizeof(struct ext4_super_block));16011601-exit_put:10451045+ err = ext4_group_extend_no_check(sb, o_blocks_count, add);16021046 return err;16031047} /* ext4_group_extend */10481048+10491049+/*10501050+ * ext4_resize_fs() resizes a fs to new size specified by @n_blocks_count10511051+ *10521052+ * @sb: super block of the fs to be resized10531053+ * @n_blocks_count: the number of blocks resides in the resized fs10541054+ */10551055+int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)10561056+{10571057+ struct ext4_new_flex_group_data *flex_gd = NULL;10581058+ struct ext4_sb_info *sbi = EXT4_SB(sb);10591059+ struct ext4_super_block *es = sbi->s_es;10601060+ struct buffer_head *bh;10611061+ struct inode *resize_inode;10621062+ ext4_fsblk_t o_blocks_count;10631063+ ext4_group_t o_group;10641064+ ext4_group_t n_group;10651065+ ext4_grpblk_t offset;10661066+ unsigned long n_desc_blocks;10671067+ unsigned long o_desc_blocks;10681068+ unsigned long desc_blocks;10691069+ int err = 0, flexbg_size = 1;10701070+10711071+ o_blocks_count = ext4_blocks_count(es);10721072+10731073+ if (test_opt(sb, DEBUG))10741074+ printk(KERN_DEBUG "EXT4-fs: resizing filesystem from %llu "10751075+ "upto %llu blocks\n", o_blocks_count, n_blocks_count);10761076+10771077+ if (n_blocks_count < o_blocks_count) {10781078+ /* On-line shrinking not supported */10791079+ ext4_warning(sb, "can't shrink FS - resize aborted");10801080+ return -EINVAL;10811081+ }10821082+10831083+ if (n_blocks_count == o_blocks_count)10841084+ /* Nothing need to do */10851085+ return 0;10861086+10871087+ ext4_get_group_no_and_offset(sb, n_blocks_count - 1, &n_group, &offset);10881088+ ext4_get_group_no_and_offset(sb, o_blocks_count, &o_group, &offset);10891089+10901090+ n_desc_blocks = (n_group + EXT4_DESC_PER_BLOCK(sb)) /10911091+ EXT4_DESC_PER_BLOCK(sb);10921092+ o_desc_blocks = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /10931093+ EXT4_DESC_PER_BLOCK(sb);10941094+ desc_blocks = n_desc_blocks - o_desc_blocks;10951095+10961096+ if (desc_blocks &&10971097+ (!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_RESIZE_INODE) ||10981098+ le16_to_cpu(es->s_reserved_gdt_blocks) < desc_blocks)) {10991099+ ext4_warning(sb, "No reserved GDT blocks, can't resize");11001100+ return -EPERM;11011101+ }11021102+11031103+ resize_inode = ext4_iget(sb, EXT4_RESIZE_INO);11041104+ if (IS_ERR(resize_inode)) {11051105+ ext4_warning(sb, "Error opening resize inode");11061106+ return PTR_ERR(resize_inode);11071107+ }11081108+11091109+ /* See if the device is actually as big as what was requested */11101110+ bh = sb_bread(sb, n_blocks_count - 1);11111111+ if (!bh) {11121112+ ext4_warning(sb, "can't read last block, resize aborted");11131113+ return -ENOSPC;11141114+ }11151115+ brelse(bh);11161116+11171117+ if (offset != 0) {11181118+ /* extend the last group */11191119+ ext4_grpblk_t add;11201120+ add = EXT4_BLOCKS_PER_GROUP(sb) - offset;11211121+ err = ext4_group_extend_no_check(sb, o_blocks_count, add);11221122+ if (err)11231123+ goto out;11241124+ }11251125+11261126+ if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG) &&11271127+ es->s_log_groups_per_flex)11281128+ flexbg_size = 1 << es->s_log_groups_per_flex;11291129+11301130+ o_blocks_count = ext4_blocks_count(es);11311131+ if (o_blocks_count == n_blocks_count)11321132+ goto out;11331133+11341134+ flex_gd = alloc_flex_gd(flexbg_size);11351135+ if (flex_gd == NULL) {11361136+ err = -ENOMEM;11371137+ goto out;11381138+ }11391139+11401140+ /* Add flex groups. Note that a regular group is a11411141+ * flex group with 1 group.11421142+ */11431143+ while (ext4_setup_next_flex_gd(sb, flex_gd, n_blocks_count,11441144+ flexbg_size)) {11451145+ ext4_alloc_group_tables(sb, flex_gd, flexbg_size);11461146+ err = ext4_flex_group_add(sb, resize_inode, flex_gd);11471147+ if (unlikely(err))11481148+ break;11491149+ }11501150+11511151+out:11521152+ if (flex_gd)11531153+ free_flex_gd(flex_gd);11541154+11551155+ iput(resize_inode);11561156+ if (test_opt(sb, DEBUG))11571157+ printk(KERN_DEBUG "EXT4-fs: resized filesystem from %llu "11581158+ "upto %llu blocks\n", o_blocks_count, n_blocks_count);11591159+ return err;11601160+}
+5-6
fs/ext4/super.c
···10951095 }10961096 if (sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME) {10971097 seq_printf(seq, ",max_batch_time=%u",10981098- (unsigned) sbi->s_min_batch_time);10981098+ (unsigned) sbi->s_max_batch_time);10991099 }1100110011011101 /*···20052005 struct ext4_group_desc *gdp = NULL;20062006 ext4_group_t flex_group_count;20072007 ext4_group_t flex_group;20082008- int groups_per_flex = 0;20082008+ unsigned int groups_per_flex = 0;20092009 size_t size;20102010 int i;2011201120122012 sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex;20132013- groups_per_flex = 1 << sbi->s_log_groups_per_flex;20142014-20152015- if (groups_per_flex < 2) {20132013+ if (sbi->s_log_groups_per_flex < 1 || sbi->s_log_groups_per_flex > 31) {20162014 sbi->s_log_groups_per_flex = 0;20172015 return 1;20182016 }20172017+ groups_per_flex = 1 << sbi->s_log_groups_per_flex;2019201820202019 /* We allocate both existing and potentially added groups */20212020 flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) +···35053506 * of the filesystem.35063507 */35073508 if (le32_to_cpu(es->s_first_data_block) >= ext4_blocks_count(es)) {35083508- ext4_msg(sb, KERN_WARNING, "bad geometry: first data"35093509+ ext4_msg(sb, KERN_WARNING, "bad geometry: first data "35093510 "block %u is beyond end of filesystem (%llu)",35103511 le32_to_cpu(es->s_first_data_block),35113512 ext4_blocks_count(es));
···430430 jbd_debug(3, "JBD2: commit phase 1\n");431431432432 /*433433+ * Clear revoked flag to reflect there is no revoked buffers434434+ * in the next transaction which is going to be started.435435+ */436436+ jbd2_clear_buffer_revoked_flags(journal);437437+438438+ /*433439 * Switch to a new revoke table.434440 */435441 jbd2_journal_switch_revoke_table(journal);
+34
fs/jbd2/revoke.c
···4747 * overwriting the new data. We don't even need to clear the revoke4848 * bit here.4949 *5050+ * We cache revoke status of a buffer in the current transaction in b_states5151+ * bits. As the name says, revokevalid flag indicates that the cached revoke5252+ * status of a buffer is valid and we can rely on the cached status.5353+ *5054 * Revoke information on buffers is a tri-state value:5155 *5256 * RevokeValid clear: no cached revoke status, need to look it up···480476 }481477 }482478 return did_revoke;479479+}480480+481481+/*482482+ * journal_clear_revoked_flag clears revoked flag of buffers in483483+ * revoke table to reflect there is no revoked buffers in the next484484+ * transaction which is going to be started.485485+ */486486+void jbd2_clear_buffer_revoked_flags(journal_t *journal)487487+{488488+ struct jbd2_revoke_table_s *revoke = journal->j_revoke;489489+ int i = 0;490490+491491+ for (i = 0; i < revoke->hash_size; i++) {492492+ struct list_head *hash_list;493493+ struct list_head *list_entry;494494+ hash_list = &revoke->hash_table[i];495495+496496+ list_for_each(list_entry, hash_list) {497497+ struct jbd2_revoke_record_s *record;498498+ struct buffer_head *bh;499499+ record = (struct jbd2_revoke_record_s *)list_entry;500500+ bh = __find_get_block(journal->j_fs_dev,501501+ record->blocknr,502502+ journal->j_blocksize);503503+ if (bh) {504504+ clear_buffer_revoked(bh);505505+ __brelse(bh);506506+ }507507+ }508508+ }483509}484510485511/* journal_switch_revoke table select j_revoke for next transaction