2 * tune2fs.c - Change the file system parameters on an ext2 file system
4 * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
5 * Laboratoire MASI, Institut Blaise Pascal
6 * Universite Pierre et Marie Curie (Paris VI)
8 * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
11 * This file may be redistributed under the terms of the GNU Public
19 * 93/10/31 - Added the -c option to change the maximal mount counts
20 * 93/12/14 - Added -l flag to list contents of superblock
21 * M.J.E. Mol (marcel@duteca.et.tudelft.nl)
22 * F.W. ten Wolde (franky@duteca.et.tudelft.nl)
23 * 93/12/29 - Added the -e option to change errors behavior
24 * 94/02/27 - Ported to use the ext2fs library
25 * 94/03/06 - Added the checks interval from Uwe Ohse (uwe@tirka.gun.de)
28 #define _XOPEN_SOURCE 600 /* for inclusion of strptime() */
44 #include <strings.h> /* for strcasecmp() */
46 #define _BSD_SOURCE /* for inclusion of strcasecmp() via <string.h> */
51 #include <sys/types.h>
55 #include "ext2fs/ext2_fs.h"
56 #include "ext2fs/ext2fs.h"
57 #include "et/com_err.h"
58 #include "uuid/uuid.h"
62 #include "blkid/blkid.h"
63 #include "quota/mkquota.h"
65 #include "../version.h"
66 #include "nls-enable.h"
68 #define QOPT_ENABLE (1)
69 #define QOPT_DISABLE (-1)
71 extern int ask_yn(const char *string, int def);
73 const char *program_name = "tune2fs";
75 char *new_label, *new_last_mounted, *new_UUID;
77 static int c_flag, C_flag, e_flag, f_flag, g_flag, i_flag, l_flag, L_flag;
78 static int m_flag, M_flag, Q_flag, r_flag, s_flag = -1, u_flag, U_flag, T_flag;
81 static time_t last_check_time;
82 static int print_label;
83 static int max_mount_count, mount_count, mount_flags;
84 static unsigned long interval;
85 static blk64_t reserved_blocks;
86 static double reserved_ratio;
87 static unsigned long resgid, resuid;
88 static unsigned short errors;
90 static char *features_cmd;
91 static char *mntopts_cmd;
92 static int stride, stripe_width;
93 static int stride_set, stripe_width_set;
94 static char *extended_cmd;
95 static unsigned long new_inode_size;
96 static char *ext_mount_opts;
97 static int usrquota, grpquota;
98 static int rewrite_checksums;
100 int journal_size, journal_flags;
101 char *journal_device;
102 static blk64_t journal_location = ~0LL;
104 static struct list_head blk_move_list;
107 struct list_head list;
113 static const char *please_fsck = N_("Please run e2fsck on the filesystem.\n");
114 static const char *please_dir_fsck =
115 N_("Please run e2fsck -D on the filesystem.\n");
117 #ifdef CONFIG_BUILD_FINDFS
118 void do_findfs(int argc, char **argv);
121 static void usage(void)
124 _("Usage: %s [-c max_mounts_count] [-e errors_behavior] "
126 "\t[-i interval[d|m|w]] [-j] [-J journal_options] [-l]\n"
127 "\t[-m reserved_blocks_percent] "
128 "[-o [^]mount_options[,...]] [-p mmp_update_interval]\n"
129 "\t[-r reserved_blocks_count] [-u user] [-C mount_count] "
130 "[-L volume_label]\n"
131 "\t[-M last_mounted_dir] [-O [^]feature[,...]]\n"
133 "\t[-Q quota_options]\n"
135 "\t[-E extended-option[,...]] [-T last_check_time] "
136 "[-U UUID]\n\t[ -I new_inode_size ] device\n"), program_name);
140 static __u32 ok_features[3] = {
142 EXT3_FEATURE_COMPAT_HAS_JOURNAL |
143 EXT2_FEATURE_COMPAT_DIR_INDEX,
145 EXT2_FEATURE_INCOMPAT_FILETYPE |
146 EXT3_FEATURE_INCOMPAT_EXTENTS |
147 EXT4_FEATURE_INCOMPAT_FLEX_BG |
148 EXT4_FEATURE_INCOMPAT_MMP,
150 EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
151 EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
152 EXT4_FEATURE_RO_COMPAT_DIR_NLINK|
153 EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|
154 EXT4_FEATURE_RO_COMPAT_GDT_CSUM |
155 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER |
157 EXT4_FEATURE_RO_COMPAT_QUOTA |
159 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM
162 static __u32 clear_ok_features[3] = {
164 EXT3_FEATURE_COMPAT_HAS_JOURNAL |
165 EXT2_FEATURE_COMPAT_RESIZE_INODE |
166 EXT2_FEATURE_COMPAT_DIR_INDEX,
168 EXT2_FEATURE_INCOMPAT_FILETYPE |
169 EXT4_FEATURE_INCOMPAT_FLEX_BG |
170 EXT4_FEATURE_INCOMPAT_MMP,
172 EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
173 EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
174 EXT4_FEATURE_RO_COMPAT_DIR_NLINK|
175 EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|
176 EXT4_FEATURE_RO_COMPAT_GDT_CSUM |
178 EXT4_FEATURE_RO_COMPAT_QUOTA |
180 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM
184 * Remove an external journal from the filesystem
186 static int remove_journal_device(ext2_filsys fs)
191 journal_superblock_t *jsb;
194 int commit_remove_journal = 0;
198 commit_remove_journal = 1; /* force removal even if error */
200 uuid_unparse(fs->super->s_journal_uuid, buf);
201 journal_path = blkid_get_devname(NULL, "UUID", buf);
205 ext2fs_find_block_device(fs->super->s_journal_dev);
207 goto no_valid_journal;
210 #ifdef CONFIG_TESTIO_DEBUG
211 if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
212 io_ptr = test_io_manager;
213 test_io_backing_manager = unix_io_manager;
216 io_ptr = unix_io_manager;
217 retval = ext2fs_open(journal_path, EXT2_FLAG_RW|
218 EXT2_FLAG_JOURNAL_DEV_OK, 0,
219 fs->blocksize, io_ptr, &jfs);
221 com_err(program_name, retval, "%s",
222 _("while trying to open external journal"));
223 goto no_valid_journal;
225 if (!(jfs->super->s_feature_incompat &
226 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
227 fprintf(stderr, _("%s is not a journal device.\n"),
229 goto no_valid_journal;
232 /* Get the journal superblock */
233 if ((retval = io_channel_read_blk64(jfs->io, 1, -1024, buf))) {
234 com_err(program_name, retval, "%s",
235 _("while reading journal superblock"));
236 goto no_valid_journal;
239 jsb = (journal_superblock_t *) buf;
240 if ((jsb->s_header.h_magic != (unsigned)ntohl(JFS_MAGIC_NUMBER)) ||
241 (jsb->s_header.h_blocktype != (unsigned)ntohl(JFS_SUPERBLOCK_V2))) {
242 fputs(_("Journal superblock not found!\n"), stderr);
243 goto no_valid_journal;
246 /* Find the filesystem UUID */
247 nr_users = ntohl(jsb->s_nr_users);
248 for (i = 0; i < nr_users; i++) {
249 if (memcmp(fs->super->s_uuid, &jsb->s_users[i * 16], 16) == 0)
253 fputs(_("Filesystem's UUID not found on journal device.\n"),
255 commit_remove_journal = 1;
256 goto no_valid_journal;
259 for (i = 0; i < nr_users; i++)
260 memcpy(&jsb->s_users[i * 16], &jsb->s_users[(i + 1) * 16], 16);
261 jsb->s_nr_users = htonl(nr_users);
263 /* Write back the journal superblock */
264 if ((retval = io_channel_write_blk64(jfs->io, 1, -1024, buf))) {
265 com_err(program_name, retval,
266 "while writing journal superblock.");
267 goto no_valid_journal;
270 commit_remove_journal = 1;
273 if (commit_remove_journal == 0) {
274 fputs(_("Cannot locate journal device. It was NOT removed\n"
275 "Use -f option to remove missing journal device.\n"),
279 fs->super->s_journal_dev = 0;
280 uuid_clear(fs->super->s_journal_uuid);
281 ext2fs_mark_super_dirty(fs);
282 fputs(_("Journal removed\n"), stdout);
288 /* Helper function for remove_journal_inode */
289 static int release_blocks_proc(ext2_filsys fs, blk64_t *blocknr,
290 e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
291 blk64_t ref_block EXT2FS_ATTR((unused)),
292 int ref_offset EXT2FS_ATTR((unused)),
293 void *private EXT2FS_ATTR((unused)))
299 ext2fs_unmark_block_bitmap2(fs->block_map, block);
300 group = ext2fs_group_of_blk2(fs, block);
301 ext2fs_bg_free_blocks_count_set(fs, group, ext2fs_bg_free_blocks_count(fs, group) + 1);
302 ext2fs_group_desc_csum_set(fs, group);
303 ext2fs_free_blocks_count_add(fs->super, EXT2FS_CLUSTER_RATIO(fs));
308 * Remove the journal inode from the filesystem
310 static errcode_t remove_journal_inode(ext2_filsys fs)
312 struct ext2_inode inode;
314 ino_t ino = fs->super->s_journal_inum;
316 retval = ext2fs_read_inode(fs, ino, &inode);
318 com_err(program_name, retval, "%s",
319 _("while reading journal inode"));
322 if (ino == EXT2_JOURNAL_INO) {
323 retval = ext2fs_read_bitmaps(fs);
325 com_err(program_name, retval, "%s",
326 _("while reading bitmaps"));
329 retval = ext2fs_block_iterate3(fs, ino,
330 BLOCK_FLAG_READ_ONLY, NULL,
331 release_blocks_proc, NULL);
333 com_err(program_name, retval, "%s",
334 _("while clearing journal inode"));
337 memset(&inode, 0, sizeof(inode));
338 ext2fs_mark_bb_dirty(fs);
339 fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
341 inode.i_flags &= ~EXT2_IMMUTABLE_FL;
342 retval = ext2fs_write_inode(fs, ino, &inode);
344 com_err(program_name, retval, "%s",
345 _("while writing journal inode"));
348 fs->super->s_journal_inum = 0;
349 ext2fs_mark_super_dirty(fs);
355 * Update the default mount options
357 static int update_mntopts(ext2_filsys fs, char *mntopts)
359 struct ext2_super_block *sb = fs->super;
361 if (e2p_edit_mntopts(mntopts, &sb->s_default_mount_opts, ~0)) {
362 fprintf(stderr, _("Invalid mount option set: %s\n"),
366 ext2fs_mark_super_dirty(fs);
371 static int check_fsck_needed(ext2_filsys fs)
373 if (fs->super->s_state & EXT2_VALID_FS)
375 printf("\n%s\n", _(please_fsck));
376 if (mount_flags & EXT2_MF_READONLY)
377 printf("%s", _("(and reboot afterwards!)\n"));
381 static void request_dir_fsck_afterwards(ext2_filsys fs)
383 static int requested;
387 fs->super->s_state &= ~EXT2_VALID_FS;
388 printf("\n%s\n", _(please_dir_fsck));
389 if (mount_flags & EXT2_MF_READONLY)
390 printf(_("(and reboot afterwards!)\n"));
393 static void request_fsck_afterwards(ext2_filsys fs)
395 static int requested = 0;
399 fs->super->s_state &= ~EXT2_VALID_FS;
400 printf("\n%s\n", _(please_fsck));
401 if (mount_flags & EXT2_MF_READONLY)
402 printf("%s", _("(and reboot afterwards!)\n"));
405 /* Rewrite extents */
406 static errcode_t rewrite_extents(ext2_filsys fs, ext2_ino_t ino,
407 struct ext2_inode *inode)
409 ext2_extent_handle_t handle;
410 struct ext2fs_extent extent;
411 int op = EXT2_EXTENT_ROOT;
414 if (!(inode->i_flags & EXT4_EXTENTS_FL))
417 errcode = ext2fs_extent_open(fs, ino, &handle);
422 errcode = ext2fs_extent_get(handle, op, &extent);
426 /* Root node is in the separately checksummed inode */
427 if (op == EXT2_EXTENT_ROOT) {
428 op = EXT2_EXTENT_NEXT;
431 op = EXT2_EXTENT_NEXT;
433 /* Only visit the first extent in each extent block */
434 if (extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)
436 errcode = ext2fs_extent_replace(handle, 0, &extent);
441 /* Ok if we run off the end */
442 if (errcode == EXT2_ET_EXTENT_NO_NEXT)
448 * Rewrite directory blocks with checksums
450 struct rewrite_dir_context {
457 static int rewrite_dir_block(ext2_filsys fs,
459 e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
460 blk64_t ref_block EXT2FS_ATTR((unused)),
461 int ref_offset EXT2FS_ATTR((unused)),
464 struct ext2_dx_countlimit *dcl = NULL;
465 struct rewrite_dir_context *ctx = priv_data;
466 int dcl_offset, changed = 0;
468 ctx->errcode = ext2fs_read_dir_block4(fs, *blocknr, ctx->buf, 0,
473 /* if htree node... */
475 ext2fs_get_dx_countlimit(fs, (struct ext2_dir_entry *)ctx->buf,
478 if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
479 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
480 /* Ensure limit is the max size */
481 int max_entries = (fs->blocksize - dcl_offset) /
482 sizeof(struct ext2_dx_entry);
483 if (ext2fs_le16_to_cpu(dcl->limit) != max_entries) {
485 dcl->limit = ext2fs_cpu_to_le16(max_entries);
488 /* If htree block is full then rebuild the dir */
489 if (ext2fs_le16_to_cpu(dcl->count) ==
490 ext2fs_le16_to_cpu(dcl->limit)) {
491 request_dir_fsck_afterwards(fs);
495 * Ensure dcl->limit is small enough to leave room for
498 int max_entries = (fs->blocksize - (dcl_offset +
499 sizeof(struct ext2_dx_tail))) /
500 sizeof(struct ext2_dx_entry);
501 if (ext2fs_le16_to_cpu(dcl->limit) != max_entries)
502 dcl->limit = ext2fs_cpu_to_le16(max_entries);
503 /* Always rewrite checksum */
507 unsigned int rec_len, name_size;
508 char *top = ctx->buf + fs->blocksize;
509 struct ext2_dir_entry *de = (struct ext2_dir_entry *)ctx->buf;
510 struct ext2_dir_entry *last_de = NULL, *penultimate_de = NULL;
512 /* Find last and penultimate dirent */
513 while ((char *)de < top) {
514 penultimate_de = last_de;
516 ctx->errcode = ext2fs_get_rec_len(fs, de, &rec_len);
517 if (!ctx->errcode && !rec_len)
518 ctx->errcode = EXT2_ET_DIR_CORRUPTED;
521 de = (struct ext2_dir_entry *)(((char *)de) + rec_len);
523 ctx->errcode = ext2fs_get_rec_len(fs, last_de, &rec_len);
526 name_size = ext2fs_dirent_name_len(last_de);
528 if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
529 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
532 if (last_de->inode ||
534 rec_len != sizeof(struct ext2_dir_entry_tail))
537 * The last dirent is unused and the right length to
538 * have stored a checksum. Erase it.
540 ctx->errcode = ext2fs_get_rec_len(fs, penultimate_de,
543 ctx->errcode = EXT2_ET_DIR_CORRUPTED;
546 ext2fs_set_rec_len(fs, rec_len +
547 sizeof(struct ext2_dir_entry_tail),
551 unsigned csum_size = sizeof(struct ext2_dir_entry_tail);
552 struct ext2_dir_entry_tail *t;
555 * If the last dirent looks like the tail, just update
558 if (!last_de->inode &&
559 rec_len == csum_size) {
560 t = (struct ext2_dir_entry_tail *)last_de;
561 t->det_reserved_name_len =
562 EXT2_DIR_NAME_LEN_CSUM;
567 name_size = (name_size & ~3) + 4;
568 /* If there's not enough space for the tail, e2fsck */
569 if (rec_len <= (8 + name_size + csum_size)) {
570 request_dir_fsck_afterwards(fs);
573 /* Shorten that last de and insert the tail */
574 ext2fs_set_rec_len(fs, rec_len - csum_size, last_de);
575 t = EXT2_DIRENT_TAIL(ctx->buf, fs->blocksize);
576 ext2fs_initialize_dirent_tail(fs, t);
578 /* Always update checksum */
587 ctx->errcode = ext2fs_write_dir_block4(fs, *blocknr, ctx->buf,
595 static errcode_t rewrite_directory(ext2_filsys fs, ext2_ino_t dir,
596 struct ext2_inode *inode)
599 struct rewrite_dir_context ctx;
601 retval = ext2fs_get_mem(fs->blocksize, &ctx.buf);
605 ctx.is_htree = (inode->i_flags & EXT2_INDEX_FL);
608 retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_READ_ONLY |
609 BLOCK_FLAG_DATA_ONLY,
610 0, rewrite_dir_block, &ctx);
612 ext2fs_free_mem(&ctx.buf);
620 * Forcibly set checksums in all inodes.
622 static void rewrite_inodes(ext2_filsys fs)
624 int length = EXT2_INODE_SIZE(fs->super);
625 struct ext2_inode *inode, *zero;
627 ext2_inode_scan scan;
630 blk64_t file_acl_block;
633 if (fs->super->s_creator_os != EXT2_OS_LINUX)
636 retval = ext2fs_open_inode_scan(fs, 0, &scan);
638 com_err("set_csum", retval, "while opening inode scan");
642 retval = ext2fs_get_mem(length, &inode);
644 com_err("set_csum", retval, "while allocating memory");
648 retval = ext2fs_get_memzero(length, &zero);
650 com_err("set_csum", retval, "while allocating memory");
654 retval = ext2fs_get_mem(fs->blocksize, &ea_buf);
656 com_err("set_csum", retval, "while allocating memory");
661 retval = ext2fs_get_next_inode_full(scan, &ino, inode, length);
663 com_err("set_csum", retval, "while getting next inode");
668 if (ext2fs_test_inode_bitmap2(fs->inode_map, ino)) {
671 if (memcmp(inode, zero, length) != 0) {
672 memset(inode, 0, length);
680 retval = ext2fs_write_inode_full(fs, ino, inode,
683 com_err("set_csum", retval, "while writing "
689 retval = rewrite_extents(fs, ino, inode);
691 com_err("rewrite_extents", retval,
692 "while rewriting extents");
696 if (LINUX_S_ISDIR(inode->i_mode)) {
697 retval = rewrite_directory(fs, ino, inode);
699 com_err("rewrite_directory", retval,
700 "while rewriting directories");
705 file_acl_block = ext2fs_file_acl_block(fs, inode);
708 retval = ext2fs_read_ext_attr3(fs, file_acl_block, ea_buf, ino);
710 com_err("rewrite_eablock", retval,
711 "while rewriting extended attribute");
714 retval = ext2fs_write_ext_attr3(fs, file_acl_block, ea_buf,
717 com_err("rewrite_eablock", retval,
718 "while rewriting extended attribute");
723 ext2fs_free_mem(&zero);
724 ext2fs_free_mem(&inode);
725 ext2fs_free_mem(&ea_buf);
726 ext2fs_close_inode_scan(scan);
729 static void rewrite_metadata_checksums(ext2_filsys fs)
734 fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
735 ext2fs_init_csum_seed(fs);
736 for (i = 0; i < fs->group_desc_count; i++)
737 ext2fs_group_desc_csum_set(fs, i);
738 retval = ext2fs_read_bitmaps(fs);
740 com_err("rewrite_metadata_checksums", retval,
741 "while reading bitmaps");
745 ext2fs_mark_ib_dirty(fs);
746 ext2fs_mark_bb_dirty(fs);
747 ext2fs_mmp_update2(fs, 1);
748 fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
749 fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
750 if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
751 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
752 fs->super->s_checksum_type = EXT2_CRC32C_CHKSUM;
754 fs->super->s_checksum_type = 0;
755 ext2fs_mark_super_dirty(fs);
758 static void enable_uninit_bg(ext2_filsys fs)
760 struct ext2_group_desc *gd;
763 for (i = 0; i < fs->group_desc_count; i++) {
764 gd = ext2fs_group_desc(fs, fs->group_desc, i);
765 gd->bg_itable_unused = 0;
766 gd->bg_flags = EXT2_BG_INODE_ZEROED;
767 ext2fs_group_desc_csum_set(fs, i);
769 fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
772 static errcode_t zero_empty_inodes(ext2_filsys fs)
774 int length = EXT2_INODE_SIZE(fs->super);
775 struct ext2_inode *inode;
776 ext2_inode_scan scan;
780 retval = ext2fs_open_inode_scan(fs, 0, &scan);
784 retval = ext2fs_get_mem(length, &inode);
789 retval = ext2fs_get_next_inode_full(scan, &ino, inode, length);
794 if (!ext2fs_test_inode_bitmap2(fs->inode_map, ino)) {
795 memset(inode, 0, length);
796 retval = ext2fs_write_inode_full(fs, ino, inode,
804 ext2fs_free_mem(&inode);
805 ext2fs_close_inode_scan(scan);
809 static void disable_uninit_bg(ext2_filsys fs, __u32 csum_feature_flag)
811 struct ext2_group_desc *gd;
817 /* Load bitmaps to ensure that the uninit ones get written out */
818 fs->super->s_feature_ro_compat |= csum_feature_flag;
819 retval = ext2fs_read_bitmaps(fs);
821 com_err("disable_uninit_bg", retval,
822 "while reading bitmaps");
825 ext2fs_mark_ib_dirty(fs);
826 ext2fs_mark_bb_dirty(fs);
827 fs->super->s_feature_ro_compat &= ~csum_feature_flag;
829 /* If we're only turning off uninit_bg, zero the inodes */
830 if (csum_feature_flag == EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
831 retval = zero_empty_inodes(fs);
833 com_err("disable_uninit_bg", retval,
834 "while zeroing unused inodes");
835 request_fsck_afterwards(fs);
839 /* The bbitmap is zeroed; we must mark group metadata blocks in use */
840 for (i = 0; i < fs->group_desc_count; i++) {
841 b = ext2fs_block_bitmap_loc(fs, i);
842 ext2fs_mark_block_bitmap2(fs->block_map, b);
843 b = ext2fs_inode_bitmap_loc(fs, i);
844 ext2fs_mark_block_bitmap2(fs->block_map, b);
846 retval = ext2fs_super_and_bgd_loc2(fs, i, &b, &c, &d, NULL);
847 if (retval == 0 && b)
848 ext2fs_mark_block_bitmap2(fs->block_map, b);
849 if (retval == 0 && c)
850 ext2fs_mark_block_bitmap2(fs->block_map, c);
851 if (retval == 0 && d)
852 ext2fs_mark_block_bitmap2(fs->block_map, d);
854 com_err("disable_uninit_bg", retval,
855 "while initializing block bitmaps");
856 request_fsck_afterwards(fs);
859 gd = ext2fs_group_desc(fs, fs->group_desc, i);
860 gd->bg_itable_unused = 0;
862 ext2fs_group_desc_csum_set(fs, i);
864 fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
865 ext2fs_mark_super_dirty(fs);
869 * Update the feature set as provided by the user.
871 static int update_feature_set(ext2_filsys fs, char *features)
873 struct ext2_super_block *sb = fs->super;
874 __u32 old_features[3];
876 unsigned int mask_err;
878 #define FEATURE_ON(type, mask) (!(old_features[(type)] & (mask)) && \
879 ((&sb->s_feature_compat)[(type)] & (mask)))
880 #define FEATURE_OFF(type, mask) ((old_features[(type)] & (mask)) && \
881 !((&sb->s_feature_compat)[(type)] & (mask)))
882 #define FEATURE_CHANGED(type, mask) ((mask) & \
883 (old_features[(type)] ^ (&sb->s_feature_compat)[(type)]))
885 old_features[E2P_FEATURE_COMPAT] = sb->s_feature_compat;
886 old_features[E2P_FEATURE_INCOMPAT] = sb->s_feature_incompat;
887 old_features[E2P_FEATURE_RO_INCOMPAT] = sb->s_feature_ro_compat;
889 if (e2p_edit_feature2(features, &sb->s_feature_compat,
890 ok_features, clear_ok_features,
891 &type_err, &mask_err)) {
894 _("Invalid filesystem option set: %s\n"),
896 else if (type_err & E2P_FEATURE_NEGATE_FLAG)
897 fprintf(stderr, _("Clearing filesystem feature '%s' "
899 e2p_feature2string(type_err &
900 E2P_FEATURE_TYPE_MASK,
903 fprintf(stderr, _("Setting filesystem feature '%s' "
905 e2p_feature2string(type_err, mask_err));
909 if (FEATURE_OFF(E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
910 if ((mount_flags & EXT2_MF_MOUNTED) &&
911 !(mount_flags & EXT2_MF_READONLY)) {
912 fputs(_("The has_journal feature may only be "
913 "cleared when the filesystem is\n"
914 "unmounted or mounted "
915 "read-only.\n"), stderr);
918 if ((sb->s_feature_incompat &
919 EXT3_FEATURE_INCOMPAT_RECOVER) &&
921 fputs(_("The needs_recovery flag is set. "
922 "Please run e2fsck before clearing\n"
923 "the has_journal flag.\n"), stderr);
926 if (sb->s_journal_inum) {
927 if (remove_journal_inode(fs))
930 if (sb->s_journal_dev) {
931 if (remove_journal_device(fs))
936 if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
937 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
938 if (sb->s_feature_incompat &
939 EXT2_FEATURE_INCOMPAT_META_BG) {
940 fputs(_("Setting filesystem feature 'sparse_super' "
941 "not supported\nfor filesystems with "
942 "the meta_bg feature enabled.\n"),
948 if (FEATURE_ON(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_MMP)) {
951 if ((mount_flags & EXT2_MF_MOUNTED) ||
952 (mount_flags & EXT2_MF_READONLY)) {
953 fputs(_("The multiple mount protection feature can't\n"
954 "be set if the filesystem is mounted or\n"
955 "read-only.\n"), stderr);
959 error = ext2fs_mmp_init(fs);
961 fputs(_("\nError while enabling multiple mount "
962 "protection feature."), stderr);
967 * We want to update group desc with the new free blocks count
969 fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
971 printf(_("Multiple mount protection has been enabled "
972 "with update interval %ds.\n"),
973 sb->s_mmp_update_interval);
976 if (FEATURE_OFF(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_MMP)) {
979 if (mount_flags & EXT2_MF_READONLY) {
980 fputs(_("The multiple mount protection feature cannot\n"
981 "be disabled if the filesystem is readonly.\n"),
986 error = ext2fs_read_bitmaps(fs);
988 fputs(_("Error while reading bitmaps\n"), stderr);
992 error = ext2fs_mmp_read(fs, sb->s_mmp_block, NULL);
994 struct mmp_struct *mmp_cmp = fs->mmp_cmp;
996 if (error == EXT2_ET_MMP_MAGIC_INVALID)
997 printf(_("Magic number in MMP block does not "
998 "match. expected: %x, actual: %x\n"),
999 EXT4_MMP_MAGIC, mmp_cmp->mmp_magic);
1001 com_err(program_name, error, "%s",
1002 _("while reading MMP block."));
1006 /* We need to force out the group descriptors as well */
1007 fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
1008 ext2fs_block_alloc_stats2(fs, sb->s_mmp_block, -1);
1010 sb->s_mmp_block = 0;
1011 sb->s_mmp_update_interval = 0;
1014 if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
1016 * If adding a journal flag, let the create journal
1017 * code below handle setting the flag and creating the
1018 * journal. We supply a default size if necessary.
1022 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1025 if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX)) {
1026 if (!sb->s_def_hash_version)
1027 sb->s_def_hash_version = EXT2_HASH_HALF_MD4;
1028 if (uuid_is_null((unsigned char *) sb->s_hash_seed))
1029 uuid_generate((unsigned char *) sb->s_hash_seed);
1032 if (FEATURE_OFF(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
1033 if (ext2fs_check_desc(fs)) {
1034 fputs(_("Clearing the flex_bg flag would "
1035 "cause the the filesystem to be\n"
1036 "inconsistent.\n"), stderr);
1041 if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
1042 EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
1043 if ((mount_flags & EXT2_MF_MOUNTED) &&
1044 !(mount_flags & EXT2_MF_READONLY)) {
1045 fputs(_("The huge_file feature may only be "
1046 "cleared when the filesystem is\n"
1047 "unmounted or mounted "
1048 "read-only.\n"), stderr);
1053 if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
1054 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
1055 if (check_fsck_needed(fs))
1057 rewrite_checksums = 1;
1058 /* metadata_csum supersedes uninit_bg */
1059 fs->super->s_feature_ro_compat &=
1060 ~EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
1062 /* if uninit_bg was previously off, rewrite group desc */
1063 if (!(old_features[E2P_FEATURE_RO_INCOMPAT] &
1064 EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
1065 enable_uninit_bg(fs);
1068 * Since metadata_csum supersedes uninit_bg, pretend like
1069 * uninit_bg has been off all along.
1071 old_features[E2P_FEATURE_RO_INCOMPAT] &=
1072 ~EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
1075 if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
1076 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
1077 if (check_fsck_needed(fs))
1079 rewrite_checksums = 1;
1081 * If we're turning off metadata_csum and not turning on
1082 * uninit_bg, rewrite group desc.
1084 if (!(fs->super->s_feature_ro_compat &
1085 EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
1086 disable_uninit_bg(fs,
1087 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
1090 * metadata_csum previously provided uninit_bg, so if
1091 * we're also setting the uninit_bg feature bit,
1092 * pretend like it was previously enabled. Checksums
1093 * will be rewritten with crc16 later.
1095 old_features[E2P_FEATURE_RO_INCOMPAT] |=
1096 EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
1099 if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
1100 EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
1101 /* Do not enable uninit_bg when metadata_csum enabled */
1102 if (fs->super->s_feature_ro_compat &
1103 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)
1104 fs->super->s_feature_ro_compat &=
1105 ~EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
1107 enable_uninit_bg(fs);
1110 if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
1111 EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
1112 disable_uninit_bg(fs,
1113 EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
1115 if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
1116 EXT4_FEATURE_RO_COMPAT_QUOTA)) {
1118 * Set the Q_flag here and handle the quota options in the code
1123 /* Enable both user quota and group quota by default */
1124 usrquota = QOPT_ENABLE;
1125 grpquota = QOPT_ENABLE;
1127 sb->s_feature_ro_compat &= ~EXT4_FEATURE_RO_COMPAT_QUOTA;
1130 if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
1131 EXT4_FEATURE_RO_COMPAT_QUOTA)) {
1133 * Set the Q_flag here and handle the quota options in the code
1137 fputs(_("\nWarning: '^quota' option overrides '-Q'"
1138 "arguments.\n"), stderr);
1140 /* Disable both user quota and group quota by default */
1141 usrquota = QOPT_DISABLE;
1142 grpquota = QOPT_DISABLE;
1145 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
1146 (sb->s_feature_compat || sb->s_feature_ro_compat ||
1147 sb->s_feature_incompat))
1148 ext2fs_update_dynamic_rev(fs);
1150 if (FEATURE_CHANGED(E2P_FEATURE_RO_INCOMPAT,
1151 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) ||
1152 FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
1153 EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
1154 FEATURE_CHANGED(E2P_FEATURE_INCOMPAT,
1155 EXT2_FEATURE_INCOMPAT_FILETYPE) ||
1156 FEATURE_CHANGED(E2P_FEATURE_COMPAT,
1157 EXT2_FEATURE_COMPAT_RESIZE_INODE) ||
1158 FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
1159 EXT2_FEATURE_RO_COMPAT_LARGE_FILE))
1160 request_fsck_afterwards(fs);
1162 if ((old_features[E2P_FEATURE_COMPAT] != sb->s_feature_compat) ||
1163 (old_features[E2P_FEATURE_INCOMPAT] != sb->s_feature_incompat) ||
1164 (old_features[E2P_FEATURE_RO_INCOMPAT] != sb->s_feature_ro_compat))
1165 ext2fs_mark_super_dirty(fs);
1171 * Add a journal to the filesystem.
1173 static int add_journal(ext2_filsys fs)
1175 unsigned long journal_blocks;
1180 if (fs->super->s_feature_compat &
1181 EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1182 fputs(_("The filesystem already has a journal.\n"), stderr);
1185 if (journal_device) {
1186 check_plausibility(journal_device);
1187 check_mount(journal_device, 0, _("journal"));
1188 #ifdef CONFIG_TESTIO_DEBUG
1189 if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
1190 io_ptr = test_io_manager;
1191 test_io_backing_manager = unix_io_manager;
1194 io_ptr = unix_io_manager;
1195 retval = ext2fs_open(journal_device, EXT2_FLAG_RW|
1196 EXT2_FLAG_JOURNAL_DEV_OK, 0,
1197 fs->blocksize, io_ptr, &jfs);
1199 com_err(program_name, retval,
1200 _("\n\twhile trying to open journal on %s\n"),
1204 printf(_("Creating journal on device %s: "),
1208 retval = ext2fs_add_journal_device(fs, jfs);
1211 com_err(program_name, retval,
1212 _("while adding filesystem to journal on %s"),
1216 fputs(_("done\n"), stdout);
1217 } else if (journal_size) {
1218 fputs(_("Creating journal inode: "), stdout);
1220 journal_blocks = figure_journal_size(journal_size, fs);
1222 if (journal_location_string)
1224 parse_num_blocks2(journal_location_string,
1225 fs->super->s_log_block_size);
1226 retval = ext2fs_add_journal_inode2(fs, journal_blocks,
1230 fprintf(stderr, "\n");
1231 com_err(program_name, retval, "%s",
1232 _("\n\twhile trying to create journal file"));
1235 fputs(_("done\n"), stdout);
1237 * If the filesystem wasn't mounted, we need to force
1238 * the block group descriptors out.
1240 if ((mount_flags & EXT2_MF_MOUNTED) == 0)
1241 fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
1243 print_check_message(fs->super->s_max_mnt_count,
1244 fs->super->s_checkinterval);
1248 free(journal_device);
1252 static void handle_quota_options(ext2_filsys fs)
1257 if (!usrquota && !grpquota)
1258 /* Nothing to do. */
1261 quota_init_context(&qctx, fs, -1);
1263 if (usrquota == QOPT_ENABLE || grpquota == QOPT_ENABLE)
1264 quota_compute_usage(qctx);
1266 if (usrquota == QOPT_ENABLE && !fs->super->s_usr_quota_inum) {
1267 if ((qf_ino = quota_file_exists(fs, USRQUOTA,
1269 quota_update_limits(qctx, qf_ino, USRQUOTA);
1270 quota_write_inode(qctx, USRQUOTA);
1271 } else if (usrquota == QOPT_DISABLE) {
1272 quota_remove_inode(fs, USRQUOTA);
1275 if (grpquota == QOPT_ENABLE && !fs->super->s_grp_quota_inum) {
1276 if ((qf_ino = quota_file_exists(fs, GRPQUOTA,
1278 quota_update_limits(qctx, qf_ino, GRPQUOTA);
1279 quota_write_inode(qctx, GRPQUOTA);
1280 } else if (grpquota == QOPT_DISABLE) {
1281 quota_remove_inode(fs, GRPQUOTA);
1284 quota_release_context(&qctx);
1286 if ((usrquota == QOPT_ENABLE) || (grpquota == QOPT_ENABLE)) {
1287 fprintf(stderr, "%s", _("\nWarning: the quota feature is still "
1288 "under development\n"
1289 "See https://ext4.wiki.kernel.org/"
1290 "index.php/Quota for more information\n\n"));
1291 fs->super->s_feature_ro_compat |= EXT4_FEATURE_RO_COMPAT_QUOTA;
1292 ext2fs_mark_super_dirty(fs);
1293 } else if (!fs->super->s_usr_quota_inum &&
1294 !fs->super->s_grp_quota_inum) {
1295 fs->super->s_feature_ro_compat &= ~EXT4_FEATURE_RO_COMPAT_QUOTA;
1296 ext2fs_mark_super_dirty(fs);
1303 static void parse_quota_opts(const char *opts)
1305 char *buf, *token, *next, *p;
1309 buf = malloc(len+1);
1311 fputs(_("Couldn't allocate memory to parse quota "
1312 "options!\n"), stderr);
1316 for (token = buf; token && *token; token = next) {
1317 p = strchr(token, ',');
1324 if (strcmp(token, "usrquota") == 0) {
1325 usrquota = QOPT_ENABLE;
1326 } else if (strcmp(token, "^usrquota") == 0) {
1327 usrquota = QOPT_DISABLE;
1328 } else if (strcmp(token, "grpquota") == 0) {
1329 grpquota = QOPT_ENABLE;
1330 } else if (strcmp(token, "^grpquota") == 0) {
1331 grpquota = QOPT_DISABLE;
1333 fputs(_("\nBad quota options specified.\n\n"
1334 "Following valid quota options are available "
1335 "(pass by separating with comma):\n"
1347 static void parse_e2label_options(int argc, char ** argv)
1349 if ((argc < 2) || (argc > 3)) {
1350 fputs(_("Usage: e2label device [newlabel]\n"), stderr);
1353 io_options = strchr(argv[1], '?');
1356 device_name = blkid_get_devname(NULL, argv[1], NULL);
1358 com_err("e2label", 0, _("Unable to resolve '%s'"),
1362 open_flag = EXT2_FLAG_JOURNAL_DEV_OK;
1364 open_flag |= EXT2_FLAG_RW;
1366 new_label = argv[2];
1371 static time_t parse_time(char *str)
1375 if (strcmp(str, "now") == 0) {
1378 memset(&ts, 0, sizeof(ts));
1379 #ifdef HAVE_STRPTIME
1380 strptime(str, "%Y%m%d%H%M%S", &ts);
1382 sscanf(str, "%4d%2d%2d%2d%2d%2d", &ts.tm_year, &ts.tm_mon,
1383 &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec);
1386 if (ts.tm_year < 0 || ts.tm_mon < 0 || ts.tm_mon > 11 ||
1387 ts.tm_mday < 0 || ts.tm_mday > 31 || ts.tm_hour > 23 ||
1388 ts.tm_min > 59 || ts.tm_sec > 61)
1391 if (ts.tm_mday == 0) {
1392 com_err(program_name, 0,
1393 _("Couldn't parse date/time specifier: %s"),
1398 return (mktime(&ts));
1401 static void parse_tune2fs_options(int argc, char **argv)
1407 char optstring[100] = "c:e:fg:i:jlm:o:r:s:u:C:E:I:J:L:M:O:T:U:";
1410 strcat(optstring, "Q:");
1414 printf("tune2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
1415 while ((c = getopt(argc, argv, optstring)) != EOF)
1418 max_mount_count = strtol(optarg, &tmp, 0);
1419 if (*tmp || max_mount_count > 16000) {
1420 com_err(program_name, 0,
1421 _("bad mounts count - %s"),
1425 if (max_mount_count == 0)
1426 max_mount_count = -1;
1428 open_flag = EXT2_FLAG_RW;
1431 mount_count = strtoul(optarg, &tmp, 0);
1432 if (*tmp || mount_count > 16000) {
1433 com_err(program_name, 0,
1434 _("bad mounts count - %s"),
1439 open_flag = EXT2_FLAG_RW;
1442 if (strcmp(optarg, "continue") == 0)
1443 errors = EXT2_ERRORS_CONTINUE;
1444 else if (strcmp(optarg, "remount-ro") == 0)
1445 errors = EXT2_ERRORS_RO;
1446 else if (strcmp(optarg, "panic") == 0)
1447 errors = EXT2_ERRORS_PANIC;
1449 com_err(program_name, 0,
1450 _("bad error behavior - %s"),
1455 open_flag = EXT2_FLAG_RW;
1458 extended_cmd = optarg;
1459 open_flag |= EXT2_FLAG_RW;
1461 case 'f': /* Force */
1465 resgid = strtoul(optarg, &tmp, 0);
1467 gr = getgrnam(optarg);
1471 resgid = gr->gr_gid;
1476 com_err(program_name, 0,
1477 _("bad gid/group name - %s"),
1482 open_flag = EXT2_FLAG_RW;
1485 interval = strtoul(optarg, &tmp, 0);
1492 case 'D': /* days */
1498 case 'M': /* months! */
1499 interval *= 86400 * 30;
1503 case 'W': /* weeks */
1504 interval *= 86400 * 7;
1509 com_err(program_name, 0,
1510 _("bad interval - %s"), optarg);
1514 open_flag = EXT2_FLAG_RW;
1519 open_flag = EXT2_FLAG_RW;
1522 parse_journal_opts(optarg);
1523 open_flag = EXT2_FLAG_RW;
1531 open_flag |= EXT2_FLAG_RW |
1532 EXT2_FLAG_JOURNAL_DEV_OK;
1535 reserved_ratio = strtod(optarg, &tmp);
1536 if (*tmp || reserved_ratio > 50 ||
1537 reserved_ratio < 0) {
1538 com_err(program_name, 0,
1539 _("bad reserved block ratio - %s"),
1544 open_flag = EXT2_FLAG_RW;
1547 new_last_mounted = optarg;
1549 open_flag = EXT2_FLAG_RW;
1553 com_err(program_name, 0, "%s",
1554 _("-o may only be specified once"));
1557 mntopts_cmd = optarg;
1558 open_flag = EXT2_FLAG_RW;
1562 com_err(program_name, 0, "%s",
1563 _("-O may only be specified once"));
1566 features_cmd = optarg;
1567 open_flag = EXT2_FLAG_RW;
1572 parse_quota_opts(optarg);
1573 open_flag = EXT2_FLAG_RW;
1577 reserved_blocks = strtoul(optarg, &tmp, 0);
1579 com_err(program_name, 0,
1580 _("bad reserved blocks count - %s"),
1585 open_flag = EXT2_FLAG_RW;
1587 case 's': /* Deprecated */
1588 s_flag = atoi(optarg);
1589 open_flag = EXT2_FLAG_RW;
1593 last_check_time = parse_time(optarg);
1594 open_flag = EXT2_FLAG_RW;
1597 resuid = strtoul(optarg, &tmp, 0);
1599 pw = getpwnam(optarg);
1603 resuid = pw->pw_uid;
1608 com_err(program_name, 0,
1609 _("bad uid/user name - %s"),
1614 open_flag = EXT2_FLAG_RW;
1619 open_flag = EXT2_FLAG_RW |
1620 EXT2_FLAG_JOURNAL_DEV_OK;
1623 new_inode_size = strtoul(optarg, &tmp, 0);
1625 com_err(program_name, 0,
1626 _("bad inode size - %s"),
1630 if (!((new_inode_size &
1631 (new_inode_size - 1)) == 0)) {
1632 com_err(program_name, 0,
1633 _("Inode size must be a "
1634 "power of two- %s"),
1638 open_flag = EXT2_FLAG_RW;
1644 if (optind < argc - 1 || optind == argc)
1646 if (!open_flag && !l_flag)
1648 io_options = strchr(argv[optind], '?');
1651 device_name = blkid_get_devname(NULL, argv[optind], NULL);
1653 com_err(program_name, 0, _("Unable to resolve '%s'"),
1659 #ifdef CONFIG_BUILD_FINDFS
1660 void do_findfs(int argc, char **argv)
1665 (strncmp(argv[1], "LABEL=", 6) && strncmp(argv[1], "UUID=", 5))) {
1666 fprintf(stderr, "Usage: findfs LABEL=<label>|UUID=<uuid>\n");
1669 dev = blkid_get_devname(NULL, argv[1], NULL);
1671 com_err("findfs", 0, _("Unable to resolve '%s'"),
1680 static int parse_extended_opts(ext2_filsys fs, const char *opts)
1682 char *buf, *token, *next, *p, *arg;
1687 buf = malloc(len+1);
1689 fprintf(stderr, "%s",
1690 _("Couldn't allocate memory to parse options!\n"));
1694 for (token = buf; token && *token; token = next) {
1695 p = strchr(token, ',');
1701 arg = strchr(token, '=');
1706 if (strcmp(token, "clear-mmp") == 0 ||
1707 strcmp(token, "clear_mmp") == 0) {
1709 } else if (strcmp(token, "mmp_update_interval") == 0) {
1715 intv = strtoul(arg, &p, 0);
1718 _("Invalid mmp_update_interval: %s\n"),
1724 intv = EXT4_MMP_UPDATE_INTERVAL;
1725 } else if (intv > EXT4_MMP_MAX_UPDATE_INTERVAL) {
1727 _("mmp_update_interval too big: %lu\n"),
1732 printf(P_("Setting multiple mount protection update "
1733 "interval to %lu second\n",
1734 "Setting multiple mount protection update "
1735 "interval to %lu seconds\n", intv),
1737 fs->super->s_mmp_update_interval = intv;
1738 ext2fs_mark_super_dirty(fs);
1739 } else if (!strcmp(token, "test_fs")) {
1740 fs->super->s_flags |= EXT2_FLAGS_TEST_FILESYS;
1741 printf("Setting test filesystem flag\n");
1742 ext2fs_mark_super_dirty(fs);
1743 } else if (!strcmp(token, "^test_fs")) {
1744 fs->super->s_flags &= ~EXT2_FLAGS_TEST_FILESYS;
1745 printf("Clearing test filesystem flag\n");
1746 ext2fs_mark_super_dirty(fs);
1747 } else if (strcmp(token, "stride") == 0) {
1752 stride = strtoul(arg, &p, 0);
1755 _("Invalid RAID stride: %s\n"),
1761 } else if (strcmp(token, "stripe-width") == 0 ||
1762 strcmp(token, "stripe_width") == 0) {
1767 stripe_width = strtoul(arg, &p, 0);
1770 _("Invalid RAID stripe-width: %s\n"),
1775 stripe_width_set = 1;
1776 } else if (strcmp(token, "hash_alg") == 0 ||
1777 strcmp(token, "hash-alg") == 0) {
1782 hash_alg = e2p_string2hash(arg);
1785 _("Invalid hash algorithm: %s\n"),
1790 fs->super->s_def_hash_version = hash_alg;
1791 printf(_("Setting default hash algorithm "
1794 ext2fs_mark_super_dirty(fs);
1795 } else if (!strcmp(token, "mount_opts")) {
1800 if (strlen(arg) >= sizeof(fs->super->s_mount_opts)) {
1802 "Extended mount options too long\n");
1805 ext_mount_opts = strdup(arg);
1810 fprintf(stderr, "%s", _("\nBad options specified.\n\n"
1811 "Extended options are separated by commas, "
1812 "and may take an argument which\n"
1813 "\tis set off by an equals ('=') sign.\n\n"
1814 "Valid extended options are:\n"
1816 "\thash_alg=<hash algorithm>\n"
1817 "\tmount_opts=<extended default mount options>\n"
1818 "\tstride=<RAID per-disk chunk size in blocks>\n"
1819 "\tstripe_width=<RAID stride*data disks in blocks>\n"
1831 * Fill in the block bitmap bmap with the information regarding the
1832 * blocks to be moved
1834 static int get_move_bitmaps(ext2_filsys fs, int new_ino_blks_per_grp,
1835 ext2fs_block_bitmap bmap)
1839 ext2_badblocks_list bb_list = 0;
1840 blk64_t j, needed_blocks = 0;
1841 blk64_t start_blk, end_blk;
1843 retval = ext2fs_read_bb_inode(fs, &bb_list);
1847 for (i = 0; i < fs->group_desc_count; i++) {
1848 start_blk = ext2fs_inode_table_loc(fs, i) +
1849 fs->inode_blocks_per_group;
1851 end_blk = ext2fs_inode_table_loc(fs, i) +
1852 new_ino_blks_per_grp;
1854 for (j = start_blk; j < end_blk; j++) {
1855 if (ext2fs_test_block_bitmap2(fs->block_map, j)) {
1857 * IF the block is a bad block we fail
1859 if (ext2fs_badblocks_list_test(bb_list, j)) {
1860 ext2fs_badblocks_list_free(bb_list);
1864 ext2fs_mark_block_bitmap2(bmap, j);
1867 * We are going to use this block for
1868 * inode table. So mark them used.
1870 ext2fs_mark_block_bitmap2(fs->block_map, j);
1873 needed_blocks += end_blk - start_blk;
1876 ext2fs_badblocks_list_free(bb_list);
1877 if (needed_blocks > ext2fs_free_blocks_count(fs->super))
1883 static int ext2fs_is_meta_block(ext2_filsys fs, blk64_t blk)
1886 group = ext2fs_group_of_blk2(fs, blk);
1887 if (ext2fs_block_bitmap_loc(fs, group) == blk)
1889 if (ext2fs_inode_bitmap_loc(fs, group) == blk)
1894 static int ext2fs_is_block_in_group(ext2_filsys fs, dgrp_t group, blk64_t blk)
1896 blk64_t start_blk, end_blk;
1897 start_blk = fs->super->s_first_data_block +
1898 EXT2_BLOCKS_PER_GROUP(fs->super) * group;
1900 * We cannot get new block beyond end_blk for for the last block group
1901 * so we can check with EXT2_BLOCKS_PER_GROUP even for last block group
1903 end_blk = start_blk + EXT2_BLOCKS_PER_GROUP(fs->super);
1904 if (blk >= start_blk && blk <= end_blk)
1909 static int move_block(ext2_filsys fs, ext2fs_block_bitmap bmap)
1916 blk64_t blk, new_blk, goal;
1917 struct blk_move *bmv;
1919 retval = ext2fs_get_mem(fs->blocksize, &buf);
1923 for (new_blk = blk = fs->super->s_first_data_block;
1924 blk < ext2fs_blocks_count(fs->super); blk++) {
1925 if (!ext2fs_test_block_bitmap2(bmap, blk))
1928 if (ext2fs_is_meta_block(fs, blk)) {
1930 * If the block is mapping a fs meta data block
1931 * like group desc/block bitmap/inode bitmap. We
1932 * should find a block in the same group and fix
1933 * the respective fs metadata pointers. Otherwise
1936 group = ext2fs_group_of_blk2(fs, blk);
1937 goal = ext2fs_group_first_block2(fs, group);
1943 retval = ext2fs_new_block2(fs, goal, NULL, &new_blk);
1947 /* new fs meta data block should be in the same group */
1948 if (meta_data && !ext2fs_is_block_in_group(fs, group, new_blk)) {
1953 /* Mark this block as allocated */
1954 ext2fs_mark_block_bitmap2(fs->block_map, new_blk);
1956 /* Add it to block move list */
1957 retval = ext2fs_get_mem(sizeof(struct blk_move), &bmv);
1962 bmv->new_loc = new_blk;
1964 list_add(&(bmv->list), &blk_move_list);
1966 retval = io_channel_read_blk64(fs->io, blk, 1, buf);
1970 retval = io_channel_write_blk64(fs->io, new_blk, 1, buf);
1976 ext2fs_free_mem(&buf);
1980 static blk64_t translate_block(blk64_t blk)
1982 struct list_head *entry;
1983 struct blk_move *bmv;
1985 list_for_each(entry, &blk_move_list) {
1986 bmv = list_entry(entry, struct blk_move, list);
1987 if (bmv->old_loc == blk)
1988 return bmv->new_loc;
1994 static int process_block(ext2_filsys fs EXT2FS_ATTR((unused)),
1996 e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
1997 blk64_t ref_block EXT2FS_ATTR((unused)),
1998 int ref_offset EXT2FS_ATTR((unused)),
2003 ext2fs_block_bitmap bmap = (ext2fs_block_bitmap) priv_data;
2005 if (!ext2fs_test_block_bitmap2(bmap, *block_nr))
2007 new_blk = translate_block(*block_nr);
2009 *block_nr = new_blk;
2011 * This will force the ext2fs_write_inode in the iterator
2013 ret |= BLOCK_CHANGED;
2019 static int inode_scan_and_fix(ext2_filsys fs, ext2fs_block_bitmap bmap)
2021 errcode_t retval = 0;
2024 char *block_buf = 0;
2025 struct ext2_inode inode;
2026 ext2_inode_scan scan = NULL;
2028 retval = ext2fs_get_mem(fs->blocksize * 3, &block_buf);
2032 retval = ext2fs_open_inode_scan(fs, 0, &scan);
2037 retval = ext2fs_get_next_inode(scan, &ino, &inode);
2044 if (inode.i_links_count == 0)
2045 continue; /* inode not in use */
2048 * If we end up modifying the journal inode
2049 * the sb->s_jnl_blocks will differ. But a
2050 * subsequent e2fsck fixes that.
2051 * Do we need to fix this ??
2054 if (ext2fs_file_acl_block(fs, &inode) &&
2055 ext2fs_test_block_bitmap2(bmap,
2056 ext2fs_file_acl_block(fs, &inode))) {
2057 blk = translate_block(ext2fs_file_acl_block(fs,
2062 ext2fs_file_acl_block_set(fs, &inode, blk);
2065 * Write the inode to disk so that inode table
2068 retval = ext2fs_write_inode(fs, ino, &inode);
2073 if (!ext2fs_inode_has_valid_blocks2(fs, &inode))
2076 retval = ext2fs_block_iterate3(fs, ino, 0, block_buf,
2077 process_block, bmap);
2084 ext2fs_free_mem(&block_buf);
2090 * We need to scan for inode and block bitmaps that may need to be
2091 * moved. This can take place if the filesystem was formatted for
2092 * RAID arrays using the mke2fs's extended option "stride".
2094 static int group_desc_scan_and_fix(ext2_filsys fs, ext2fs_block_bitmap bmap)
2097 blk64_t blk, new_blk;
2099 for (i = 0; i < fs->group_desc_count; i++) {
2100 blk = ext2fs_block_bitmap_loc(fs, i);
2101 if (ext2fs_test_block_bitmap2(bmap, blk)) {
2102 new_blk = translate_block(blk);
2105 ext2fs_block_bitmap_loc_set(fs, i, new_blk);
2108 blk = ext2fs_inode_bitmap_loc(fs, i);
2109 if (ext2fs_test_block_bitmap2(bmap, blk)) {
2110 new_blk = translate_block(blk);
2113 ext2fs_inode_bitmap_loc_set(fs, i, new_blk);
2119 static int expand_inode_table(ext2_filsys fs, unsigned long new_ino_size)
2124 int new_ino_blks_per_grp;
2126 char *old_itable = NULL, *new_itable = NULL;
2127 char *tmp_old_itable = NULL, *tmp_new_itable = NULL;
2128 unsigned long old_ino_size;
2129 int old_itable_size, new_itable_size;
2131 old_itable_size = fs->inode_blocks_per_group * fs->blocksize;
2132 old_ino_size = EXT2_INODE_SIZE(fs->super);
2134 new_ino_blks_per_grp = ext2fs_div_ceil(
2135 EXT2_INODES_PER_GROUP(fs->super) *
2139 new_itable_size = new_ino_blks_per_grp * fs->blocksize;
2141 retval = ext2fs_get_mem(old_itable_size, &old_itable);
2145 retval = ext2fs_get_mem(new_itable_size, &new_itable);
2149 tmp_old_itable = old_itable;
2150 tmp_new_itable = new_itable;
2152 for (i = 0; i < fs->group_desc_count; i++) {
2153 blk = ext2fs_inode_table_loc(fs, i);
2154 retval = io_channel_read_blk64(fs->io, blk,
2155 fs->inode_blocks_per_group, old_itable);
2159 for (j = 0; j < EXT2_INODES_PER_GROUP(fs->super); j++) {
2160 memcpy(new_itable, old_itable, old_ino_size);
2162 memset(new_itable+old_ino_size, 0,
2163 new_ino_size - old_ino_size);
2165 new_itable += new_ino_size;
2166 old_itable += old_ino_size;
2169 /* reset the pointer */
2170 old_itable = tmp_old_itable;
2171 new_itable = tmp_new_itable;
2173 retval = io_channel_write_blk64(fs->io, blk,
2174 new_ino_blks_per_grp, new_itable);
2179 /* Update the meta data */
2180 fs->inode_blocks_per_group = new_ino_blks_per_grp;
2181 fs->super->s_inode_size = new_ino_size;
2185 ext2fs_free_mem(&old_itable);
2188 ext2fs_free_mem(&new_itable);
2193 static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs)
2197 unsigned int group = 0;
2198 unsigned int count = 0;
2203 * First calculate the block statistics
2205 for (blk = fs->super->s_first_data_block;
2206 blk < ext2fs_blocks_count(fs->super); blk++) {
2207 if (!ext2fs_fast_test_block_bitmap2(fs->block_map, blk)) {
2212 if ((count == fs->super->s_blocks_per_group) ||
2213 (blk == ext2fs_blocks_count(fs->super)-1)) {
2214 ext2fs_bg_free_blocks_count_set(fs, group++,
2220 total_free = EXT2FS_C2B(fs, total_free);
2221 ext2fs_free_blocks_count_set(fs->super, total_free);
2224 * Next, calculate the inode statistics
2231 /* Protect loop from wrap-around if s_inodes_count maxed */
2232 for (ino = 1; ino <= fs->super->s_inodes_count && ino > 0; ino++) {
2233 if (!ext2fs_fast_test_inode_bitmap2(fs->inode_map, ino)) {
2238 if ((count == fs->super->s_inodes_per_group) ||
2239 (ino == fs->super->s_inodes_count)) {
2240 ext2fs_bg_free_inodes_count_set(fs, group++,
2246 fs->super->s_free_inodes_count = total_free;
2247 ext2fs_mark_super_dirty(fs);
2251 #define list_for_each_safe(pos, pnext, head) \
2252 for (pos = (head)->next, pnext = pos->next; pos != (head); \
2253 pos = pnext, pnext = pos->next)
2255 static void free_blk_move_list(void)
2257 struct list_head *entry, *tmp;
2258 struct blk_move *bmv;
2260 list_for_each_safe(entry, tmp, &blk_move_list) {
2261 bmv = list_entry(entry, struct blk_move, list);
2263 ext2fs_free_mem(&bmv);
2268 static int resize_inode(ext2_filsys fs, unsigned long new_size)
2271 int new_ino_blks_per_grp;
2272 ext2fs_block_bitmap bmap;
2274 retval = ext2fs_read_inode_bitmap(fs);
2276 fputs(_("Failed to read inode bitmap\n"), stderr);
2279 retval = ext2fs_read_block_bitmap(fs);
2281 fputs(_("Failed to read block bitmap\n"), stderr);
2284 INIT_LIST_HEAD(&blk_move_list);
2287 new_ino_blks_per_grp = ext2fs_div_ceil(
2288 EXT2_INODES_PER_GROUP(fs->super)*
2292 /* We may change the file system.
2293 * Mark the file system as invalid so that
2294 * the user is prompted to run fsck.
2296 fs->super->s_state &= ~EXT2_VALID_FS;
2298 retval = ext2fs_allocate_block_bitmap(fs, _("blocks to be moved"),
2301 fputs(_("Failed to allocate block bitmap when "
2302 "increasing inode size\n"), stderr);
2305 retval = get_move_bitmaps(fs, new_ino_blks_per_grp, bmap);
2307 fputs(_("Not enough space to increase inode size \n"), stderr);
2310 retval = move_block(fs, bmap);
2312 fputs(_("Failed to relocate blocks during inode resize \n"),
2316 retval = inode_scan_and_fix(fs, bmap);
2320 retval = group_desc_scan_and_fix(fs, bmap);
2324 retval = expand_inode_table(fs, new_size);
2328 ext2fs_calculate_summary_stats(fs);
2330 fs->super->s_state |= EXT2_VALID_FS;
2331 /* mark super block and block bitmap as dirty */
2332 ext2fs_mark_super_dirty(fs);
2333 ext2fs_mark_bb_dirty(fs);
2336 free_blk_move_list();
2337 ext2fs_free_block_bitmap(bmap);
2342 free_blk_move_list();
2343 ext2fs_free_block_bitmap(bmap);
2344 fputs(_("Error in resizing the inode size.\n"
2345 "Run e2undo to undo the "
2346 "file system changes. \n"), stderr);
2351 static int tune2fs_setup_tdb(const char *name, io_manager *io_ptr)
2353 errcode_t retval = 0;
2354 const char *tdb_dir;
2356 char *dev_name, *tmp_name;
2360 * Configuration via a conf file would be
2363 profile_get_string(profile, "scratch_files",
2367 tmp_name = strdup(name);
2370 com_err(program_name, ENOMEM, "%s",
2371 _("Couldn't allocate memory for tdb filename\n"));
2374 dev_name = basename(tmp_name);
2376 tdb_dir = getenv("E2FSPROGS_UNDO_DIR");
2378 tdb_dir = "/var/lib/e2fsprogs";
2380 if (!strcmp(tdb_dir, "none") || (tdb_dir[0] == 0) ||
2381 access(tdb_dir, W_OK))
2384 tdb_file = malloc(strlen(tdb_dir) + 9 + strlen(dev_name) + 7 + 1);
2387 sprintf(tdb_file, "%s/tune2fs-%s.e2undo", tdb_dir, dev_name);
2389 if ((unlink(tdb_file) < 0) && (errno != ENOENT)) {
2391 com_err(program_name, retval,
2392 _("while trying to delete %s"), tdb_file);
2397 set_undo_io_backing_manager(*io_ptr);
2398 *io_ptr = undo_io_manager;
2399 set_undo_io_backup_file(tdb_file);
2400 printf(_("To undo the tune2fs operation please run "
2401 "the command\n e2undo %s %s\n\n"),
2408 int main(int argc, char **argv)
2412 struct ext2_super_block *sb;
2413 io_manager io_ptr, io_ptr_orig = NULL;
2417 setlocale(LC_MESSAGES, "");
2418 setlocale(LC_CTYPE, "");
2419 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
2420 textdomain(NLS_CAT_NAME);
2421 set_com_err_gettext(gettext);
2424 program_name = *argv;
2425 add_error_table(&et_ext2_error_table);
2427 #ifdef CONFIG_BUILD_FINDFS
2428 if (strcmp(get_progname(argv[0]), "findfs") == 0)
2429 do_findfs(argc, argv);
2431 if (strcmp(get_progname(argv[0]), "e2label") == 0)
2432 parse_e2label_options(argc, argv);
2434 parse_tune2fs_options(argc, argv);
2436 #ifdef CONFIG_TESTIO_DEBUG
2437 if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_DEBUG")) {
2438 io_ptr = test_io_manager;
2439 test_io_backing_manager = unix_io_manager;
2442 io_ptr = unix_io_manager;
2445 if ((open_flag & EXT2_FLAG_RW) == 0 || f_flag)
2446 open_flag |= EXT2_FLAG_SKIP_MMP;
2448 open_flag |= EXT2_FLAG_64BITS;
2450 /* keep the filesystem struct around to dump MMP data */
2451 open_flag |= EXT2_FLAG_NOFREE_ON_ERROR;
2453 retval = ext2fs_open2(device_name, io_options, open_flag,
2456 com_err(program_name, retval,
2457 _("while trying to open %s"),
2459 if (retval == EXT2_ET_MMP_FSCK_ON ||
2460 retval == EXT2_ET_MMP_UNKNOWN_SEQ)
2461 dump_mmp_msg(fs->mmp_buf,
2462 _("If you are sure the filesystem "
2463 "is not in use on any node, run:\n"
2464 "'tune2fs -f -E clear_mmp {device}'\n"));
2465 else if (retval == EXT2_ET_MMP_FAILED)
2466 dump_mmp_msg(fs->mmp_buf, NULL);
2467 else if (retval == EXT2_ET_MMP_MAGIC_INVALID)
2469 _("MMP block magic is bad. Try to fix it by "
2470 "running:\n'e2fsck -f %s'\n"), device_name);
2471 else if (retval != EXT2_ET_MMP_FAILED)
2472 fprintf(stderr, "%s",
2473 _("Couldn't find valid filesystem superblock.\n"));
2478 fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE;
2480 if (I_flag && !io_ptr_orig) {
2482 * Check the inode size is right so we can issue an
2483 * error message and bail before setting up the tdb
2486 if (new_inode_size == EXT2_INODE_SIZE(fs->super)) {
2487 fprintf(stderr, _("The inode size is already %lu\n"),
2492 if (new_inode_size < EXT2_INODE_SIZE(fs->super)) {
2493 fprintf(stderr, "%s",
2494 _("Shrinking inode size is not supported\n"));
2498 if (new_inode_size > fs->blocksize) {
2499 fprintf(stderr, _("Invalid inode size %lu (max %d)\n"),
2500 new_inode_size, fs->blocksize);
2506 * If inode resize is requested use the
2509 io_ptr_orig = io_ptr;
2510 retval = tune2fs_setup_tdb(device_name, &io_ptr);
2515 if (io_ptr != io_ptr_orig) {
2522 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2525 /* For e2label emulation */
2526 printf("%.*s\n", (int) sizeof(sb->s_volume_name),
2528 remove_error_table(&et_ext2_error_table);
2532 retval = ext2fs_check_if_mounted(device_name, &mount_flags);
2534 com_err("ext2fs_check_if_mount", retval,
2535 _("while determining whether %s is mounted."),
2540 /* Normally we only need to write out the superblock */
2541 fs->flags |= EXT2_FLAG_SUPER_ONLY;
2544 sb->s_max_mnt_count = max_mount_count;
2545 ext2fs_mark_super_dirty(fs);
2546 printf(_("Setting maximal mount count to %d\n"),
2550 sb->s_mnt_count = mount_count;
2551 ext2fs_mark_super_dirty(fs);
2552 printf(_("Setting current mount count to %d\n"), mount_count);
2555 sb->s_errors = errors;
2556 ext2fs_mark_super_dirty(fs);
2557 printf(_("Setting error behavior to %d\n"), errors);
2560 sb->s_def_resgid = resgid;
2561 ext2fs_mark_super_dirty(fs);
2562 printf(_("Setting reserved blocks gid to %lu\n"), resgid);
2565 if (interval >= (1ULL << 32)) {
2566 com_err(program_name, 0,
2567 _("interval between checks is too big (%lu)"),
2572 sb->s_checkinterval = interval;
2573 ext2fs_mark_super_dirty(fs);
2574 printf(_("Setting interval between checks to %lu seconds\n"),
2578 ext2fs_r_blocks_count_set(sb, reserved_ratio *
2579 ext2fs_blocks_count(sb) / 100.0);
2580 ext2fs_mark_super_dirty(fs);
2581 printf (_("Setting reserved blocks percentage to %g%% (%llu blocks)\n"),
2582 reserved_ratio, ext2fs_r_blocks_count(sb));
2585 if (reserved_blocks > ext2fs_blocks_count(sb)/2) {
2586 com_err(program_name, 0,
2587 _("reserved blocks count is too big (%llu)"),
2592 ext2fs_r_blocks_count_set(sb, reserved_blocks);
2593 ext2fs_mark_super_dirty(fs);
2594 printf(_("Setting reserved blocks count to %llu\n"),
2598 if (sb->s_feature_ro_compat &
2599 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) {
2600 fputs(_("\nThe filesystem already has sparse "
2601 "superblocks.\n"), stderr);
2602 } else if (sb->s_feature_incompat &
2603 EXT2_FEATURE_INCOMPAT_META_BG) {
2604 fputs(_("\nSetting the sparse superblock flag not "
2605 "supported\nfor filesystems with "
2606 "the meta_bg feature enabled.\n"),
2611 sb->s_feature_ro_compat |=
2612 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
2613 sb->s_state &= ~EXT2_VALID_FS;
2614 ext2fs_mark_super_dirty(fs);
2615 printf(_("\nSparse superblock flag set. %s"),
2620 fputs(_("\nClearing the sparse superblock flag not supported.\n"),
2626 sb->s_lastcheck = last_check_time;
2627 ext2fs_mark_super_dirty(fs);
2628 printf(_("Setting time filesystem last checked to %s\n"),
2629 ctime(&last_check_time));
2632 sb->s_def_resuid = resuid;
2633 ext2fs_mark_super_dirty(fs);
2634 printf(_("Setting reserved blocks uid to %lu\n"), resuid);
2637 if (strlen(new_label) > sizeof(sb->s_volume_name))
2638 fputs(_("Warning: label too long, truncating.\n"),
2640 memset(sb->s_volume_name, 0, sizeof(sb->s_volume_name));
2641 strncpy(sb->s_volume_name, new_label,
2642 sizeof(sb->s_volume_name));
2643 ext2fs_mark_super_dirty(fs);
2646 memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted));
2647 strncpy(sb->s_last_mounted, new_last_mounted,
2648 sizeof(sb->s_last_mounted));
2649 ext2fs_mark_super_dirty(fs);
2652 rc = update_mntopts(fs, mntopts_cmd);
2657 rc = update_feature_set(fs, features_cmd);
2662 rc = parse_extended_opts(fs, extended_cmd);
2665 if (clear_mmp && !f_flag) {
2666 fputs(_("Error in using clear_mmp. "
2667 "It must be used with -f\n"),
2673 rc = ext2fs_mmp_clear(fs);
2676 if (journal_size || journal_device) {
2677 rc = add_journal(fs);
2683 if (mount_flags & EXT2_MF_MOUNTED) {
2684 fputs(_("The quota feature may only be changed when "
2685 "the filesystem is unmounted.\n"), stderr);
2689 handle_quota_options(fs);
2696 if (ext2fs_has_group_desc_csum(fs)) {
2698 * Changing the UUID requires rewriting all metadata,
2699 * which can race with a mounted fs. Don't allow that.
2701 if (mount_flags & EXT2_MF_MOUNTED) {
2702 fputs(_("The UUID may only be "
2703 "changed when the filesystem is "
2704 "unmounted.\n"), stderr);
2707 if (check_fsck_needed(fs))
2711 * Determine if the block group checksums are
2712 * correct so we know whether or not to set
2715 for (i = 0; i < fs->group_desc_count; i++)
2716 if (!ext2fs_group_desc_csum_verify(fs, i))
2718 if (i >= fs->group_desc_count)
2721 if ((strcasecmp(new_UUID, "null") == 0) ||
2722 (strcasecmp(new_UUID, "clear") == 0)) {
2723 uuid_clear(sb->s_uuid);
2724 } else if (strcasecmp(new_UUID, "time") == 0) {
2725 uuid_generate_time(sb->s_uuid);
2726 } else if (strcasecmp(new_UUID, "random") == 0) {
2727 uuid_generate(sb->s_uuid);
2728 } else if (uuid_parse(new_UUID, sb->s_uuid)) {
2729 com_err(program_name, 0, "%s",
2730 _("Invalid UUID format\n"));
2734 ext2fs_init_csum_seed(fs);
2736 for (i = 0; i < fs->group_desc_count; i++)
2737 ext2fs_group_desc_csum_set(fs, i);
2738 fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
2740 ext2fs_mark_super_dirty(fs);
2741 if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
2742 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
2743 rewrite_checksums = 1;
2745 if (rewrite_checksums)
2746 rewrite_metadata_checksums(fs);
2748 if (mount_flags & EXT2_MF_MOUNTED) {
2749 fputs(_("The inode size may only be "
2750 "changed when the filesystem is "
2751 "unmounted.\n"), stderr);
2755 if (fs->super->s_feature_incompat &
2756 EXT4_FEATURE_INCOMPAT_FLEX_BG) {
2757 fputs(_("Changing the inode size not supported for "
2758 "filesystems with the flex_bg\n"
2759 "feature enabled.\n"),
2765 * We want to update group descriptor also
2766 * with the new free inode count
2768 fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
2769 if (resize_inode(fs, new_inode_size) == 0) {
2770 printf(_("Setting inode size %lu\n"),
2773 printf("%s", _("Failed to change inode size\n"));
2782 sb->s_raid_stride = stride;
2783 ext2fs_mark_super_dirty(fs);
2784 printf(_("Setting stride size to %d\n"), stride);
2786 if (stripe_width_set) {
2787 sb->s_raid_stripe_width = stripe_width;
2788 ext2fs_mark_super_dirty(fs);
2789 printf(_("Setting stripe width to %d\n"), stripe_width);
2791 if (ext_mount_opts) {
2792 strncpy((char *)(fs->super->s_mount_opts), ext_mount_opts,
2793 sizeof(fs->super->s_mount_opts));
2794 fs->super->s_mount_opts[sizeof(fs->super->s_mount_opts)-1] = 0;
2795 ext2fs_mark_super_dirty(fs);
2796 printf(_("Setting extended default mount options to '%s'\n"),
2798 free(ext_mount_opts);
2801 remove_error_table(&et_ext2_error_table);
2805 ext2fs_mmp_stop(fs);
2809 return (ext2fs_close(fs) ? 1 : 0);