From 6b8e40e2042b6fa948bce1371b50e4d502e96c76 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 03 2016 06:09:33 +0000 Subject: import gfs2-utils-3.1.9-3.el7 --- diff --git a/.gfs2-utils.metadata b/.gfs2-utils.metadata index ef5589c..0a37ce4 100644 --- a/.gfs2-utils.metadata +++ b/.gfs2-utils.metadata @@ -1 +1 @@ -cd76f70559b4c97b7dc8aa7c3cef74291ec7957b SOURCES/gfs2-utils-3.1.8.tar.gz +6c500b8cdfd9c16ae2c3a7c40511f6d57bcb87e3 SOURCES/gfs2-utils-3.1.9.tar.gz diff --git a/.gitignore b/.gitignore index da093ca..df6925f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/gfs2-utils-3.1.8.tar.gz +SOURCES/gfs2-utils-3.1.9.tar.gz diff --git a/SOURCES/bz1162216-gfs2_edit_savemeta_speed_up_is_block_in_per_node.patch b/SOURCES/bz1162216-gfs2_edit_savemeta_speed_up_is_block_in_per_node.patch deleted file mode 100644 index 313e77b..0000000 --- a/SOURCES/bz1162216-gfs2_edit_savemeta_speed_up_is_block_in_per_node.patch +++ /dev/null @@ -1,135 +0,0 @@ -commit 342ab070d42625e6e4b65caf66f7b7117f7d4509 -Author: Andrew Price -Date: Wed Sep 2 14:12:31 2015 -0500 - - gfs2_edit savemeta: speed up is_block_in_per_node() - - Previously is_block_in_per_node() called lgfs2_inode_read() and - do_dinode_extended() for each block and savemeta was spending the vast - majority of its time in this function according to perf. This patch - speeds up the lookups by keeping a tree of per_node block addresses - which can be quickly consulted. In my tests with a full 700G filesystem - this patch cuts the run time in half. - - Resolves: rhbz#1162216 - Signed-off-by: Andrew Price - -diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c -index b68b0ff..b08eb5e 100644 ---- a/gfs2/edit/savemeta.c -+++ b/gfs2/edit/savemeta.c -@@ -74,8 +74,70 @@ static int block_is_a_journal(void) - return FALSE; - } - -+struct osi_root per_node_tree; -+struct per_node_node { -+ struct osi_node node; -+ uint64_t block; -+}; -+ -+static void destroy_per_node_lookup(void) -+{ -+ struct osi_node *n; -+ struct per_node_node *pnp; -+ -+ while ((n = osi_first(&per_node_tree))) { -+ pnp = (struct per_node_node *)n; -+ osi_erase(n, &per_node_tree); -+ free(pnp); -+ } -+} -+ - static int block_is_in_per_node(void) - { -+ struct per_node_node *pnp = (struct per_node_node *)per_node_tree.osi_node; -+ -+ while (pnp) { -+ if (block < pnp->block) -+ pnp = (struct per_node_node *)pnp->node.osi_left; -+ else if (block > pnp->block) -+ pnp = (struct per_node_node *)pnp->node.osi_right; -+ else -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static int insert_per_node_lookup(uint64_t blk) -+{ -+ struct osi_node **newn = &per_node_tree.osi_node, *parent = NULL; -+ struct per_node_node *pnp; -+ -+ while (*newn) { -+ struct per_node_node *cur = (struct per_node_node *)*newn; -+ -+ parent = *newn; -+ if (blk < cur->block) -+ newn = &((*newn)->osi_left); -+ else if (blk > cur->block) -+ newn = &((*newn)->osi_right); -+ else -+ return 0; -+ } -+ -+ pnp = calloc(1, sizeof(struct per_node_node)); -+ if (pnp == NULL) { -+ perror("Failed to insert per_node lookup entry"); -+ return 1; -+ } -+ pnp->block = blk; -+ osi_link_node(&pnp->node, parent, newn); -+ osi_insert_color(&pnp->node, &per_node_tree); -+ return 0; -+} -+ -+static int init_per_node_lookup(void) -+{ - int i; - struct gfs2_inode *per_node_di; - -@@ -85,7 +147,7 @@ static int block_is_in_per_node(void) - per_node_di = lgfs2_inode_read(&sbd, masterblock("per_node")); - if (per_node_di == NULL) { - fprintf(stderr, "Failed to read per_node: %s\n", strerror(errno)); -- exit(1); -+ return 1; - } - - do_dinode_extended(&per_node_di->i_di, per_node_di->i_bh); -@@ -94,11 +156,12 @@ static int block_is_in_per_node(void) - for (i = 0; i < indirect_blocks; i++) { - int d; - for (d = 0; d < indirect->ii[i].dirents; d++) { -- if (block == indirect->ii[i].dirent[d].block) -- return TRUE; -+ int ret = insert_per_node_lookup(indirect->ii[i].dirent[d].block); -+ if (ret != 0) -+ return ret; - } - } -- return FALSE; -+ return 0; - } - - static int block_is_systemfile(void) -@@ -749,6 +812,10 @@ void savemeta(char *out_fn, int saveoption, int gziplevel) - printf("Filesystem size: %s\n", anthropomorphize(sbd.fssize * sbd.bsize)); - get_journal_inode_blocks(); - -+ err = init_per_node_lookup(); -+ if (err) -+ exit(1); -+ - /* Write the savemeta file header */ - err = save_header(&mfd, sbd.fssize * sbd.bsize); - if (err) { -@@ -810,6 +877,7 @@ void savemeta(char *out_fn, int saveoption, int gziplevel) - } - savemetaclose(&mfd); - close(sbd.device_fd); -+ destroy_per_node_lookup(); - free(indirect); - gfs2_rgrp_free(&sbd.rgtree); - exit(0); diff --git a/SOURCES/bz1186515-fsck_gfs2_replace_recent_i_goal_fixes_with_simple_logic.patch b/SOURCES/bz1186515-fsck_gfs2_replace_recent_i_goal_fixes_with_simple_logic.patch deleted file mode 100644 index 2ada585..0000000 --- a/SOURCES/bz1186515-fsck_gfs2_replace_recent_i_goal_fixes_with_simple_logic.patch +++ /dev/null @@ -1,304 +0,0 @@ -commit e394013ec812e7fa359344a3b901b8b15b15bc4a -Author: Abhi Das -Date: Tue Apr 14 19:51:55 2015 -0500 - - fsck.gfs2: replace recent i_goal fixes with simple logic - - This patch reverses the recent set of i_goal fixes for fsck.gfs2. - This is because of two problems. - 1. It is not possible to determine if a valid block within the fs - is the correct goal block for a given inode. - 2. Conversely, given an inode, it is also not possible to accurately - determine what its goal block should be. - - The previous patches assumed that the last block of a file is its - goal block, but that is not true if the file is a directory or if - its blocks are not allocated sequentially. fsck.gfs2 would flag - these inodes incorrectly as having bad i_goal values. - - This patch takes a simple approach. It checks if the i_goal of a - given inode is out of bounds of the fs. If so, we can be certain - that it is wrong and we set it to the inode metadata block. This - is a safe starting point for gfs2 to determine where to allocate - from next. - - Resolves: rhbz#1186515 - Signed-off-by: Abhi Das - -diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c -index f05fb51..4d5a660 100644 ---- a/gfs2/fsck/metawalk.c -+++ b/gfs2/fsck/metawalk.c -@@ -1428,8 +1428,7 @@ static int build_and_check_metalist(struct gfs2_inode *ip, osi_list_t *mlp, - */ - static int check_data(struct gfs2_inode *ip, struct metawalk_fxns *pass, - struct gfs2_buffer_head *bh, int head_size, -- uint64_t *last_block, uint64_t *blks_checked, -- uint64_t *error_blk) -+ uint64_t *blks_checked, uint64_t *error_blk) - { - int error = 0, rc = 0; - uint64_t block, *ptr; -@@ -1444,7 +1443,7 @@ static int check_data(struct gfs2_inode *ip, struct metawalk_fxns *pass, - - if (skip_this_pass || fsck_abort) - return error; -- *last_block = block = be64_to_cpu(*ptr); -+ block = be64_to_cpu(*ptr); - /* It's important that we don't call valid_block() and - bypass calling check_data on invalid blocks because that - would defeat the rangecheck_block related functions in -@@ -1548,15 +1547,12 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass) - struct gfs2_buffer_head *bh; - uint32_t height = ip->i_di.di_height; - int i, head_size; -- uint64_t blks_checked = 0, last_block = 0; -+ uint64_t blks_checked = 0; - int error, rc; - int metadata_clean = 0; - uint64_t error_blk = 0; - int hit_error_blk = 0; - -- if (!height && pass->check_i_goal) -- pass->check_i_goal(ip, ip->i_di.di_num.no_addr, -- pass->private); - if (!height && !is_dir(&ip->i_di, ip->i_sbd->gfs1)) - return 0; - -@@ -1575,9 +1571,6 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass) - * comprise the directory hash table, so we perform the directory - * checks and exit. */ - if (is_dir(&ip->i_di, ip->i_sbd->gfs1)) { -- last_block = ip->i_di.di_num.no_addr; -- if (pass->check_i_goal) -- pass->check_i_goal(ip, last_block, pass->private); - if (!(ip->i_di.di_flags & GFS2_DIF_EXHASH)) - goto out; - /* check validity of leaf blocks and leaf chains */ -@@ -1604,7 +1597,7 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass) - - if (pass->check_data) - error = check_data(ip, pass, bh, head_size, -- &last_block, &blks_checked, &error_blk); -+ &blks_checked, &error_blk); - if (pass->big_file_msg && ip->i_di.di_blocks > COMFORTABLE_BLKS) - pass->big_file_msg(ip, blks_checked); - } -@@ -1616,8 +1609,6 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass) - (unsigned long long)ip->i_di.di_num.no_addr); - fflush(stdout); - } -- if (!error && pass->check_i_goal) -- pass->check_i_goal(ip, last_block, pass->private); - undo_metalist: - if (!error) - goto out; -@@ -1958,80 +1949,6 @@ static int alloc_leaf(struct gfs2_inode *ip, uint64_t block, void *private) - return 0; - } - --/** -- * rgrp_contains_block - Check if the rgrp provided contains the -- * given block. Taken directly from the gfs2 kernel code -- * @rgd: The rgrp to search within -- * @block: The block to search for -- * -- * Returns: 1 if present, 0 if not. -- */ --static inline int rgrp_contains_block(struct rgrp_tree *rgd, uint64_t block) --{ -- uint64_t first = rgd->ri.ri_data0; -- uint64_t last = first + rgd->ri.ri_data; -- return first <= block && block < last; --} -- --/** -- * check_i_goal -- * @ip -- * @goal_blk: What the goal block should be for this inode -- * -- * The goal block for a regular file is typically the last -- * data block of the file. If we can't get the right value, -- * the inode metadata block is the next best thing. -- * -- * Returns: 0 if corrected, 1 if not corrected -- */ --int check_i_goal(struct gfs2_inode *ip, uint64_t goal_blk, -- void *private) --{ -- struct gfs2_sbd *sdp = ip->i_sbd; -- uint64_t i_block = ip->i_di.di_num.no_addr; -- -- /* Don't fix gfs1 inodes, system inodes or inodes whose goal blocks are -- * set to the inode blocks themselves. */ -- if (sdp->gfs1 || ip->i_di.di_flags & GFS2_DIF_SYSTEM || -- ip->i_di.di_goal_meta == i_block) -- return 0; -- /* Don't fix directory goal blocks unless we know they're wrong. -- * i.e. out of bounds of the fs. Directories can easily have blocks -- * outside of the dinode's rgrp and thus we have no way of knowing -- * if the goal block is bogus or not. */ -- if (is_dir(&ip->i_di, ip->i_sbd->gfs1) && -- (ip->i_di.di_goal_meta > sdp->sb_addr && -- ip->i_di.di_goal_meta <= sdp->fssize)) -- return 0; -- /* We default to the inode block */ -- if (!goal_blk) -- goal_blk = i_block; -- -- if (ip->i_di.di_goal_meta != goal_blk) { -- /* If the existing goal block is in the same rgrp as the inode, -- * we give the benefit of doubt and assume the value is correct */ -- if (ip->i_rgd && -- rgrp_contains_block(ip->i_rgd, ip->i_di.di_goal_meta)) -- goto skip; -- log_err( _("Error: inode %llu (0x%llx) has invalid " -- "allocation goal block %llu (0x%llx). Should" -- " be %llu (0x%llx)\n"), -- (unsigned long long)i_block, (unsigned long long)i_block, -- (unsigned long long)ip->i_di.di_goal_meta, -- (unsigned long long)ip->i_di.di_goal_meta, -- (unsigned long long)goal_blk, (unsigned long long)goal_blk); -- if (query( _("Fix the invalid goal block? (y/n) "))) { -- ip->i_di.di_goal_meta = ip->i_di.di_goal_data = goal_blk; -- bmodified(ip->i_bh); -- } else { -- log_err(_("Invalid goal block not fixed.\n")); -- return 1; -- } -- } --skip: -- return 0; --} -- - struct metawalk_fxns alloc_fxns = { - .private = NULL, - .check_leaf = alloc_leaf, -@@ -2042,7 +1959,6 @@ struct metawalk_fxns alloc_fxns = { - .check_dentry = NULL, - .check_eattr_entry = NULL, - .check_eattr_extentry = NULL, -- .check_i_goal = check_i_goal, - .finish_eattr_indir = NULL, - }; - -diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h -index 779360e..fa4c850 100644 ---- a/gfs2/fsck/metawalk.h -+++ b/gfs2/fsck/metawalk.h -@@ -50,8 +50,6 @@ extern int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock, - const char *caller, int line); - extern int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk, - int error_on_dinode, int new_blockmap_state); --extern int check_i_goal(struct gfs2_inode *ip, uint64_t goal_blk, -- void *private); - extern void reprocess_inode(struct gfs2_inode *ip, const char *desc); - extern struct duptree *dupfind(uint64_t block); - extern struct gfs2_inode *fsck_system_inode(struct gfs2_sbd *sdp, -@@ -91,7 +89,6 @@ enum meta_check_rc { - * check_dentry: - * check_eattr_entry: - * check_eattr_extentry: -- * check_i_goal: - */ - struct metawalk_fxns { - void *private; -@@ -143,8 +140,6 @@ struct metawalk_fxns { - struct gfs2_ea_header *ea_hdr, - struct gfs2_ea_header *ea_hdr_prev, - void *private); -- int (*check_i_goal) (struct gfs2_inode *ip, uint64_t goal_blk, -- void *private); - int (*finish_eattr_indir) (struct gfs2_inode *ip, int leaf_pointers, - int leaf_pointer_errors, void *private); - void (*big_file_msg) (struct gfs2_inode *ip, uint64_t blks_checked); -diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c -index 69c88f4..0909873 100644 ---- a/gfs2/fsck/pass1.c -+++ b/gfs2/fsck/pass1.c -@@ -100,7 +100,6 @@ struct metawalk_fxns pass1_fxns = { - .check_dentry = NULL, - .check_eattr_entry = check_eattr_entries, - .check_eattr_extentry = check_extended_leaf_eattr, -- .check_i_goal = check_i_goal, - .finish_eattr_indir = finish_eattr_indir, - .big_file_msg = big_file_comfort, - .repair_leaf = pass1_repair_leaf, -@@ -1205,12 +1204,37 @@ bad_dinode: - return -1; - } - -+static void check_i_goal(struct gfs2_sbd *sdp, struct gfs2_inode *ip) -+{ -+ if (sdp->gfs1 || ip->i_di.di_flags & GFS2_DIF_SYSTEM) -+ return; -+ -+ if (ip->i_di.di_goal_meta <= sdp->sb_addr || -+ ip->i_di.di_goal_meta > sdp->fssize) { -+ log_err(_("Inode #%llu (0x%llx): Bad allocation goal block " -+ "found: %llu (0x%llx)\n"), -+ (unsigned long long)ip->i_di.di_num.no_addr, -+ (unsigned long long)ip->i_di.di_num.no_addr, -+ (unsigned long long)ip->i_di.di_goal_meta, -+ (unsigned long long)ip->i_di.di_goal_meta); -+ if (query( _("Fix goal block in inode #%llu (0x%llx)? (y/n) "), -+ (unsigned long long)ip->i_di.di_num.no_addr, -+ (unsigned long long)ip->i_di.di_num.no_addr)) { -+ ip->i_di.di_goal_meta = ip->i_di.di_num.no_addr; -+ bmodified(ip->i_bh); -+ } else -+ log_err(_("Allocation goal block in inode #%lld " -+ "(0x%llx) not fixed\n"), -+ (unsigned long long)ip->i_di.di_num.no_addr, -+ (unsigned long long)ip->i_di.di_num.no_addr); -+ } -+} -+ - /* - * handle_di - This is now a wrapper function that takes a gfs2_buffer_head - * and calls handle_ip, which takes an in-code dinode structure. - */ --static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, -- struct rgrp_tree *rgd) -+static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh) - { - int error = 0; - uint64_t block = bh->b_blocknr; -@@ -1252,7 +1276,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, - (unsigned long long)block, - (unsigned long long)block); - } -- ip->i_rgd = rgd; -+ check_i_goal(sdp, ip); - error = handle_ip(sdp, ip); - fsck_inode_put(&ip); - return error; -@@ -1378,6 +1402,7 @@ static int check_system_inode(struct gfs2_sbd *sdp, - "directory entries.\n"), filename); - } - } -+ check_i_goal(sdp, *sysinode); - error = handle_ip(sdp, *sysinode); - return error ? error : err; - } -@@ -1602,7 +1627,7 @@ static int pass1_process_bitmap(struct gfs2_sbd *sdp, struct rgrp_tree *rgd, uin - (unsigned long long)block, - (unsigned long long)block); - check_n_fix_bitmap(sdp, block, 0, GFS2_BLKST_FREE); -- } else if (handle_di(sdp, bh, rgd) < 0) { -+ } else if (handle_di(sdp, bh) < 0) { - stack; - brelse(bh); - gfs2_special_free(&gfs1_rindex_blks); -diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h -index f1f81d3..ccae721 100644 ---- a/gfs2/libgfs2/libgfs2.h -+++ b/gfs2/libgfs2/libgfs2.h -@@ -233,7 +233,6 @@ struct gfs2_inode { - struct gfs2_dinode i_di; - struct gfs2_buffer_head *i_bh; - struct gfs2_sbd *i_sbd; -- struct rgrp_tree *i_rgd; /* The rgrp this inode is in */ - }; - - struct master_dir diff --git a/SOURCES/bz1202831-mkfs_gfs2_Allow_longer_cluster_names.patch b/SOURCES/bz1202831-mkfs_gfs2_Allow_longer_cluster_names.patch deleted file mode 100644 index 40c8e2d..0000000 --- a/SOURCES/bz1202831-mkfs_gfs2_Allow_longer_cluster_names.patch +++ /dev/null @@ -1,87 +0,0 @@ -commit a523af584645a01bb4900b10d0c9232d0ae50339 -Author: Paul Evans -Date: Wed Apr 22 17:43:26 2015 +0100 - - mkfs.gfs2: Allow longer cluster names - - Increase the enforced limit for cluster name to 32 bytes and file - system name to 30 bytes for mkfs.gfs2 (was previously 16 + 16 - bytes). - - Also increased this limit in tunegfs2 when labelling gfs2 file - systems. - - Updated the formation in the man pages along with adding a new test - case for mkfs.gfs2 to validate the increased cluster/file system - name support. - - Resolves: rhbz#1202831 - Signed-off-by: Paul Evans - -diff --git a/gfs2/man/mkfs.gfs2.8 b/gfs2/man/mkfs.gfs2.8 -index ceb6f38..f480082 100644 ---- a/gfs2/man/mkfs.gfs2.8 -+++ b/gfs2/man/mkfs.gfs2.8 -@@ -101,9 +101,9 @@ bigger file systems will have bigger RGs for better performance. - The lock table field appropriate to the lock module you're using. - It is \fIclustername:fsname\fR. - Clustername must match that in cluster.conf; only members of this --cluster are permitted to use this file system. -+cluster are permitted to use this file system (1 to 32 characters). - Fsname is a unique file system name used to distinguish this GFS2 file --system from others created (1 to 16 characters). Lock_nolock doesn't -+system from others created (1 to 30 characters). Lock_nolock doesn't - use this field. Valid \fIclustername\fRs and \fIfsname\fRs may only contain - alphanumeric characters, hyphens (-) and underscores (_). - .TP -diff --git a/gfs2/mkfs/main_mkfs.c b/gfs2/mkfs/main_mkfs.c -index 0636f0b..3fab08c 100644 ---- a/gfs2/mkfs/main_mkfs.c -+++ b/gfs2/mkfs/main_mkfs.c -@@ -398,7 +398,7 @@ static void test_locking(const char *lockproto, const char *locktable) - - if (c == locktable) - die("%s %s\n", errprefix, _("cluster name is missing")); -- if (c - locktable > 16) -+ if (c - locktable > 32) - die("%s %s\n", errprefix, _("cluster name is too long")); - - c++; -@@ -406,7 +406,7 @@ static void test_locking(const char *lockproto, const char *locktable) - die("%s %s\n", errprefix, _("contains more than one colon")); - if (!strlen(c)) - die("%s %s\n", errprefix, _("file system name is missing")); -- if (strlen(c) > 16) -+ if (strlen(c) > 30) - die("%s %s\n", errprefix, _("file system name is too long")); - } else { - die( _("Invalid lock protocol: %s\n"), lockproto); -diff --git a/gfs2/tune/super.c b/gfs2/tune/super.c -index cbd0026..560ce68 100644 ---- a/gfs2/tune/super.c -+++ b/gfs2/tune/super.c -@@ -194,7 +194,7 @@ int change_locktable(struct tunegfs2 *tfs, const char *locktable) - fprintf(stderr, "%s %s\n", errpre, _("missing colon")); - return EX_DATAERR; - } -- if (strlen(++fsname) > 16) { -+ if (strlen(++fsname) > 30) { - fprintf(stderr, "%s %s\n", errpre, _("file system name is too long")); - return EX_DATAERR; - } -diff --git a/tests/mkfs.at b/tests/mkfs.at -index 438184c..e25b6dc 100644 ---- a/tests/mkfs.at -+++ b/tests/mkfs.at -@@ -89,3 +89,11 @@ AT_SETUP([Min. quota change file size]) - AT_KEYWORDS(mkfs.gfs2 mkfs) - GFS_FSCK_CHECK([$GFS_MKFS -p lock_nolock -c 1 $GFS_TGT]) - AT_CLEANUP -+ -+AT_SETUP([Incr. cluster/file system name validation]) -+AT_KEYWORDS(mkfs.gfs2 mkfs) -+AT_CHECK([$GFS_MKFS -p lock_dlm -t "" $GFS_TGT], 255, [ignore], [ignore]) -+AT_CHECK([$GFS_MKFS -p lock_dlm -t "quite_long_cluster_name_test_here:intec34p" $GFS_TGT], 255, [ignore], [ignore]) -+AT_CHECK([$GFS_MKFS -p lock_dlm -t "financial_cluster:this_time_we_test_fs_naming_len" $GFS_TGT], 255, [ignore], [ignore]) -+GFS_FSCK_CHECK([$GFS_MKFS -p lock_dlm -t "a_really_long_named_cluster_here:concurrently_lets_check_fs_len" $GFS_TGT]) -+AT_CLEANUP diff --git a/SOURCES/bz1225634-1-gfs2_utils_Fix_hang_on_withdraw.patch b/SOURCES/bz1225634-1-gfs2_utils_Fix_hang_on_withdraw.patch deleted file mode 100644 index 191e79f..0000000 --- a/SOURCES/bz1225634-1-gfs2_utils_Fix_hang_on_withdraw.patch +++ /dev/null @@ -1,97 +0,0 @@ -commit 40b872651561de2e8a06fdb1b792be8874e2b19a -Author: Abhi Das -Date: Tue Aug 4 11:00:51 2015 -0500 - - gfs2-utils: Fix hang on withdraw - - Issuing a withdraw on a gfs2 filesystem causes a hang. When - gfs_controld was removed, the userspace functionality that - completes a withdraw operation went away. This causes gfs2 - kernel to hang waiting for a withdraw completion ack from - userspace. - - This patchset introduces a uevent-based shell script to do - the job that gfs_controld used to do on withdraw. An 'offline' - uevent triggers the execution of this script. This script - suspends the device associated with the filesystem and signals - a completed withdraw to the kernel. - - Resolves: rhbz#1225634 - Signed-off-by: Abhi Das - -diff --git a/README.build b/README.build -index f4ebe53..6487bae 100644 ---- a/README.build -+++ b/README.build -@@ -29,5 +29,14 @@ To install gfs2-utils, run: - - make install - -+The following scripts (located in gfs2/scripts) are used to complete -+the userland portion of the gfs2 withdraw feature using uevents. They -+are not installed by 'make install' and need to be installed manually -+or during rpm installation to the corresponding locations. -+ -+ 82-gfs2-withdraw.rules in /etc/udev/rules.d/ -+ gfs2_wd_udev.sh in /usr/sbin/ -+ - See also doc/README.contributing for details on submitting patches and - doc/README.tests for more details regarding the test suite. -+ -diff --git a/gfs2/scripts/82-gfs2-withdraw.rules b/gfs2/scripts/82-gfs2-withdraw.rules -new file mode 100644 -index 0000000..2228615 ---- /dev/null -+++ b/gfs2/scripts/82-gfs2-withdraw.rules -@@ -0,0 +1,2 @@ -+SUBSYSTEM=="gfs2", ACTION=="offline", RUN+="/bin/sh /usr/sbin/gfs2_wd_udev.sh" -+ -diff --git a/gfs2/scripts/Makefile.am b/gfs2/scripts/Makefile.am -index 62fb2fe..dde906f 100644 ---- a/gfs2/scripts/Makefile.am -+++ b/gfs2/scripts/Makefile.am -@@ -3,3 +3,8 @@ MAINTAINERCLEANFILES = Makefile.in - dist_sbin_SCRIPTS = \ - gfs2_lockcapture \ - gfs2_trace -+ -+noinst_SCRIPTS = \ -+ 82-gfs2-withdraw.rules \ -+ gfs2_wd_udev.sh -+ -diff --git a/gfs2/scripts/gfs2_wd_udev.sh b/gfs2/scripts/gfs2_wd_udev.sh -new file mode 100755 -index 0000000..ac3ce35 ---- /dev/null -+++ b/gfs2/scripts/gfs2_wd_udev.sh -@@ -0,0 +1,30 @@ -+#!/bin/sh -+# -+# Do not run this script manually. This script is called by udev on a gfs2 -+# withdraw uevent and is used to complete the withdraw action and notify the -+# kernel. -+# -+ -+# Sanity checks -+if [ "$SUBSYSTEM" != "gfs2" ] || [ "$LOCKPROTO" != "lock_dlm" ] || -+ [ -z "$DEVPATH" ] || [ "$ACTION" != "offline" ] -+then -+ exit 1 # Nothing to do here -+fi -+ -+# Try and suspend the device -+SYSFS_TOPDIR="/sys"$DEVPATH -+DM_NAME=$(cat "$SYSFS_TOPDIR/device/dm/name") -+DM_DEV="/dev/mapper/"$DM_NAME -+ -+if [ -z "$DM_DEV" ] -+then -+ /usr/bin/dmsetup suspend $DM_DEV -+fi -+ -+# Signal completion of withdraw -+WD_ACK="$SYSFS_TOPDIR/lock_module/withdraw" -+if [ -f "$WD_ACK" ] -+then -+ echo "1" > $WD_ACK -+fi diff --git a/SOURCES/bz1225634-2-scripts_rename_gfs2_wd_udev_sh_to_gfs2_withdraw_helper.patch b/SOURCES/bz1225634-2-scripts_rename_gfs2_wd_udev_sh_to_gfs2_withdraw_helper.patch deleted file mode 100644 index 749ffaf..0000000 --- a/SOURCES/bz1225634-2-scripts_rename_gfs2_wd_udev_sh_to_gfs2_withdraw_helper.patch +++ /dev/null @@ -1,116 +0,0 @@ -commit 60db3c365128dc8aa7e0d3c903c426c8a743b8e2 -Author: Andrew Price -Date: Tue Aug 18 12:35:52 2015 +0100 - - scripts: rename gfs2_wd_udev.sh to gfs2_withdraw_helper - - Makes the name more descriptive and consistent with the name of the udev - rules script. - - Resolves: rhbz#1225634 - Signed-off-by: Andrew Price - -diff --git a/README.build b/README.build -index 6487bae..acfde1b 100644 ---- a/README.build -+++ b/README.build -@@ -35,7 +35,7 @@ are not installed by 'make install' and need to be installed manually - or during rpm installation to the corresponding locations. - - 82-gfs2-withdraw.rules in /etc/udev/rules.d/ -- gfs2_wd_udev.sh in /usr/sbin/ -+ gfs2_withdraw_helper in /usr/sbin/ - - See also doc/README.contributing for details on submitting patches and - doc/README.tests for more details regarding the test suite. -diff --git a/gfs2/scripts/82-gfs2-withdraw.rules b/gfs2/scripts/82-gfs2-withdraw.rules -index 2228615..2c9e0e8 100644 ---- a/gfs2/scripts/82-gfs2-withdraw.rules -+++ b/gfs2/scripts/82-gfs2-withdraw.rules -@@ -1,2 +1,2 @@ --SUBSYSTEM=="gfs2", ACTION=="offline", RUN+="/bin/sh /usr/sbin/gfs2_wd_udev.sh" -+SUBSYSTEM=="gfs2", ACTION=="offline", RUN+="/bin/sh /usr/sbin/gfs2_withdraw_helper" - -diff --git a/gfs2/scripts/Makefile.am b/gfs2/scripts/Makefile.am -index dde906f..51764fa 100644 ---- a/gfs2/scripts/Makefile.am -+++ b/gfs2/scripts/Makefile.am -@@ -6,5 +6,5 @@ dist_sbin_SCRIPTS = \ - - noinst_SCRIPTS = \ - 82-gfs2-withdraw.rules \ -- gfs2_wd_udev.sh -+ gfs2_withdraw_helper - -diff --git a/gfs2/scripts/gfs2_wd_udev.sh b/gfs2/scripts/gfs2_wd_udev.sh -deleted file mode 100755 -index ac3ce35..0000000 ---- a/gfs2/scripts/gfs2_wd_udev.sh -+++ /dev/null -@@ -1,30 +0,0 @@ --#!/bin/sh --# --# Do not run this script manually. This script is called by udev on a gfs2 --# withdraw uevent and is used to complete the withdraw action and notify the --# kernel. --# -- --# Sanity checks --if [ "$SUBSYSTEM" != "gfs2" ] || [ "$LOCKPROTO" != "lock_dlm" ] || -- [ -z "$DEVPATH" ] || [ "$ACTION" != "offline" ] --then -- exit 1 # Nothing to do here --fi -- --# Try and suspend the device --SYSFS_TOPDIR="/sys"$DEVPATH --DM_NAME=$(cat "$SYSFS_TOPDIR/device/dm/name") --DM_DEV="/dev/mapper/"$DM_NAME -- --if [ -z "$DM_DEV" ] --then -- /usr/bin/dmsetup suspend $DM_DEV --fi -- --# Signal completion of withdraw --WD_ACK="$SYSFS_TOPDIR/lock_module/withdraw" --if [ -f "$WD_ACK" ] --then -- echo "1" > $WD_ACK --fi -diff --git a/gfs2/scripts/gfs2_withdraw_helper b/gfs2/scripts/gfs2_withdraw_helper -new file mode 100755 -index 0000000..ac3ce35 ---- /dev/null -+++ b/gfs2/scripts/gfs2_withdraw_helper -@@ -0,0 +1,30 @@ -+#!/bin/sh -+# -+# Do not run this script manually. This script is called by udev on a gfs2 -+# withdraw uevent and is used to complete the withdraw action and notify the -+# kernel. -+# -+ -+# Sanity checks -+if [ "$SUBSYSTEM" != "gfs2" ] || [ "$LOCKPROTO" != "lock_dlm" ] || -+ [ -z "$DEVPATH" ] || [ "$ACTION" != "offline" ] -+then -+ exit 1 # Nothing to do here -+fi -+ -+# Try and suspend the device -+SYSFS_TOPDIR="/sys"$DEVPATH -+DM_NAME=$(cat "$SYSFS_TOPDIR/device/dm/name") -+DM_DEV="/dev/mapper/"$DM_NAME -+ -+if [ -z "$DM_DEV" ] -+then -+ /usr/bin/dmsetup suspend $DM_DEV -+fi -+ -+# Signal completion of withdraw -+WD_ACK="$SYSFS_TOPDIR/lock_module/withdraw" -+if [ -f "$WD_ACK" ] -+then -+ echo "1" > $WD_ACK -+fi diff --git a/SOURCES/bz1225634-3-scripts_install_the_withdraw_helper_script.patch b/SOURCES/bz1225634-3-scripts_install_the_withdraw_helper_script.patch deleted file mode 100644 index cfd0149..0000000 --- a/SOURCES/bz1225634-3-scripts_install_the_withdraw_helper_script.patch +++ /dev/null @@ -1,28 +0,0 @@ -commit c17455947281083e73567871ba1777d7ec135d4e -Author: Andrew Price -Date: Tue Aug 18 12:48:50 2015 +0100 - - scripts: install the withdraw helper script - - Install gfs2_withdraw_helper into /usr/sbin in 'make install'. - - Resolves: rhbz#1225634 - Signed-off-by: Andrew Price - -diff --git a/gfs2/scripts/Makefile.am b/gfs2/scripts/Makefile.am -index 51764fa..056aaa5 100644 ---- a/gfs2/scripts/Makefile.am -+++ b/gfs2/scripts/Makefile.am -@@ -2,9 +2,9 @@ MAINTAINERCLEANFILES = Makefile.in - - dist_sbin_SCRIPTS = \ - gfs2_lockcapture \ -- gfs2_trace -+ gfs2_trace \ -+ gfs2_withdraw_helper - - noinst_SCRIPTS = \ -- 82-gfs2-withdraw.rules \ -- gfs2_withdraw_helper -+ 82-gfs2-withdraw.rules - diff --git a/SOURCES/bz1225634-4-scripts_install_the_withdraw_udev_rules_script.patch b/SOURCES/bz1225634-4-scripts_install_the_withdraw_udev_rules_script.patch deleted file mode 100644 index 6b960a8..0000000 --- a/SOURCES/bz1225634-4-scripts_install_the_withdraw_udev_rules_script.patch +++ /dev/null @@ -1,73 +0,0 @@ -commit f26de3589548a9fde9797e9f515b5b27de5a961d -Author: Andrew Price -Date: Wed Aug 19 12:13:39 2015 +0100 - - scripts: install the withdraw udev rules script - - Add a --with-udevdir configure option and default to $prefix/lib/udev. - Note that we can't use $libdir for this as that will often be /usr/lib64 - and the udevdir is arch-independent. - - Also add the autoconf bits needed to install 82-gfs2-withdraw.rules into - $udevdir/rules.d - - Resolves: rhbz#1225634 - Signed-off-by: Andrew Price - -diff --git a/README.build b/README.build -index acfde1b..d0a21c3 100644 ---- a/README.build -+++ b/README.build -@@ -31,10 +31,9 @@ To install gfs2-utils, run: - - The following scripts (located in gfs2/scripts) are used to complete - the userland portion of the gfs2 withdraw feature using uevents. They --are not installed by 'make install' and need to be installed manually --or during rpm installation to the corresponding locations. -+will be installed by 'make install' to these directories by default: - -- 82-gfs2-withdraw.rules in /etc/udev/rules.d/ -+ 82-gfs2-withdraw.rules in /usr/lib/udev/rules.d/ - gfs2_withdraw_helper in /usr/sbin/ - - See also doc/README.contributing for details on submitting patches and -diff --git a/configure.ac b/configure.ac -index de96e5a..35cafe6 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -110,6 +110,12 @@ if test -z "$ncurses_CFLAGS" && test -z "$ncurses_LIBS"; then - ncurses_LIBS=-lncurses - fi - -+AC_ARG_WITH([udevdir], -+ AS_HELP_STRING([--with-udevdir=DIR], -+ [udev directory containing rules.d [default=${prefix}/lib/udev]]), -+ [], [with_udevdir=\${prefix}/lib/udev]) -+AC_SUBST([udevdir], [$with_udevdir]) -+ - # Checks for header files. - AC_CHECK_HEADERS([fcntl.h libintl.h limits.h locale.h mntent.h stddef.h sys/file.h sys/ioctl.h sys/mount.h sys/time.h sys/vfs.h syslog.h termios.h]) - AC_CHECK_HEADER([linux/fs.h], [], [AC_MSG_ERROR([Unable to find linux/fs.h])]) -@@ -209,7 +215,9 @@ echo " Configure summary" - echo " ===================" - echo " prefix : $prefix" - echo " exec_prefix : $exec_prefix" -+echo " libdir : $libdir" - echo " sbindir : $sbindir" -+echo " udevdir : $udevdir" - echo " ------------------" - echo " debug build : $enable_debug" - echo " C unit tests : $have_check" -diff --git a/gfs2/scripts/Makefile.am b/gfs2/scripts/Makefile.am -index 056aaa5..d4bda04 100644 ---- a/gfs2/scripts/Makefile.am -+++ b/gfs2/scripts/Makefile.am -@@ -5,6 +5,6 @@ dist_sbin_SCRIPTS = \ - gfs2_trace \ - gfs2_withdraw_helper - --noinst_SCRIPTS = \ -+udevrulesdir=@udevdir@/rules.d -+dist_udevrules_DATA = \ - 82-gfs2-withdraw.rules -- diff --git a/SOURCES/bz1236669-1-fsck_gfs2_Change_duptree_structure_to_have_generic_flags.patch b/SOURCES/bz1236669-1-fsck_gfs2_Change_duptree_structure_to_have_generic_flags.patch deleted file mode 100644 index a4a8de1..0000000 --- a/SOURCES/bz1236669-1-fsck_gfs2_Change_duptree_structure_to_have_generic_flags.patch +++ /dev/null @@ -1,76 +0,0 @@ -commit f9b17da3f2e4b278bfcb04465a7a22c45c441d04 -Author: Bob Peterson -Date: Fri Jun 26 12:18:59 2015 -0500 - - fsck.gfs2: Change duptree structure to have generic flags - - This patch does not change any functionality. It merely changes the - specialized first_ref_found flag to a flag within a multi-flag var. - - rhbz#1236669 - -diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h -index 09db668..78e8ad4 100644 ---- a/gfs2/fsck/fsck.h -+++ b/gfs2/fsck/fsck.h -@@ -57,9 +57,11 @@ struct dir_status { - uint32_t entry_count; - }; - -+#define DUPFLAG_REF1_FOUND 1 /* Has the original reference been found? */ -+ - struct duptree { - struct osi_node node; -- int first_ref_found; /* Has the original reference been found? */ -+ int dup_flags; - int refs; - uint64_t block; - osi_list_t ref_inode_list; /* list of inodes referencing a dup block */ -diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c -index efdd132..4022fee 100644 ---- a/gfs2/fsck/util.c -+++ b/gfs2/fsck/util.c -@@ -261,7 +261,6 @@ static struct duptree *gfs2_dup_set(uint64_t dblock, int create) - dt->block = dblock; - dt->refs = 1; /* reference 1 is actually the reference we need to - discover in pass1b. */ -- dt->first_ref_found = 0; - osi_list_init(&dt->ref_inode_list); - osi_list_init(&dt->ref_invinode_list); - osi_link_node(&dt->node, parent, newn); -@@ -326,7 +325,7 @@ int add_duplicate_ref(struct gfs2_inode *ip, uint64_t block, - /* If we found the duplicate reference but we've already discovered - the first reference (in pass1b) and the other references in pass1, - we don't need to count it, so just return. */ -- if (dt->first_ref_found) -+ if (dt->dup_flags & DUPFLAG_REF1_FOUND) - return meta_is_good; - - /* Check for a previous reference to this duplicate */ -@@ -338,7 +337,7 @@ int add_duplicate_ref(struct gfs2_inode *ip, uint64_t block, - that case, we don't want to be confused and consider this second - reference the same as the first. If we do, we'll never be able to - resolve it. The first reference can't be the second reference. */ -- if (id && first && !dt->first_ref_found) { -+ if (id && first && !(dt->dup_flags & DUPFLAG_REF1_FOUND)) { - log_info(_("Original reference to block %llu (0x%llx) was " - "previously found to be bad and deleted.\n"), - (unsigned long long)block, -@@ -347,7 +346,7 @@ int add_duplicate_ref(struct gfs2_inode *ip, uint64_t block, - "(0x%llx) the first reference.\n"), - (unsigned long long)ip->i_di.di_num.no_addr, - (unsigned long long)ip->i_di.di_num.no_addr); -- dt->first_ref_found = 1; -+ dt->dup_flags |= DUPFLAG_REF1_FOUND; - return meta_is_good; - } - -@@ -356,7 +355,7 @@ int add_duplicate_ref(struct gfs2_inode *ip, uint64_t block, - reference, we don't want to increment the reference count because - it's already accounted for. */ - if (first) { -- dt->first_ref_found = 1; -+ dt->dup_flags |= DUPFLAG_REF1_FOUND; - dups_found_first++; /* We found another first ref. */ - } else { - dt->refs++; diff --git a/SOURCES/bz1236669-2-fsck_gfs2_Detect_fix_and_clone_duplicate_block_refs_within_a_dinode.patch b/SOURCES/bz1236669-2-fsck_gfs2_Detect_fix_and_clone_duplicate_block_refs_within_a_dinode.patch deleted file mode 100644 index 3595b4e..0000000 --- a/SOURCES/bz1236669-2-fsck_gfs2_Detect_fix_and_clone_duplicate_block_refs_within_a_dinode.patch +++ /dev/null @@ -1,343 +0,0 @@ -commit ce7b371a5ef76526eeba90b2eb62e1912d9b772f -Author: Bob Peterson -Date: Mon Jun 29 10:53:52 2015 -0500 - - fsck.gfs2: Detect, fix and clone duplicate block refs within a dinode - - Prior to this patch, fsck.gfs2 was unable to detect and fix duplicate - block references within the same file. This patch detects when data - blocks are duplicated within a dinode, then tries to clone the data - to a new block. - - rhbz#1236669 - -diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c -index 9be5a95..ce11fb4 100644 ---- a/gfs2/fsck/fs_recovery.c -+++ b/gfs2/fsck/fs_recovery.c -@@ -668,7 +668,8 @@ static int rangecheck_jmeta(struct gfs2_inode *ip, uint64_t block, - } - - static int rangecheck_jdata(struct gfs2_inode *ip, uint64_t metablock, -- uint64_t block, void *private) -+ uint64_t block, void *private, -+ struct gfs2_buffer_head *bh, uint64_t *ptr) - { - return rangecheck_jblock(ip, block); - } -diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h -index 78e8ad4..a3c5f72 100644 ---- a/gfs2/fsck/fsck.h -+++ b/gfs2/fsck/fsck.h -@@ -58,6 +58,8 @@ struct dir_status { - }; - - #define DUPFLAG_REF1_FOUND 1 /* Has the original reference been found? */ -+#define DUPFLAG_REF1_IS_DUPL 2 /* The original reference is also where we -+ determined there was a duplicate. */ - - struct duptree { - struct osi_node node; -diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c -index 4d5a660..333bec6 100644 ---- a/gfs2/fsck/metawalk.c -+++ b/gfs2/fsck/metawalk.c -@@ -1449,7 +1449,8 @@ static int check_data(struct gfs2_inode *ip, struct metawalk_fxns *pass, - would defeat the rangecheck_block related functions in - pass1. Therefore the individual check_data functions - should do a range check. */ -- rc = pass->check_data(ip, metablock, block, pass->private); -+ rc = pass->check_data(ip, metablock, block, pass->private, -+ bh, ptr); - if (rc && (!error || (rc < error))) { - log_info("\n"); - if (rc < 0) { -@@ -1787,7 +1788,8 @@ int delete_leaf(struct gfs2_inode *ip, uint64_t block, void *private) - } - - int delete_data(struct gfs2_inode *ip, uint64_t metablock, -- uint64_t block, void *private) -+ uint64_t block, void *private, struct gfs2_buffer_head *bh, -+ uint64_t *ptr) - { - return delete_block_if_notdup(ip, block, NULL, _("data"), NULL, - private); -@@ -1915,7 +1917,8 @@ static int alloc_metalist(struct gfs2_inode *ip, uint64_t block, - } - - static int alloc_data(struct gfs2_inode *ip, uint64_t metablock, -- uint64_t block, void *private) -+ uint64_t block, void *private, -+ struct gfs2_buffer_head *bh, uint64_t *ptr) - { - uint8_t q; - const char *desc = (const char *)private; -diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h -index fa4c850..8ec38d0 100644 ---- a/gfs2/fsck/metawalk.h -+++ b/gfs2/fsck/metawalk.h -@@ -29,7 +29,8 @@ extern int delete_metadata(struct gfs2_inode *ip, uint64_t block, - int *was_duplicate, void *private); - extern int delete_leaf(struct gfs2_inode *ip, uint64_t block, void *private); - extern int delete_data(struct gfs2_inode *ip, uint64_t metablock, -- uint64_t block, void *private); -+ uint64_t block, void *private, -+ struct gfs2_buffer_head *bh, uint64_t *ptr); - extern int delete_eattr_indir(struct gfs2_inode *ip, uint64_t block, uint64_t parent, - struct gfs2_buffer_head **bh, void *private); - extern int delete_eattr_leaf(struct gfs2_inode *ip, uint64_t block, uint64_t parent, -@@ -117,7 +118,8 @@ struct metawalk_fxns { - int *is_valid, int *was_duplicate, - void *private); - int (*check_data) (struct gfs2_inode *ip, uint64_t metablock, -- uint64_t block, void *private); -+ uint64_t block, void *private, -+ struct gfs2_buffer_head *bh, uint64_t *ptr); - int (*check_eattr_indir) (struct gfs2_inode *ip, uint64_t block, - uint64_t parent, - struct gfs2_buffer_head **bh, void *private); -diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c -index 0909873..c0f2f1e 100644 ---- a/gfs2/fsck/pass1.c -+++ b/gfs2/fsck/pass1.c -@@ -44,7 +44,8 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block, - static int undo_check_metalist(struct gfs2_inode *ip, uint64_t block, - int h, void *private); - static int check_data(struct gfs2_inode *ip, uint64_t metablock, -- uint64_t block, void *private); -+ uint64_t block, void *private, -+ struct gfs2_buffer_head *bh, uint64_t *ptr); - static int undo_check_data(struct gfs2_inode *ip, uint64_t block, - void *private); - static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect, -@@ -72,7 +73,8 @@ static int invalidate_metadata(struct gfs2_inode *ip, uint64_t block, - static int invalidate_leaf(struct gfs2_inode *ip, uint64_t block, - void *private); - static int invalidate_data(struct gfs2_inode *ip, uint64_t metablock, -- uint64_t block, void *private); -+ uint64_t block, void *private, -+ struct gfs2_buffer_head *bh, uint64_t *ptr); - static int invalidate_eattr_indir(struct gfs2_inode *ip, uint64_t block, - uint64_t parent, - struct gfs2_buffer_head **bh, -@@ -441,7 +443,8 @@ out: - } - - static int check_data(struct gfs2_inode *ip, uint64_t metablock, -- uint64_t block, void *private) -+ uint64_t block, void *private, -+ struct gfs2_buffer_head *bbh, uint64_t *ptr) - { - uint8_t q; - struct block_count *bc = (struct block_count *) private; -@@ -969,7 +972,8 @@ static int invalidate_leaf(struct gfs2_inode *ip, uint64_t block, - } - - static int invalidate_data(struct gfs2_inode *ip, uint64_t metablock, -- uint64_t block, void *private) -+ uint64_t block, void *private, -+ struct gfs2_buffer_head *bh, uint64_t *ptr) - { - return mark_block_invalid(ip, block, ref_as_data, _("data"), - NULL, NULL); -@@ -1069,7 +1073,8 @@ static int rangecheck_leaf(struct gfs2_inode *ip, uint64_t block, - } - - static int rangecheck_data(struct gfs2_inode *ip, uint64_t metablock, -- uint64_t block, void *private) -+ uint64_t block, void *private, -+ struct gfs2_buffer_head *bh, uint64_t *ptr) - { - return rangecheck_block(ip, block, NULL, btype_data, private); - } -diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c -index a8f3d28..c1598ff 100644 ---- a/gfs2/fsck/pass1b.c -+++ b/gfs2/fsck/pass1b.c -@@ -28,6 +28,11 @@ struct dup_handler { - int ref_count; - }; - -+struct clone_target { -+ uint64_t dup_block; -+ int first; -+}; -+ - static void log_inode_reference(struct duptree *dt, osi_list_t *tmp, int inval) - { - char reftypestring[32]; -@@ -249,6 +254,116 @@ static void revise_dup_handler(uint64_t dup_blk, struct dup_handler *dh) - } - } - -+static int clone_check_meta(struct gfs2_inode *ip, uint64_t block, -+ struct gfs2_buffer_head **bh, int h, -+ int *is_valid, int *was_duplicate, void *private) -+{ -+ *was_duplicate = 0; -+ *is_valid = 1; -+ *bh = bread(ip->i_sbd, block); -+ return 0; -+} -+ -+/* clone_data - clone a duplicate reference -+ * -+ * This function remembers the first reference to the specified block, and -+ * clones all subsequent references to it (with permission). -+ */ -+static int clone_data(struct gfs2_inode *ip, uint64_t metablock, -+ uint64_t block, void *private, -+ struct gfs2_buffer_head *bh, uint64_t *ptr) -+{ -+ struct clone_target *clonet = (struct clone_target *)private; -+ struct gfs2_buffer_head *clone_bh; -+ uint64_t cloneblock; -+ int error; -+ -+ if (block != clonet->dup_block) -+ return 0; -+ -+ if (clonet->first) { -+ log_debug(_("Inode %lld (0x%llx)'s first reference to " -+ "block %lld (0x%llx) is targeted for cloning.\n"), -+ (unsigned long long)ip->i_di.di_num.no_addr, -+ (unsigned long long)ip->i_di.di_num.no_addr, -+ (unsigned long long)block, -+ (unsigned long long)block); -+ clonet->first = 0; -+ return 0; -+ } -+ log_err(_("Error: Inode %lld (0x%llx)'s subsequent reference to " -+ "block %lld (0x%llx) is an error.\n"), -+ (unsigned long long)ip->i_di.di_num.no_addr, -+ (unsigned long long)ip->i_di.di_num.no_addr, -+ (unsigned long long)block, (unsigned long long)block); -+ if (query( _("Okay to clone the duplicated reference? (y/n) "))) { -+ error = lgfs2_meta_alloc(ip, &cloneblock); -+ if (!error) { -+ clone_bh = bread(ip->i_sbd, clonet->dup_block); -+ if (clone_bh) { -+ fsck_blockmap_set(ip, cloneblock, _("data"), -+ GFS2_BLKST_USED); -+ clone_bh->b_blocknr = cloneblock; -+ bmodified(clone_bh); -+ brelse(clone_bh); -+ /* Now fix the reference: */ -+ *ptr = cpu_to_be64(cloneblock); -+ bmodified(bh); -+ log_err(_("Duplicate reference to block %lld " -+ "(0x%llx) was cloned to block %lld " -+ "(0x%llx).\n"), -+ (unsigned long long)block, -+ (unsigned long long)block, -+ (unsigned long long)cloneblock, -+ (unsigned long long)cloneblock); -+ return 0; -+ } -+ } -+ log_err(_("Error: Unable to allocate a new data block.\n")); -+ if (!query("Should I zero the reference instead? (y/n)")) { -+ log_err(_("Duplicate reference to block %lld " -+ "(0x%llx) was not fixed.\n"), -+ (unsigned long long)block, -+ (unsigned long long)block); -+ return 0; -+ } -+ *ptr = 0; -+ bmodified(bh); -+ log_err(_("Duplicate reference to block %lld (0x%llx) was " -+ "zeroed.\n"), -+ (unsigned long long)block, -+ (unsigned long long)block); -+ } else { -+ log_err(_("Duplicate reference to block %lld (0x%llx) " -+ "was not fixed.\n"), (unsigned long long)block, -+ (unsigned long long)block); -+ } -+ return 0; -+} -+ -+/* clone_dup_ref_in_inode - clone a duplicate reference within a single inode -+ * -+ * This function traverses the metadata tree of an inode, cloning all -+ * but the first reference to a duplicate block reference. -+ */ -+static void clone_dup_ref_in_inode(struct gfs2_inode *ip, struct duptree *dt) -+{ -+ int error; -+ struct clone_target clonet = {.dup_block = dt->block, .first = 1}; -+ struct metawalk_fxns pass1b_fxns_clone = { -+ .private = &clonet, -+ .check_metalist = clone_check_meta, -+ .check_data = clone_data, -+ }; -+ -+ error = check_metatree(ip, &pass1b_fxns_clone); -+ if (error) { -+ log_err(_("Error cloning duplicate reference(s) to block %lld " -+ "(0x%llx).\n"), (unsigned long long)dt->block, -+ (unsigned long long)dt->block); -+ } -+} -+ - /* handle_dup_blk - handle a duplicate block reference. - * - * This function should resolve and delete the duplicate block reference given, -@@ -389,6 +504,9 @@ static int handle_dup_blk(struct gfs2_sbd *sdp, struct duptree *dt) - (unsigned long long)id->block_no); - ip = fsck_load_inode(sdp, id->block_no); - -+ if (dt->dup_flags & DUPFLAG_REF1_IS_DUPL) -+ clone_dup_ref_in_inode(ip, dt); -+ - q = block_type(id->block_no); - if (q == GFS2_BLKST_UNLINKED) { - log_debug( _("The remaining reference inode %lld " -@@ -468,7 +586,8 @@ static int check_metalist_refs(struct gfs2_inode *ip, uint64_t block, - } - - static int check_data_refs(struct gfs2_inode *ip, uint64_t metablock, -- uint64_t block, void *private) -+ uint64_t block, void *private, -+ struct gfs2_buffer_head *bh, uint64_t *ptr) - { - return add_duplicate_ref(ip, block, ref_as_data, 1, INODE_VALID); - } -diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c -index b31fbd4..900d4e1 100644 ---- a/gfs2/fsck/pass2.c -+++ b/gfs2/fsck/pass2.c -@@ -1580,7 +1580,8 @@ static int check_metalist_qc(struct gfs2_inode *ip, uint64_t block, - } - - static int check_data_qc(struct gfs2_inode *ip, uint64_t metablock, -- uint64_t block, void *private) -+ uint64_t block, void *private, -+ struct gfs2_buffer_head *bbh, uint64_t *ptr) - { - struct gfs2_buffer_head *bh; - -diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c -index 4022fee..a6a5cdc 100644 ---- a/gfs2/fsck/util.c -+++ b/gfs2/fsck/util.c -@@ -339,15 +339,16 @@ int add_duplicate_ref(struct gfs2_inode *ip, uint64_t block, - resolve it. The first reference can't be the second reference. */ - if (id && first && !(dt->dup_flags & DUPFLAG_REF1_FOUND)) { - log_info(_("Original reference to block %llu (0x%llx) was " -- "previously found to be bad and deleted.\n"), -+ "either found to be bad and deleted, or else " -+ "a duplicate within the same inode.\n"), - (unsigned long long)block, - (unsigned long long)block); - log_info(_("I'll consider the reference from inode %llu " - "(0x%llx) the first reference.\n"), - (unsigned long long)ip->i_di.di_num.no_addr, - (unsigned long long)ip->i_di.di_num.no_addr); -- dt->dup_flags |= DUPFLAG_REF1_FOUND; -- return meta_is_good; -+ dt->dup_flags |= DUPFLAG_REF1_IS_DUPL; -+ dt->refs++; - } - - /* The first time this is called from pass1 is actually the second diff --git a/SOURCES/bz1326508-gfs2_5_Clarify_the_availability_of_the_loccookie_option.patch b/SOURCES/bz1326508-gfs2_5_Clarify_the_availability_of_the_loccookie_option.patch new file mode 100644 index 0000000..ea9f946 --- /dev/null +++ b/SOURCES/bz1326508-gfs2_5_Clarify_the_availability_of_the_loccookie_option.patch @@ -0,0 +1,27 @@ +commit 704beb265cd6f860a10f4a5ae0fd8c52e72bf392 +Author: Andrew Price +Date: Tue Jul 19 15:41:13 2016 +0100 + + gfs2(5): Clarify the availability of the loccookie option + + The loccookie option was added in kernel-3.10.0-341.el7 but the first + release will be RHEL 7.3 so use that to clarify when 'loccookie' appears + in RHEL7. + + Resolves: rhbz#1326508 + + Signed-off-by: Andrew Price + +diff --git a/gfs2/man/gfs2.5 b/gfs2/man/gfs2.5 +index 56d1a00..6c77519 100644 +--- a/gfs2/man/gfs2.5 ++++ b/gfs2/man/gfs2.5 +@@ -193,7 +193,7 @@ give out well over half a billion location based cookies. This option was added + in the 4.5 Linux kernel. Prior to this kernel, gfs2 did not add directory + entries in a way that allowed it to use location based readdir cookies. + \fBNote:\fP To safely turn on this option, all nodes mounting the filesystem +-must be running at least a 4.5 Linux kernel. If this option is only enabled on ++must be running at least a 4.5 Linux kernel or RHEL 7.3. If this option is only enabled on + some of the nodes mounting a filesystem, the cookies returned by nodes using + this option will not be valid on nodes that are not using this option, and vice + versa. Finally, when first enabling this option on a filesystem that had been diff --git a/SOURCES/bz1348703-fsck_gfs2_undo_functions_can_stop_too_early_on_duplicates.patch b/SOURCES/bz1348703-fsck_gfs2_undo_functions_can_stop_too_early_on_duplicates.patch new file mode 100644 index 0000000..ff0ae59 --- /dev/null +++ b/SOURCES/bz1348703-fsck_gfs2_undo_functions_can_stop_too_early_on_duplicates.patch @@ -0,0 +1,197 @@ +commit 0a0d4af99c9be8abc863e272d6e7f46bb6ad4b41 +Author: Bob Peterson +Date: Tue Jun 21 14:52:06 2016 -0500 + + fsck.gfs2: "undo" functions can stop too early on duplicates + + This patch addresses a bug in which blocks may not be freed properly + because the "undo" processing in pass1 can stop early when duplicate + data blocks are encountered. What happens is this: The "undo" process + called from metawalk.c is coded to stop its undo when it encounters + the block containing corruption. However, if the block containing the + corruption is actually the second reference to the same block, inside + the same dinode, the undo process stops early when it encounters the + first reference. The problem is that it's coded to stop when it sees + a reference to the corrupt block. That's wrong. It should really + stop when it sees the reference to that block that triggered the + "unrecoverable" error. In other words, when it hits that exact + metadata block and its offset. This patch scraps the old system of + looking for the corrupt block in favor of looking for the corrupt + reference, including metadata block and offset within that block. + + Signed-off-by: Bob Peterson + + This is a RHEL7 port of this upstream patch: + https://git.fedorahosted.org/cgit/gfs2-utils.git/commit/?id=6b40deabbbbd59a1cbddbe633984214b6752d25a + + rhbz#1348703 + +diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h +index 73cff4c..8af4eb4 100644 +--- a/gfs2/fsck/fsck.h ++++ b/gfs2/fsck/fsck.h +@@ -106,6 +106,12 @@ enum rgindex_trust_level { /* how far can we trust our RG index? */ + must have been converted from gfs2_convert. */ + }; + ++struct error_block { ++ uint64_t metablk; /* metadata block where error was found */ ++ int metaoff; /* offset in that metadata block where error found */ ++ uint64_t errblk; /* error block */ ++}; ++ + extern struct gfs2_inode *fsck_load_inode(struct gfs2_sbd *sdp, uint64_t block); + extern struct gfs2_inode *fsck_inode_get(struct gfs2_sbd *sdp, + struct rgrp_tree *rgd, +diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c +index c0cc2ab..fecf33e 100644 +--- a/gfs2/fsck/metawalk.c ++++ b/gfs2/fsck/metawalk.c +@@ -1387,7 +1387,7 @@ error_undo: /* undo what we've done so far for this block */ + */ + static int check_data(struct gfs2_inode *ip, struct metawalk_fxns *pass, + struct gfs2_buffer_head *bh, int head_size, +- uint64_t *blks_checked, uint64_t *error_blk) ++ uint64_t *blks_checked, struct error_block *error_blk) + { + int error = 0, rc = 0; + uint64_t block, *ptr; +@@ -1418,21 +1418,36 @@ static int check_data(struct gfs2_inode *ip, struct metawalk_fxns *pass, + log_info("\n"); + if (rc < 0) { + /* A fatal error trumps a non-fatal one. */ +- if ((*error_blk == 0) || (rc < error)) { +- log_debug(_("Fatal error on block 0x" +- "%llx preempts non-fatal " +- "error on block 0x%llx\n"), ++ if ((error_blk->errblk == 0) || ++ (rc < error)) { ++ log_debug(_("Fatal error on metadata " ++ "block 0x%llx, offset " ++ "0x%x, referencing block " ++ "0x%llx preempts non-fatal" ++ " error on block 0x%llx\n"), ++ (unsigned long long)metablock, ++ (int)(ptr - ptr_start), + (unsigned long long)block, +- (unsigned long long)*error_blk); +- *error_blk = block; ++ (unsigned long long)error_blk->errblk); ++ error_blk->metablk = metablock; ++ error_blk->metaoff = ptr - ptr_start; ++ error_blk->errblk = block; + } + log_info(_("Unrecoverable ")); + } else { /* nonfatal error */ +- if ((*error_blk) == 0) +- *error_blk = block; ++ if (error_blk->errblk == 0) { ++ error_blk->metablk = metablock; ++ error_blk->metaoff = ptr - ptr_start; ++ error_blk->errblk = block; ++ } + } +- log_info(_("data block error %d on block %llu " +- "(0x%llx).\n"), rc, ++ log_info(_("data block error %d on metadata block " ++ "%lld (0x%llx), offset %d (0x%x), " ++ "referencing data block %lld (0x%llx).\n"), ++ rc, (unsigned long long)metablock, ++ (unsigned long long)metablock, ++ (int)(ptr - ptr_start), ++ (int)(ptr - ptr_start), + (unsigned long long)block, + (unsigned long long)block); + error = rc; +@@ -1445,8 +1460,9 @@ static int check_data(struct gfs2_inode *ip, struct metawalk_fxns *pass, + } + + static int undo_check_data(struct gfs2_inode *ip, struct metawalk_fxns *pass, ++ uint64_t metablock, + uint64_t *ptr_start, char *ptr_end, +- uint64_t error_blk, int error) ++ struct error_block *error_blk, int error) + { + int rc = 0; + uint64_t block, *ptr; +@@ -1460,19 +1476,27 @@ static int undo_check_data(struct gfs2_inode *ip, struct metawalk_fxns *pass, + if (skip_this_pass || fsck_abort) + return 1; + block = be64_to_cpu(*ptr); +- if (block == error_blk) { ++ if (metablock == error_blk->metablk && ++ (ptr - ptr_start == error_blk->metaoff) && ++ block == error_blk->errblk) { + if (error < 0) { /* A fatal error that stopped it? */ + log_debug(_("Stopping the undo process: " + "fatal error block 0x%llx was " +- "found.\n"), +- (unsigned long long)error_blk); ++ "found at metadata block 0x%llx," ++ "offset 0x%x.\n"), ++ (unsigned long long)error_blk->errblk, ++ (unsigned long long)error_blk->metablk, ++ error_blk->metaoff); + return 1; + } + found_error_blk = 1; + log_debug(_("The non-fatal error block 0x%llx was " +- "found, but undo processing will continue " ++ "found at metadata block 0x%llx, offset " ++ "0x%d, but undo processing will continue " + "until the end of this metadata block.\n"), +- (unsigned long long)error_blk); ++ (unsigned long long)error_blk->errblk, ++ (unsigned long long)error_blk->metablk, ++ error_blk->metaoff); + } + rc = pass->undo_check_data(ip, block, pass->private); + if (rc < 0) +@@ -1514,7 +1538,7 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass) + uint64_t blks_checked = 0; + int error, rc; + int metadata_clean = 0; +- uint64_t error_blk = 0; ++ struct error_block error_blk = {0, 0, 0}; + int hit_error_blk = 0; + + if (!height && !is_dir(&ip->i_di, ip->i_sbd->gfs1)) +@@ -1577,10 +1601,15 @@ undo_metalist: + if (!error) + goto out; + log_err( _("Error: inode %llu (0x%llx) had unrecoverable errors at " ++ "metadata block %lld (0x%llx), offset %d (0x%x), block " + "%lld (0x%llx).\n"), + (unsigned long long)ip->i_di.di_num.no_addr, + (unsigned long long)ip->i_di.di_num.no_addr, +- (unsigned long long)error_blk, (unsigned long long)error_blk); ++ (unsigned long long)error_blk.metablk, ++ (unsigned long long)error_blk.metablk, ++ error_blk.metaoff, error_blk.metaoff, ++ (unsigned long long)error_blk.errblk, ++ (unsigned long long)error_blk.errblk); + if (!query( _("Remove the invalid inode? (y/n) "))) { + free_metalist(ip, &metalist[0]); + log_err(_("Invalid inode not deleted.\n")); +@@ -1606,12 +1635,20 @@ undo_metalist: + head_size = hdr_size(bh, height); + if (head_size) { + rc = undo_check_data(ip, pass, ++ bh->b_blocknr, + (uint64_t *) + (bh->b_data + head_size), + (bh->b_data + ip->i_sbd->bsize), +- error_blk, error); ++ &error_blk, ++ error); + if (rc > 0) { + hit_error_blk = 1; ++ log_err("Reached the error " ++ "block undoing work " ++ "for inode %lld " ++ "(0x%llx).\n", ++ (unsigned long long)ip->i_di.di_num.no_addr, ++ (unsigned long long)ip->i_di.di_num.no_addr); + rc = 0; + } + } diff --git a/SOURCES/bz1350597-fsck_gfs2_link_count_checking_wrong_inode_s_formal_inode_number.patch b/SOURCES/bz1350597-fsck_gfs2_link_count_checking_wrong_inode_s_formal_inode_number.patch new file mode 100644 index 0000000..bd97bd7 --- /dev/null +++ b/SOURCES/bz1350597-fsck_gfs2_link_count_checking_wrong_inode_s_formal_inode_number.patch @@ -0,0 +1,54 @@ +commit 1adddb1098c10766ae2587d393c1612e5670a52d +Author: Bob Peterson +Date: Thu Jun 23 08:16:25 2016 -0500 + + fsck.gfs2: link count checking wrong inode's formal inode number + + This patch fixes a bug whereby inodes that aren't in the dirtree or + the inodetree are checking the wrong formal inode number. Function + incr_link_count checks the wrong inode value, and thus reports an + error where there are none. Also, when the error is reported back, + it reports the wrong value, using a copy of the inum value. In this + case, it should look up the dentry's inode's formal inode number. + This should only hurt performance in error cases. + + Signed-off-by: Bob Peterson + + This is a RHEL7 port of this upstream patch: + https://git.fedorahosted.org/cgit/gfs2-utils.git/commit/?id=ad19203f04caa3fb1c777250a21fe1a968999e8f + + rhbz#1350597 + +diff --git a/gfs2/fsck/link.c b/gfs2/fsck/link.c +index 0243d85..00636d7 100644 +--- a/gfs2/fsck/link.c ++++ b/gfs2/fsck/link.c +@@ -112,7 +112,7 @@ int incr_link_count(struct gfs2_inum no, struct gfs2_inode *ip, + + link_ip = fsck_load_inode(ip->i_sbd, no.no_addr); + /* Check formal ino against dinode before adding to inode tree. */ +- if (no.no_formal_ino != ip->i_di.di_num.no_formal_ino) { ++ if (no.no_formal_ino != link_ip->i_di.di_num.no_formal_ino) { + fsck_inode_put(&link_ip); + return 1; + } +diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c +index f808cea..8ac5547 100644 +--- a/gfs2/fsck/pass2.c ++++ b/gfs2/fsck/pass2.c +@@ -195,8 +195,13 @@ static int bad_formal_ino(struct gfs2_inode *ip, struct gfs2_dirent *dent, + di = dirtree_find(entry.no_addr); + if (di) + inum = di->dinode; +- else if (link1_type(&clink1map, entry.no_addr) == 1) +- inum = entry; ++ else if (link1_type(&clink1map, entry.no_addr) == 1) { ++ struct gfs2_inode *dent_ip; ++ ++ dent_ip = fsck_load_inode(ip->i_sbd, entry.no_addr); ++ inum = dent_ip->i_di.di_num; ++ fsck_inode_put(&dent_ip); ++ } + } + log_err( _("Directory entry '%s' pointing to block %llu (0x%llx) in " + "directory %llu (0x%llx) has the wrong 'formal' inode " diff --git a/SOURCES/bz1350600-fsck_gfs2_check_formal_inode_number_when_links_go_from_1_to_2.patch b/SOURCES/bz1350600-fsck_gfs2_check_formal_inode_number_when_links_go_from_1_to_2.patch new file mode 100644 index 0000000..eab270f --- /dev/null +++ b/SOURCES/bz1350600-fsck_gfs2_check_formal_inode_number_when_links_go_from_1_to_2.patch @@ -0,0 +1,272 @@ +commit c78fedfd07a455e934b0a603c9c2e124b9522662 +Author: Bob Peterson +Date: Fri Jun 24 08:53:41 2016 -0500 + + fsck.gfs2: check formal inode number when links go from 1 to 2 + + Before commit f2ffb1e, function basic_dentry_checks had access to a + complete inode tree, so it was able to check the formal inode number + of every dentry against what it previously found in the inode in + pass1. But commit f2ffb1e changed function basic_dentry_checks so + that it bypasses the check if the reference count is 1, which is + most likely, and it's going to be correct 99% of the time. The + comments state: + + "Since we don't have ii or di, the only way to validate formal_ino + is to read in the inode, which would kill performance. So skip it + for now." + + The problem is, problems can slip through, undetected, and will + only be fixed with a second run of fsck.gfs2. For example, during + testing, I found a set of gfs2 metadata that had two dentries + pointing to the same dinode. The first dentry encountered by pass2 + was wrong, but it was not checked for this reason. The second + dentry was correct. The first run of fsck did not catch the problem + and reacted by setting link count to 2 for the dinode, keeping + both dentries. The second run found the problem and fixed it, + changing the link count back to 1 and deleting the bad dentry. + + Note that this problem only applies to non-directories, since + directories will have a value in the dirtree to check against. + + This patch solves the problem with a new "innocent until proven + guilty" approach. When the first dentry reference is found, it is + assumed to be correct (most files will have a single link). + When the second dentry reference is found, it goes back and checks + the original reference. To do that, it takes the (time expensive) + step of traversing the directory tree, searching every directory + for the original reference. Once the original dentry is found, it + checks its formal inode number against the one that has been proven + correct. This situation ought to be quite rare because the vast + number of files will have a single correct link. So hopefully only + valid hard links will cause the slow tree traversal. Once the first + dentry is found, the tree traversal stops and pass2 continues its + work. + + Signed-off-by: Bob Peterson + + This is a RHEL7 port of this upstream patch: + https://git.fedorahosted.org/cgit/gfs2-utils.git/commit/?id=ab92c41323babc6b6578cddfb4324ae545927f88 + + rhbz#1350600 + +diff --git a/gfs2/fsck/link.c b/gfs2/fsck/link.c +index 00636d7..8ea09c7 100644 +--- a/gfs2/fsck/link.c ++++ b/gfs2/fsck/link.c +@@ -88,33 +88,33 @@ int incr_link_count(struct gfs2_inum no, struct gfs2_inode *ip, + di = dirtree_find(no.no_addr); + if (di) { + if (di->dinode.no_formal_ino != no.no_formal_ino) +- return 1; ++ return incr_link_ino_mismatch; + + di->counted_links++; + whyincr(no.no_addr, why, referenced_from, di->counted_links); +- return 0; ++ return incr_link_good; + } + ii = inodetree_find(no.no_addr); + /* If the list has entries, look for one that matches inode_no */ + if (ii) { + if (ii->di_num.no_formal_ino != no.no_formal_ino) +- return 1; ++ return incr_link_ino_mismatch; + + ii->counted_links++; + whyincr(no.no_addr, why, referenced_from, ii->counted_links); +- return 0; ++ return incr_link_good; + } + if (link1_type(&clink1map, no.no_addr) != 1) { + link1_set(&clink1map, no.no_addr, 1); + whyincr(no.no_addr, why, referenced_from, 1); +- return 0; ++ return incr_link_good; + } + + link_ip = fsck_load_inode(ip->i_sbd, no.no_addr); + /* Check formal ino against dinode before adding to inode tree. */ + if (no.no_formal_ino != link_ip->i_di.di_num.no_formal_ino) { + fsck_inode_put(&link_ip); +- return 1; ++ return incr_link_ino_mismatch; /* inode mismatch */ + } + /* Move it from the link1 maps to a real inode tree entry */ + link1_set(&nlink1map, no.no_addr, 0); +@@ -130,7 +130,7 @@ int incr_link_count(struct gfs2_inum no, struct gfs2_inode *ip, + (unsigned long long)referenced_from, + (unsigned long long)no.no_addr); + fsck_inode_put(&link_ip); +- return -1; ++ return incr_link_bad; + } + ii->di_num = link_ip->i_di.di_num; + fsck_inode_put(&link_ip); +@@ -138,7 +138,11 @@ int incr_link_count(struct gfs2_inum no, struct gfs2_inode *ip, + nlink1map */ + ii->counted_links = 2; + whyincr(no.no_addr, why, referenced_from, ii->counted_links); +- return 0; ++ /* We transitioned a dentry link count from 1 to 2, and we know it's ++ not a directory. But the new reference has the correct formal ++ inode number, so the first reference is suspect: we need to ++ check it in case it's a bad reference, and not just a hard link. */ ++ return incr_link_check_orig; + } + + #define whydecr(no_addr, why, referenced_from, counted_links) \ +diff --git a/gfs2/fsck/link.h b/gfs2/fsck/link.h +index 14534e5..a5dd1c8 100644 +--- a/gfs2/fsck/link.h ++++ b/gfs2/fsck/link.h +@@ -4,6 +4,13 @@ + extern struct gfs2_bmap nlink1map; /* map of dinodes with nlink == 1 */ + extern struct gfs2_bmap clink1map; /* map of dinodes w/counted links == 1 */ + ++enum { ++ incr_link_bad = -1, ++ incr_link_good = 0, ++ incr_link_ino_mismatch = 1, ++ incr_link_check_orig = 2, ++}; ++ + int link1_set(struct gfs2_bmap *bmap, uint64_t bblock, int mark); + int set_di_nlink(struct gfs2_inode *ip); + int incr_link_count(struct gfs2_inum no, struct gfs2_inode *ip, +diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c +index 8ac5547..808cf21 100644 +--- a/gfs2/fsck/pass2.c ++++ b/gfs2/fsck/pass2.c +@@ -667,6 +667,113 @@ static int basic_dentry_checks(struct gfs2_inode *ip, struct gfs2_dirent *dent, + return 0; + } + ++static int dirref_find(struct gfs2_inode *ip, struct gfs2_dirent *dent, ++ struct gfs2_dirent *prev, struct gfs2_buffer_head *bh, ++ char *filename, uint32_t *count, int *lindex, ++ void *private) ++{ ++ /* the metawalk_fxn's private field must be set to the dentry ++ * block we want to clear */ ++ struct gfs2_inum *entry = (struct gfs2_inum *)private; ++ struct gfs2_dirent dentry, *de; ++ char fn[MAX_FILENAME]; ++ ++ memset(&dentry, 0, sizeof(struct gfs2_dirent)); ++ gfs2_dirent_in(&dentry, (char *)dent); ++ de = &dentry; ++ ++ if (de->de_inum.no_addr != entry->no_addr) { ++ (*count)++; ++ return 0; ++ } ++ if (de->de_inum.no_formal_ino == dent->de_inum.no_formal_ino) { ++ log_debug("Formal inode number matches; must be a hard " ++ "link.\n"); ++ goto out; ++ } ++ log_err(_("The original reference to inode %lld (0x%llx) from " ++ "directory %lld (0x%llx) has the wrong 'formal' inode " ++ "number.\n"), (unsigned long long)entry->no_addr, ++ (unsigned long long)entry->no_addr, ++ (unsigned long long)ip->i_di.di_num.no_addr, ++ (unsigned long long)ip->i_di.di_num.no_addr); ++ memset(fn, 0, sizeof(fn)); ++ if (de->de_name_len < MAX_FILENAME) ++ strncpy(fn, filename, de->de_name_len); ++ else ++ strncpy(fn, filename, MAX_FILENAME - 1); ++ log_err(_("The bad reference '%s' had formal inode number: %lld " ++ "(0x%llx) but the correct value is: %lld (0x%llx)\n"), ++ fn, (unsigned long long)de->de_inum.no_formal_ino, ++ (unsigned long long)de->de_inum.no_formal_ino, ++ (unsigned long long)entry->no_formal_ino, ++ (unsigned long long)entry->no_formal_ino); ++ if (!query(_("Delete the bad directory entry? (y/n) "))) { ++ log_err(_("The corrupt directory entry was not fixed.\n")); ++ goto out; ++ } ++ decr_link_count(entry->no_addr, ip->i_di.di_num.no_addr, ++ ip->i_sbd->gfs1, _("bad original reference")); ++ dirent2_del(ip, bh, prev, dent); ++ log_err(_("The corrupt directory entry '%s' was deleted.\n"), fn); ++out: ++ return -1; /* force check_dir to stop; don't waste time. */ ++} ++ ++/** ++ * check_suspicious_dirref - double-check a questionable first dentry ref ++ * ++ * This function is called when a dentry has caused us to increment the ++ * link count to a file from 1 to 2, and we know the object pointed to is ++ * not a directory. (Most likely, it'a a file). The second directory to ++ * reference the dinode has the correct formal inode number, but when we ++ * created the original reference in the counted links bitmap (clink1map), ++ * we had no way to check the formal inode number. (Well, we could have read ++ * in the dinode, but that would kill fsck.gfs2 performance.) ++ * So now we have to walk through the directory tree and find that original ++ * reference so make sure it's a valid reference. If the formal inode number ++ * is the same, it's a hard link (which is unlikely for gfs2). If it's not ++ * the same, that's an error, and we need to delete the damaged original ++ * dentry, since we failed to detect the problem earlier. ++ */ ++static int check_suspicious_dirref(struct gfs2_sbd *sdp, ++ struct gfs2_inum *entry) ++{ ++ struct osi_node *tmp, *next = NULL; ++ struct dir_info *dt; ++ struct gfs2_inode *ip; ++ uint64_t dirblk; ++ int error = FSCK_OK; ++ struct metawalk_fxns dirref_hunt = { ++ .private = (void *)entry, ++ .check_dentry = dirref_find, ++ }; ++ ++ log_debug("This dentry is good, but since this is a second " ++ "reference to block 0x%llx, we need to check the " ++ "original.\n", (unsigned long long)entry->no_addr); ++ for (tmp = osi_first(&dirtree); tmp; tmp = next) { ++ next = osi_next(tmp); ++ dt = (struct dir_info *)tmp; ++ dirblk = dt->dinode.no_addr; ++ if (skip_this_pass || fsck_abort) /* asked to skip the rest */ ++ break; ++ ip = fsck_load_inode(sdp, dirblk); ++ if (ip == NULL) { ++ stack; ++ return FSCK_ERROR; ++ } ++ error = check_dir(sdp, ip, &dirref_hunt); ++ fsck_inode_put(&ip); ++ /* Error just means we found the dentry and dealt with it. */ ++ if (error) ++ break; ++ } ++ log_debug("Original reference check complete. Found = %d.\n", ++ error ? 1 : 0); ++ return 0; ++} ++ + /* FIXME: should maybe refactor this a bit - but need to deal with + * FIXMEs internally first */ + static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, +@@ -870,10 +977,13 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, + dentry_is_valid: + /* This directory inode links to this inode via this dentry */ + error = incr_link_count(entry, ip, _("valid reference")); +- if (error > 0 && +- bad_formal_ino(ip, dent, entry, tmp_name, q, de, bh) == 1) +- goto nuke_dentry; +- ++ if (error == incr_link_check_orig) { ++ error = check_suspicious_dirref(sdp, &entry); ++ } else if (error == incr_link_ino_mismatch) { ++ log_err("incr_link_count err=%d.\n", error); ++ if (bad_formal_ino(ip, dent, entry, tmp_name, q, de, bh) == 1) ++ goto nuke_dentry; ++ } + (*count)++; + ds->entry_count++; + /* End of checks */ diff --git a/SPECS/gfs2-utils.spec b/SPECS/gfs2-utils.spec index 7fbb8a7..ba8a3bf 100644 --- a/SPECS/gfs2-utils.spec +++ b/SPECS/gfs2-utils.spec @@ -11,8 +11,8 @@ ############################################################################### Name: gfs2-utils -Version: 3.1.8 -Release: 6%{?dist} +Version: 3.1.9 +Release: 3%{?dist} License: GPLv2+ and LGPLv2+ Group: System Environment/Kernel Summary: Utilities for managing the global file system (GFS2) @@ -41,29 +41,19 @@ ExclusiveArch: x86_64 s390x # ./make-tarball.sh # Source0: https://fedorahosted.org/released/gfs2-utils/gfs2-utils-%{version}.tar.gz -Patch0: bz1186515-fsck_gfs2_replace_recent_i_goal_fixes_with_simple_logic.patch -Patch1: bz1202831-mkfs_gfs2_Allow_longer_cluster_names.patch -Patch2: bz1236669-1-fsck_gfs2_Change_duptree_structure_to_have_generic_flags.patch -Patch3: bz1236669-2-fsck_gfs2_Detect_fix_and_clone_duplicate_block_refs_within_a_dinode.patch -Patch4: bz1225634-1-gfs2_utils_Fix_hang_on_withdraw.patch -Patch5: bz1225634-2-scripts_rename_gfs2_wd_udev_sh_to_gfs2_withdraw_helper.patch -Patch6: bz1225634-3-scripts_install_the_withdraw_helper_script.patch -Patch7: bz1225634-4-scripts_install_the_withdraw_udev_rules_script.patch -Patch8: bz1162216-gfs2_edit_savemeta_speed_up_is_block_in_per_node.patch +Patch0: bz1348703-fsck_gfs2_undo_functions_can_stop_too_early_on_duplicates.patch +Patch1: bz1350597-fsck_gfs2_link_count_checking_wrong_inode_s_formal_inode_number.patch +Patch2: bz1350600-fsck_gfs2_check_formal_inode_number_when_links_go_from_1_to_2.patch +Patch3: bz1326508-gfs2_5_Clarify_the_availability_of_the_loccookie_option.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) %prep %setup -q -n gfs2-utils-%{version} -%patch0 -p1 -b .bz1186515-fsck_gfs2_replace_recent_i_goal_fixes_with_simple_logic -%patch1 -p1 -b .bz1202831-mkfs_gfs2_Allow_longer_cluster_names -%patch2 -p1 -b .bz1236669-1-fsck_gfs2_Change_duptree_structure_to_have_generic_flags -%patch3 -p1 -b .bz1236669-2-fsck_gfs2_Detect_fix_and_clone_duplicate_block_refs_within_a_dinode -%patch4 -p1 -b .bz1225634-1-gfs2_utils_Fix_hang_on_withdraw -%patch5 -p1 -b .bz1225634-2-scripts_rename_gfs2_wd_udev_sh_to_gfs2_withdraw_helper -%patch6 -p1 -b .bz1225634-3-scripts_install_the_withdraw_helper_script -%patch7 -p1 -b .bz1225634-4-scripts_install_the_withdraw_udev_rules_script -%patch8 -p1 -b .bz1162216-gfs2_edit_savemeta_speed_up_is_block_in_per_node +%patch0 -p1 -b .bz1348703-fsck_gfs2_undo_functions_can_stop_too_early_on_duplicates +%patch1 -p1 -b .bz1350597-fsck_gfs2_link_count_checking_wrong_inode_s_formal_inode_number +%patch2 -p1 -b .bz1350600-fsck_gfs2_check_formal_inode_number_when_links_go_from_1_to_2 +%patch3 -p1 -b .bz1326508-gfs2_5_Clarify_the_availability_of_the_loccookie_option %build ./autogen.sh @@ -102,11 +92,37 @@ file systems. %{_sbindir}/gfs2_edit %{_sbindir}/tunegfs2 %{_sbindir}/gfs2_withdraw_helper +%{_sbindir}/glocktop %{_mandir}/man8/*gfs2* +%{_mandir}/man8/glocktop* %{_mandir}/man5/* %{_prefix}/lib/udev/rules.d/82-gfs2-withdraw.rules %changelog +* Wed Jul 20 2016 Andrew Price - 3.1.9-3 +- gfs2(5): Clarify the availability of the loccookie option + Resolves: rhbz#1326508 + +* Wed Jul 06 2016 Andrew Price - 3.1.9-2 +- fsck.gfs2: "undo" functions can stop too early on duplicates + Resolves: rhbz#1348703 +- fsck.gfs2: link count checking wrong inode's formal inode number + Resolves: rhbz#1350597 +- fsck.gfs2: check formal inode number when links go from 1 to 2 + Resolves: rhbz#1350600 + +* Tue Jun 07 2016 Andrew Price - 3.1.9-1 +- Rebase to new upstream release 3.1.9 + Resolves: rhbz#1271674 + Resolves: rhbz#1162819 + Resolves: rhbz#1196321 + Resolves: rhbz#1202814 + Resolves: rhbz#1251036 + Resolves: rhbz#1257625 + Resolves: rhbz#1268045 + Resolves: rhbz#1283866 + Resolves: rhbz#1332728 + * Thu Sep 17 2015 Andrew Price - 3.1.8-6 - gfs2_edit savemeta: speed up is_block_in_per_node() Resolves: rhbz#1162216