Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 9383e745e23602bc45f9c92184feea59 > files > 55

gfs2-utils-0.1.62-28.el5.src.rpm

commit 800465eaed0ecdee931feb52f9e30467f624c00e
Author: Bob Peterson <bob@ganesha.peterson>
Date:   Mon Jan 25 14:43:14 2010 -0600

    fsck.gfs2: Don't add extended attrib blocks to list twice
    
    This patch adds a simple check to pass1 where it is adding a
    block to the list of blocks that contain an extended attribute.
    If the block is already on the list, no need to add it again.
    This can sometimes happen in duplicate reference situations and
    other obscure code paths.
    
    Since pass1 processes the file system sequentially by block number
    it's enough to check against the block most recently added to the
    list.  This is a performance increase; early versions of this
    code ran the entire linked list of special blocks.  If the file
    system was labelled for selinux, it could have millions of entries
    on the linked list, causing an enormous slowdown.
    
    rhbz#455300

diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 3ae0cc6..f7c81ff 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -509,6 +509,8 @@ static int finish_eattr_indir(struct gfs2_inode *ip, int leaf_pointers,
 			      int leaf_pointer_errors, void *private)
 {
 	struct block_count *bc = (struct block_count *) private;
+	osi_list_t *head;
+	struct special_blocks *b = NULL;
 
 	if (leaf_pointer_errors == leaf_pointers) /* All eas were bad */
 		return ask_remove_inode_eattr(ip, bc);
@@ -517,8 +519,17 @@ static int finish_eattr_indir(struct gfs2_inode *ip, int leaf_pointers,
 		   (unsigned long long)ip->i_di.di_num.no_addr,
 		   (unsigned long long)ip->i_di.di_num.no_addr);
 	/* Mark the inode as having an eattr in the block map
-	   so pass1c can check it. */
-	gfs2_special_add(&ip->i_sbd->eattr_blocks, ip->i_di.di_num.no_addr);
+	   so pass1c can check it. We may have previously added this inode
+	   to the eattr_blocks list and if we did, it would be the first
+	   one on the list.  So check that one only (to save time) and
+	   if that one matches, no need to add it again. */
+	if (!osi_list_empty(&ip->i_sbd->eattr_blocks.list)) {
+		head = &ip->i_sbd->eattr_blocks.list;
+		b = osi_list_entry(head->next, struct special_blocks, list);
+	}
+	if (!b || b->block != ip->i_di.di_num.no_addr)
+		gfs2_special_add(&ip->i_sbd->eattr_blocks,
+				 ip->i_di.di_num.no_addr);
 	if (!leaf_pointer_errors)
 		return 0;
 	log_err( _("Inode %lld (0x%llx) has recoverable indirect "
@@ -639,6 +650,8 @@ static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
 			    void *private)
 {
 	struct gfs2_sbd *sdp = ip->i_sbd;
+	osi_list_t *head;
+	struct special_blocks *b = NULL;
 
 	/* This inode contains an eattr - it may be invalid, but the
 	 * eattr attributes points to a non-zero block.
@@ -649,8 +662,13 @@ static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
 		     "block(s) attached.\n"),
 		   (unsigned long long)ip->i_di.di_num.no_addr,
 		   (unsigned long long)ip->i_di.di_num.no_addr);
-	gfs2_special_add(&sdp->eattr_blocks, ip->i_di.di_num.no_addr);
-	if(gfs2_check_range(sdp, block)) {
+	if (!osi_list_empty(&ip->i_sbd->eattr_blocks.list)) {
+		head = &ip->i_sbd->eattr_blocks.list;
+		b = osi_list_entry(head->next, struct special_blocks, list);
+	}
+	if (!b || b->block != ip->i_di.di_num.no_addr)
+		gfs2_special_add(&sdp->eattr_blocks, ip->i_di.di_num.no_addr);
+	if (gfs2_check_range(sdp, block)) {
 		log_warn( _("Inode #%llu (0x%llx): Extended Attribute leaf "
 			    "block #%llu (0x%llx) is out of range.\n"),
 			 (unsigned long long)ip->i_di.di_num.no_addr,