From c52ca18118b6e74af9a4f62a22a710c86a4003a9 Mon Sep 17 00:00:00 2001 From: deshmukh Date: Wed, 9 Dec 2009 09:17:48 +0000 Subject: [PATCH] b=21224 i=johann i=yong.fan Ported the quotacheck improvement patch to HEAD. --- lustre/lvfs/fsfilt_ext3.c | 109 +++++++++++++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 39 deletions(-) diff --git a/lustre/lvfs/fsfilt_ext3.c b/lustre/lvfs/fsfilt_ext3.c index 0444593..56728f1b 100644 --- a/lustre/lvfs/fsfilt_ext3.c +++ b/lustre/lvfs/fsfilt_ext3.c @@ -134,6 +134,18 @@ struct fsfilt_cb_data { #define ext3_inode_bitmap(sb,desc) le32_to_cpu((desc)->bg_inode_bitmap) #endif +#ifndef ext3_find_next_bit +#define ext3_find_next_bit ext2_find_next_bit +#endif + +#ifndef ext2_find_next_bit +#ifdef __LITTLE_ENDIAN +#define ext2_find_next_bit(addr, size, off) find_next_bit((unsigned long *)(addr), (size), (off)) +#else +error "Need implementation of find_next_bit on big-endian systems" +#endif /* __LITTLE_ENDIAN */ +#endif /* !ext2_find_next_le_bit */ + static char *fsfilt_ext3_get_label(struct super_block *sb) { return EXT3_SB(sb)->s_es->s_volume_name; @@ -1690,8 +1702,9 @@ static inline int read_old_dqinfo(struct super_block *sb, int type, RETURN(rc); } +#ifndef HAVE_EXT4_LDISKFS static inline struct ext3_group_desc * -get_group_desc(struct super_block *sb, int group) +get_group_desc(struct super_block *sb, int group, struct buffer_head **bh) { unsigned long desc_block, desc; struct ext3_group_desc *gdp; @@ -1704,38 +1717,24 @@ get_group_desc(struct super_block *sb, int group) return gdp + desc; } - -#ifndef HAVE_EXT4_LDISKFS static inline struct buffer_head * ext3_read_inode_bitmap(struct super_block *sb, unsigned long group) { struct ext3_group_desc *desc; struct buffer_head *bh; - desc = get_group_desc(sb, group); + desc = get_group_desc(sb, group, NULL); bh = sb_bread(sb, ext3_inode_bitmap(sb, desc)); return bh; } -#endif -static inline struct inode *ext3_iget_inuse(struct super_block *sb, - struct buffer_head *bitmap_bh, - int index, unsigned long ino) -{ - struct inode *inode = NULL; - - - if (ext3_test_bit(index, bitmap_bh->b_data)) -#ifdef HAVE_EXT4_LDISKFS - inode = ext4_iget(sb, ino); - if (IS_ERR(inode)) - /* Newer kernels return an error instead of a NULL pointer */ - inode = NULL; +static __u32 ext3_itable_unused_count(struct super_block *sb, + struct ext3_group_desc *bg) { + return le16_to_cpu(bg->bg_itable_unused); +} #else - inode = iget(sb, ino); +#define get_group_desc ext3_get_group_desc #endif - return inode; -} struct qchk_ctxt { struct hlist_head qckt_hash[NR_DQHASH]; /* quotacheck hash */ @@ -1941,14 +1940,18 @@ static int prune_chkquots(struct super_block *sb, return error; } +#ifndef EXT3_FEATURE_RO_COMPAT_GDT_CSUM +#define EXT3_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 +#endif + static int fsfilt_ext3_quotacheck(struct super_block *sb, struct obd_quotactl *oqc) { struct ext3_sb_info *sbi = EXT3_SB(sb); - int i, group; + int i, group, uninit_feat = 0; struct qchk_ctxt *qctxt; struct buffer_head *bitmap_bh = NULL; - unsigned long ino; + unsigned long ino, inode_inuse; struct inode *inode; int rc = 0; ENTRY; @@ -1979,34 +1982,63 @@ static int fsfilt_ext3_quotacheck(struct super_block *sb, GOTO(out, rc); } } + if (EXT3_HAS_RO_COMPAT_FEATURE(sb, EXT3_FEATURE_RO_COMPAT_GDT_CSUM)) + /* This filesystem supports the uninit group feature */ + uninit_feat = 1; - /* check quota and update in hash */ - for (group = 0; group < sbi->s_groups_count; group++) { - struct ext3_group_desc *desc; - desc = get_group_desc(sb, group); - if (!desc) - GOTO(out, -EIO); + /* number of inodes that have been allocated */ + inode_inuse = sbi->s_inodes_per_group * sbi->s_groups_count - + percpu_counter_sum(&sbi->s_freeinodes_counter); - spin_lock(sb_bgl_lock(sbi, group)); - if (desc->bg_flags & cpu_to_le16(EXT3_BG_INODE_UNINIT)) { - /* no inode in use in this group, just skip it */ + /* check quota and update in hash */ + for (group = 0; group < sbi->s_groups_count && inode_inuse > 0; + group++) { + unsigned long used_count = sbi->s_inodes_per_group; + + if (uninit_feat) { + struct ext3_group_desc *desc; + desc = get_group_desc(sb, group, NULL); + if (!desc) + GOTO(out, -EIO); + + /* we don't really need to take the group lock here, + * but it may be useful if one day we support online + * quotacheck */ + spin_lock(sb_bgl_lock(sbi, group)); + if (desc->bg_flags & cpu_to_le16(EXT3_BG_INODE_UNINIT)) { + /* no inode in use in this group, just skip it */ + spin_unlock(sb_bgl_lock(sbi, group)); + continue; + } + used_count -= ext3_itable_unused_count(sb, desc); spin_unlock(sb_bgl_lock(sbi, group)); - continue; } - spin_unlock(sb_bgl_lock(sbi, group)); ino = group * sbi->s_inodes_per_group + 1; bitmap_bh = ext3_read_inode_bitmap(sb, group); if (!bitmap_bh) { - CERROR("ext3_read_inode_bitmap group %d failed", group); - GOTO(out, rc = -EIO); + CERROR("%s: ext3_read_inode_bitmap group %d failed\n", + sb->s_id, group); + GOTO(out, -EIO); } - for (i = 0; i < sbi->s_inodes_per_group; i++, ino++) { + i = 0; + while (i < used_count && + (i = ext3_find_next_bit(bitmap_bh->b_data, + used_count, i)) < used_count) { + inode_inuse--; + i++; + ino = i + group * sbi->s_inodes_per_group; if (ino < sbi->s_first_ino) continue; +#if defined(HAVE_EXT4_LDISKFS) || !defined(HAVE_READ_INODE_IN_SBOPS) + inode = ext3_iget(sb, ino); +#else + inode = iget(sb, ino); +#endif + if (!inode || IS_ERR(inode)) + continue; - inode = ext3_iget_inuse(sb, bitmap_bh, i, ino); rc = add_inode_quota(inode, qctxt, oqc); iput(inode); if (rc) { @@ -2014,7 +2046,6 @@ static int fsfilt_ext3_quotacheck(struct super_block *sb, GOTO(out, rc); } } - brelse(bitmap_bh); } -- 1.8.3.1