Commit fd2d4291 authored by Avantika Mathur's avatar Avantika Mathur Committed by Theodore Ts'o

ext4: add ext4_group_t, and change all group variables to this type.

In many places variables for block group are of type int, which limits the
maximum number of block groups to 2^31.  Each block group can have up to
2^15 blocks, with a 4K block size,  and the max filesystem size is limited to
2^31 * (2^15 * 2^12) = 2^58  -- or 256 PB

This patch introduces a new type ext4_group_t, of type unsigned long, to
represent block group numbers in ext4.
All occurrences of block group variables are converted to type ext4_group_t.
Signed-off-by: default avatarAvantika Mathur <mathur@us.ibm.com>
parent bba90743
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
* Calculate the block group number and offset, given a block number * Calculate the block group number and offset, given a block number
*/ */
void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr, void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
unsigned long *blockgrpp, ext4_grpblk_t *offsetp) ext4_group_t *blockgrpp, ext4_grpblk_t *offsetp)
{ {
struct ext4_super_block *es = EXT4_SB(sb)->s_es; struct ext4_super_block *es = EXT4_SB(sb)->s_es;
ext4_grpblk_t offset; ext4_grpblk_t offset;
...@@ -46,7 +46,7 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr, ...@@ -46,7 +46,7 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
/* Initializes an uninitialized block bitmap if given, and returns the /* Initializes an uninitialized block bitmap if given, and returns the
* number of blocks free in the group. */ * number of blocks free in the group. */
unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
int block_group, struct ext4_group_desc *gdp) ext4_group_t block_group, struct ext4_group_desc *gdp)
{ {
unsigned long start; unsigned long start;
int bit, bit_max; int bit, bit_max;
...@@ -60,7 +60,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, ...@@ -60,7 +60,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
* essentially implementing a per-group read-only flag. */ * essentially implementing a per-group read-only flag. */
if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) { if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
ext4_error(sb, __FUNCTION__, ext4_error(sb, __FUNCTION__,
"Checksum bad for group %u\n", block_group); "Checksum bad for group %lu\n", block_group);
gdp->bg_free_blocks_count = 0; gdp->bg_free_blocks_count = 0;
gdp->bg_free_inodes_count = 0; gdp->bg_free_inodes_count = 0;
gdp->bg_itable_unused = 0; gdp->bg_itable_unused = 0;
...@@ -153,7 +153,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, ...@@ -153,7 +153,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
* group descriptor * group descriptor
*/ */
struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb, struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
unsigned int block_group, ext4_group_t block_group,
struct buffer_head ** bh) struct buffer_head ** bh)
{ {
unsigned long group_desc; unsigned long group_desc;
...@@ -164,7 +164,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb, ...@@ -164,7 +164,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
if (block_group >= sbi->s_groups_count) { if (block_group >= sbi->s_groups_count) {
ext4_error (sb, "ext4_get_group_desc", ext4_error (sb, "ext4_get_group_desc",
"block_group >= groups_count - " "block_group >= groups_count - "
"block_group = %d, groups_count = %lu", "block_group = %lu, groups_count = %lu",
block_group, sbi->s_groups_count); block_group, sbi->s_groups_count);
return NULL; return NULL;
...@@ -176,7 +176,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb, ...@@ -176,7 +176,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
if (!sbi->s_group_desc[group_desc]) { if (!sbi->s_group_desc[group_desc]) {
ext4_error (sb, "ext4_get_group_desc", ext4_error (sb, "ext4_get_group_desc",
"Group descriptor not loaded - " "Group descriptor not loaded - "
"block_group = %d, group_desc = %lu, desc = %lu", "block_group = %lu, group_desc = %lu, desc = %lu",
block_group, group_desc, offset); block_group, group_desc, offset);
return NULL; return NULL;
} }
...@@ -200,7 +200,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb, ...@@ -200,7 +200,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
* Return buffer_head on success or NULL in case of failure. * Return buffer_head on success or NULL in case of failure.
*/ */
struct buffer_head * struct buffer_head *
read_block_bitmap(struct super_block *sb, unsigned int block_group) read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
{ {
struct ext4_group_desc * desc; struct ext4_group_desc * desc;
struct buffer_head * bh = NULL; struct buffer_head * bh = NULL;
...@@ -227,7 +227,7 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group) ...@@ -227,7 +227,7 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
if (!bh) if (!bh)
ext4_error (sb, __FUNCTION__, ext4_error (sb, __FUNCTION__,
"Cannot read block bitmap - " "Cannot read block bitmap - "
"block_group = %d, block_bitmap = %llu", "block_group = %lu, block_bitmap = %llu",
block_group, bitmap_blk); block_group, bitmap_blk);
return bh; return bh;
} }
...@@ -320,7 +320,7 @@ static void __rsv_window_dump(struct rb_root *root, int verbose, ...@@ -320,7 +320,7 @@ static void __rsv_window_dump(struct rb_root *root, int verbose,
*/ */
static int static int
goal_in_my_reservation(struct ext4_reserve_window *rsv, ext4_grpblk_t grp_goal, goal_in_my_reservation(struct ext4_reserve_window *rsv, ext4_grpblk_t grp_goal,
unsigned int group, struct super_block * sb) ext4_group_t group, struct super_block *sb)
{ {
ext4_fsblk_t group_first_block, group_last_block; ext4_fsblk_t group_first_block, group_last_block;
...@@ -540,7 +540,7 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb, ...@@ -540,7 +540,7 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
{ {
struct buffer_head *bitmap_bh = NULL; struct buffer_head *bitmap_bh = NULL;
struct buffer_head *gd_bh; struct buffer_head *gd_bh;
unsigned long block_group; ext4_group_t block_group;
ext4_grpblk_t bit; ext4_grpblk_t bit;
unsigned long i; unsigned long i;
unsigned long overflow; unsigned long overflow;
...@@ -920,9 +920,10 @@ claim_block(spinlock_t *lock, ext4_grpblk_t block, struct buffer_head *bh) ...@@ -920,9 +920,10 @@ claim_block(spinlock_t *lock, ext4_grpblk_t block, struct buffer_head *bh)
* ext4_journal_release_buffer(), else we'll run out of credits. * ext4_journal_release_buffer(), else we'll run out of credits.
*/ */
static ext4_grpblk_t static ext4_grpblk_t
ext4_try_to_allocate(struct super_block *sb, handle_t *handle, int group, ext4_try_to_allocate(struct super_block *sb, handle_t *handle,
struct buffer_head *bitmap_bh, ext4_grpblk_t grp_goal, ext4_group_t group, struct buffer_head *bitmap_bh,
unsigned long *count, struct ext4_reserve_window *my_rsv) ext4_grpblk_t grp_goal, unsigned long *count,
struct ext4_reserve_window *my_rsv)
{ {
ext4_fsblk_t group_first_block; ext4_fsblk_t group_first_block;
ext4_grpblk_t start, end; ext4_grpblk_t start, end;
...@@ -1156,7 +1157,7 @@ static int find_next_reservable_window( ...@@ -1156,7 +1157,7 @@ static int find_next_reservable_window(
*/ */
static int alloc_new_reservation(struct ext4_reserve_window_node *my_rsv, static int alloc_new_reservation(struct ext4_reserve_window_node *my_rsv,
ext4_grpblk_t grp_goal, struct super_block *sb, ext4_grpblk_t grp_goal, struct super_block *sb,
unsigned int group, struct buffer_head *bitmap_bh) ext4_group_t group, struct buffer_head *bitmap_bh)
{ {
struct ext4_reserve_window_node *search_head; struct ext4_reserve_window_node *search_head;
ext4_fsblk_t group_first_block, group_end_block, start_block; ext4_fsblk_t group_first_block, group_end_block, start_block;
...@@ -1354,7 +1355,7 @@ static void try_to_extend_reservation(struct ext4_reserve_window_node *my_rsv, ...@@ -1354,7 +1355,7 @@ static void try_to_extend_reservation(struct ext4_reserve_window_node *my_rsv,
*/ */
static ext4_grpblk_t static ext4_grpblk_t
ext4_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, ext4_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
unsigned int group, struct buffer_head *bitmap_bh, ext4_group_t group, struct buffer_head *bitmap_bh,
ext4_grpblk_t grp_goal, ext4_grpblk_t grp_goal,
struct ext4_reserve_window_node * my_rsv, struct ext4_reserve_window_node * my_rsv,
unsigned long *count, int *errp) unsigned long *count, int *errp)
...@@ -1528,12 +1529,12 @@ ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode, ...@@ -1528,12 +1529,12 @@ ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
{ {
struct buffer_head *bitmap_bh = NULL; struct buffer_head *bitmap_bh = NULL;
struct buffer_head *gdp_bh; struct buffer_head *gdp_bh;
unsigned long group_no; ext4_group_t group_no;
int goal_group; ext4_group_t goal_group;
ext4_grpblk_t grp_target_blk; /* blockgroup relative goal block */ ext4_grpblk_t grp_target_blk; /* blockgroup relative goal block */
ext4_grpblk_t grp_alloc_blk; /* blockgroup-relative allocated block*/ ext4_grpblk_t grp_alloc_blk; /* blockgroup-relative allocated block*/
ext4_fsblk_t ret_block; /* filesyetem-wide allocated block */ ext4_fsblk_t ret_block; /* filesyetem-wide allocated block */
int bgi; /* blockgroup iteration index */ ext4_group_t bgi; /* blockgroup iteration index */
int fatal = 0, err; int fatal = 0, err;
int performed_allocation = 0; int performed_allocation = 0;
ext4_grpblk_t free_blocks; /* number of free blocks in a group */ ext4_grpblk_t free_blocks; /* number of free blocks in a group */
...@@ -1544,10 +1545,7 @@ ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode, ...@@ -1544,10 +1545,7 @@ ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
struct ext4_reserve_window_node *my_rsv = NULL; struct ext4_reserve_window_node *my_rsv = NULL;
struct ext4_block_alloc_info *block_i; struct ext4_block_alloc_info *block_i;
unsigned short windowsz = 0; unsigned short windowsz = 0;
#ifdef EXT4FS_DEBUG ext4_group_t ngroups;
static int goal_hits, goal_attempts;
#endif
unsigned long ngroups;
unsigned long num = *count; unsigned long num = *count;
*errp = -ENOSPC; *errp = -ENOSPC;
...@@ -1743,9 +1741,6 @@ ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode, ...@@ -1743,9 +1741,6 @@ ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
* list of some description. We don't know in advance whether * list of some description. We don't know in advance whether
* the caller wants to use it as metadata or data. * the caller wants to use it as metadata or data.
*/ */
ext4_debug("allocating block %lu. Goal hits %d of %d.\n",
ret_block, goal_hits, goal_attempts);
spin_lock(sb_bgl_lock(sbi, group_no)); spin_lock(sb_bgl_lock(sbi, group_no));
if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))
gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
...@@ -1804,8 +1799,8 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb) ...@@ -1804,8 +1799,8 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
{ {
ext4_fsblk_t desc_count; ext4_fsblk_t desc_count;
struct ext4_group_desc *gdp; struct ext4_group_desc *gdp;
int i; ext4_group_t i;
unsigned long ngroups = EXT4_SB(sb)->s_groups_count; ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
#ifdef EXT4FS_DEBUG #ifdef EXT4FS_DEBUG
struct ext4_super_block *es; struct ext4_super_block *es;
ext4_fsblk_t bitmap_count; ext4_fsblk_t bitmap_count;
...@@ -1829,7 +1824,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb) ...@@ -1829,7 +1824,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
continue; continue;
x = ext4_count_free(bitmap_bh, sb->s_blocksize); x = ext4_count_free(bitmap_bh, sb->s_blocksize);
printk("group %d: stored = %d, counted = %lu\n", printk(KERN_DEBUG "group %lu: stored = %d, counted = %lu\n",
i, le16_to_cpu(gdp->bg_free_blocks_count), x); i, le16_to_cpu(gdp->bg_free_blocks_count), x);
bitmap_count += x; bitmap_count += x;
} }
...@@ -1853,7 +1848,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb) ...@@ -1853,7 +1848,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
#endif #endif
} }
static inline int test_root(int a, int b) static inline int test_root(ext4_group_t a, int b)
{ {
int num = b; int num = b;
...@@ -1862,7 +1857,7 @@ static inline int test_root(int a, int b) ...@@ -1862,7 +1857,7 @@ static inline int test_root(int a, int b)
return num == a; return num == a;
} }
static int ext4_group_sparse(int group) static int ext4_group_sparse(ext4_group_t group)
{ {
if (group <= 1) if (group <= 1)
return 1; return 1;
...@@ -1880,7 +1875,7 @@ static int ext4_group_sparse(int group) ...@@ -1880,7 +1875,7 @@ static int ext4_group_sparse(int group)
* Return the number of blocks used by the superblock (primary or backup) * Return the number of blocks used by the superblock (primary or backup)
* in this group. Currently this will be only 0 or 1. * in this group. Currently this will be only 0 or 1.
*/ */
int ext4_bg_has_super(struct super_block *sb, int group) int ext4_bg_has_super(struct super_block *sb, ext4_group_t group)
{ {
if (EXT4_HAS_RO_COMPAT_FEATURE(sb, if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) && EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
...@@ -1889,18 +1884,20 @@ int ext4_bg_has_super(struct super_block *sb, int group) ...@@ -1889,18 +1884,20 @@ int ext4_bg_has_super(struct super_block *sb, int group)
return 1; return 1;
} }
static unsigned long ext4_bg_num_gdb_meta(struct super_block *sb, int group) static unsigned long ext4_bg_num_gdb_meta(struct super_block *sb,
ext4_group_t group)
{ {
unsigned long metagroup = group / EXT4_DESC_PER_BLOCK(sb); unsigned long metagroup = group / EXT4_DESC_PER_BLOCK(sb);
unsigned long first = metagroup * EXT4_DESC_PER_BLOCK(sb); ext4_group_t first = metagroup * EXT4_DESC_PER_BLOCK(sb);
unsigned long last = first + EXT4_DESC_PER_BLOCK(sb) - 1; ext4_group_t last = first + EXT4_DESC_PER_BLOCK(sb) - 1;
if (group == first || group == first + 1 || group == last) if (group == first || group == first + 1 || group == last)
return 1; return 1;
return 0; return 0;
} }
static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb, int group) static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb,
ext4_group_t group)
{ {
if (EXT4_HAS_RO_COMPAT_FEATURE(sb, if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) && EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
...@@ -1918,7 +1915,7 @@ static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb, int group) ...@@ -1918,7 +1915,7 @@ static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb, int group)
* (primary or backup) in this group. In the future there may be a * (primary or backup) in this group. In the future there may be a
* different number of descriptor blocks in each group. * different number of descriptor blocks in each group.
*/ */
unsigned long ext4_bg_num_gdb(struct super_block *sb, int group) unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group)
{ {
unsigned long first_meta_bg = unsigned long first_meta_bg =
le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg); le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg);
......
...@@ -14,14 +14,16 @@ extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group, ...@@ -14,14 +14,16 @@ extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group,
extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group, extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group,
struct ext4_group_desc *gdp); struct ext4_group_desc *gdp);
struct buffer_head *read_block_bitmap(struct super_block *sb, struct buffer_head *read_block_bitmap(struct super_block *sb,
unsigned int block_group); ext4_group_t block_group);
extern unsigned ext4_init_block_bitmap(struct super_block *sb, extern unsigned ext4_init_block_bitmap(struct super_block *sb,
struct buffer_head *bh, int group, struct buffer_head *bh,
ext4_group_t group,
struct ext4_group_desc *desc); struct ext4_group_desc *desc);
#define ext4_free_blocks_after_init(sb, group, desc) \ #define ext4_free_blocks_after_init(sb, group, desc) \
ext4_init_block_bitmap(sb, NULL, group, desc) ext4_init_block_bitmap(sb, NULL, group, desc)
extern unsigned ext4_init_inode_bitmap(struct super_block *sb, extern unsigned ext4_init_inode_bitmap(struct super_block *sb,
struct buffer_head *bh, int group, struct buffer_head *bh,
ext4_group_t group,
struct ext4_group_desc *desc); struct ext4_group_desc *desc);
extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap); extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap);
#endif /* _LINUX_EXT4_GROUP_H */ #endif /* _LINUX_EXT4_GROUP_H */
...@@ -64,8 +64,8 @@ void mark_bitmap_end(int start_bit, int end_bit, char *bitmap) ...@@ -64,8 +64,8 @@ void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
} }
/* Initializes an uninitialized inode bitmap */ /* Initializes an uninitialized inode bitmap */
unsigned ext4_init_inode_bitmap(struct super_block *sb, unsigned ext4_init_inode_bitmap(struct super_block *sb, struct buffer_head *bh,
struct buffer_head *bh, int block_group, ext4_group_t block_group,
struct ext4_group_desc *gdp) struct ext4_group_desc *gdp)
{ {
struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_sb_info *sbi = EXT4_SB(sb);
...@@ -75,7 +75,7 @@ unsigned ext4_init_inode_bitmap(struct super_block *sb, ...@@ -75,7 +75,7 @@ unsigned ext4_init_inode_bitmap(struct super_block *sb,
/* If checksum is bad mark all blocks and inodes use to prevent /* If checksum is bad mark all blocks and inodes use to prevent
* allocation, essentially implementing a per-group read-only flag. */ * allocation, essentially implementing a per-group read-only flag. */
if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) { if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
ext4_error(sb, __FUNCTION__, "Checksum bad for group %u\n", ext4_error(sb, __FUNCTION__, "Checksum bad for group %lu\n",
block_group); block_group);
gdp->bg_free_blocks_count = 0; gdp->bg_free_blocks_count = 0;
gdp->bg_free_inodes_count = 0; gdp->bg_free_inodes_count = 0;
...@@ -98,7 +98,7 @@ unsigned ext4_init_inode_bitmap(struct super_block *sb, ...@@ -98,7 +98,7 @@ unsigned ext4_init_inode_bitmap(struct super_block *sb,
* Return buffer_head of bitmap on success or NULL. * Return buffer_head of bitmap on success or NULL.
*/ */
static struct buffer_head * static struct buffer_head *
read_inode_bitmap(struct super_block * sb, unsigned long block_group) read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
{ {
struct ext4_group_desc *desc; struct ext4_group_desc *desc;
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
...@@ -152,7 +152,7 @@ void ext4_free_inode (handle_t *handle, struct inode * inode) ...@@ -152,7 +152,7 @@ void ext4_free_inode (handle_t *handle, struct inode * inode)
unsigned long ino; unsigned long ino;
struct buffer_head *bitmap_bh = NULL; struct buffer_head *bitmap_bh = NULL;
struct buffer_head *bh2; struct buffer_head *bh2;
unsigned long block_group; ext4_group_t block_group;
unsigned long bit; unsigned long bit;
struct ext4_group_desc * gdp; struct ext4_group_desc * gdp;
struct ext4_super_block * es; struct ext4_super_block * es;
...@@ -260,12 +260,12 @@ void ext4_free_inode (handle_t *handle, struct inode * inode) ...@@ -260,12 +260,12 @@ void ext4_free_inode (handle_t *handle, struct inode * inode)
* For other inodes, search forward from the parent directory\'s block * For other inodes, search forward from the parent directory\'s block
* group to find a free inode. * group to find a free inode.
*/ */
static int find_group_dir(struct super_block *sb, struct inode *parent) static ext4_group_t find_group_dir(struct super_block *sb, struct inode *parent)
{ {
int ngroups = EXT4_SB(sb)->s_groups_count; ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
unsigned int freei, avefreei; unsigned int freei, avefreei;
struct ext4_group_desc *desc, *best_desc = NULL; struct ext4_group_desc *desc, *best_desc = NULL;
int group, best_group = -1; ext4_group_t group, best_group = -1;
freei = percpu_counter_read_positive(&EXT4_SB(sb)->s_freeinodes_counter); freei = percpu_counter_read_positive(&EXT4_SB(sb)->s_freeinodes_counter);
avefreei = freei / ngroups; avefreei = freei / ngroups;
...@@ -314,12 +314,13 @@ static int find_group_dir(struct super_block *sb, struct inode *parent) ...@@ -314,12 +314,13 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
#define INODE_COST 64 #define INODE_COST 64
#define BLOCK_COST 256 #define BLOCK_COST 256
static int find_group_orlov(struct super_block *sb, struct inode *parent) static ext4_group_t find_group_orlov(struct super_block *sb,
struct inode *parent)
{ {
int parent_group = EXT4_I(parent)->i_block_group; ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_super_block *es = sbi->s_es; struct ext4_super_block *es = sbi->s_es;
int ngroups = sbi->s_groups_count; ext4_group_t ngroups = sbi->s_groups_count;
int inodes_per_group = EXT4_INODES_PER_GROUP(sb); int inodes_per_group = EXT4_INODES_PER_GROUP(sb);
unsigned int freei, avefreei; unsigned int freei, avefreei;
ext4_fsblk_t freeb, avefreeb; ext4_fsblk_t freeb, avefreeb;
...@@ -327,7 +328,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) ...@@ -327,7 +328,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
unsigned int ndirs; unsigned int ndirs;
int max_debt, max_dirs, min_inodes; int max_debt, max_dirs, min_inodes;
ext4_grpblk_t min_blocks; ext4_grpblk_t min_blocks;
int group = -1, i; ext4_group_t group = -1, i;
struct ext4_group_desc *desc; struct ext4_group_desc *desc;
freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter); freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter);
...@@ -340,7 +341,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) ...@@ -340,7 +341,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
if ((parent == sb->s_root->d_inode) || if ((parent == sb->s_root->d_inode) ||
(EXT4_I(parent)->i_flags & EXT4_TOPDIR_FL)) { (EXT4_I(parent)->i_flags & EXT4_TOPDIR_FL)) {
int best_ndir = inodes_per_group; int best_ndir = inodes_per_group;
int best_group = -1; ext4_group_t best_group = -1;
get_random_bytes(&group, sizeof(group)); get_random_bytes(&group, sizeof(group));
parent_group = (unsigned)group % ngroups; parent_group = (unsigned)group % ngroups;
...@@ -415,12 +416,13 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) ...@@ -415,12 +416,13 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
return -1; return -1;
} }
static int find_group_other(struct super_block *sb, struct inode *parent) static ext4_group_t find_group_other(struct super_block *sb,
struct inode *parent)
{ {
int parent_group = EXT4_I(parent)->i_block_group; ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
int ngroups = EXT4_SB(sb)->s_groups_count; ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
struct ext4_group_desc *desc; struct ext4_group_desc *desc;
int group, i; ext4_group_t group, i;
/* /*
* Try to place the inode in its parent directory * Try to place the inode in its parent directory
...@@ -487,7 +489,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode) ...@@ -487,7 +489,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode)
struct super_block *sb; struct super_block *sb;
struct buffer_head *bitmap_bh = NULL; struct buffer_head *bitmap_bh = NULL;
struct buffer_head *bh2; struct buffer_head *bh2;
int group; ext4_group_t group;
unsigned long ino = 0; unsigned long ino = 0;
struct inode * inode; struct inode * inode;
struct ext4_group_desc * gdp = NULL; struct ext4_group_desc * gdp = NULL;
...@@ -583,7 +585,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode) ...@@ -583,7 +585,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode)
ino > EXT4_INODES_PER_GROUP(sb)) { ino > EXT4_INODES_PER_GROUP(sb)) {
ext4_error(sb, __FUNCTION__, ext4_error(sb, __FUNCTION__,
"reserved inode or inode > inodes count - " "reserved inode or inode > inodes count - "
"block_group = %d, inode=%lu", group, "block_group = %lu, inode=%lu", group,
ino + group * EXT4_INODES_PER_GROUP(sb)); ino + group * EXT4_INODES_PER_GROUP(sb));
err = -EIO; err = -EIO;
goto fail; goto fail;
...@@ -777,7 +779,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode) ...@@ -777,7 +779,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode)
struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino) struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
{ {
unsigned long max_ino = le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count); unsigned long max_ino = le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count);
unsigned long block_group; ext4_group_t block_group;
int bit; int bit;
struct buffer_head *bitmap_bh = NULL; struct buffer_head *bitmap_bh = NULL;
struct inode *inode = NULL; struct inode *inode = NULL;
...@@ -833,7 +835,7 @@ unsigned long ext4_count_free_inodes (struct super_block * sb) ...@@ -833,7 +835,7 @@ unsigned long ext4_count_free_inodes (struct super_block * sb)
{ {
unsigned long desc_count; unsigned long desc_count;
struct ext4_group_desc *gdp; struct ext4_group_desc *gdp;
int i; ext4_group_t i;
#ifdef EXT4FS_DEBUG #ifdef EXT4FS_DEBUG
struct ext4_super_block *es; struct ext4_super_block *es;
unsigned long bitmap_count, x; unsigned long bitmap_count, x;
...@@ -879,7 +881,7 @@ unsigned long ext4_count_free_inodes (struct super_block * sb) ...@@ -879,7 +881,7 @@ unsigned long ext4_count_free_inodes (struct super_block * sb)
unsigned long ext4_count_dirs (struct super_block * sb) unsigned long ext4_count_dirs (struct super_block * sb)
{ {
unsigned long count = 0; unsigned long count = 0;
int i; ext4_group_t i;
for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) { for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
struct ext4_group_desc *gdp = ext4_get_group_desc (sb, i, NULL); struct ext4_group_desc *gdp = ext4_get_group_desc (sb, i, NULL);
......
...@@ -2464,7 +2464,8 @@ void ext4_truncate(struct inode *inode) ...@@ -2464,7 +2464,8 @@ void ext4_truncate(struct inode *inode)
static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb, static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb,
unsigned long ino, struct ext4_iloc *iloc) unsigned long ino, struct ext4_iloc *iloc)
{ {
unsigned long desc, group_desc, block_group; unsigned long desc, group_desc;
ext4_group_t block_group;
unsigned long offset; unsigned long offset;
ext4_fsblk_t block; ext4_fsblk_t block;
struct buffer_head *bh; struct buffer_head *bh;
...@@ -2551,7 +2552,7 @@ static int __ext4_get_inode_loc(struct inode *inode, ...@@ -2551,7 +2552,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
struct ext4_group_desc *desc; struct ext4_group_desc *desc;
int inodes_per_buffer; int inodes_per_buffer;
int inode_offset, i; int inode_offset, i;
int block_group; ext4_group_t block_group;
int start; int start;
block_group = (inode->i_ino - 1) / block_group = (inode->i_ino - 1) /
......
...@@ -28,7 +28,7 @@ static int verify_group_input(struct super_block *sb, ...@@ -28,7 +28,7 @@ static int verify_group_input(struct super_block *sb,
struct ext4_super_block *es = sbi->s_es; struct ext4_super_block *es = sbi->s_es;
ext4_fsblk_t start = ext4_blocks_count(es); ext4_fsblk_t start = ext4_blocks_count(es);
ext4_fsblk_t end = start + input->blocks_count; ext4_fsblk_t end = start + input->blocks_count;
unsigned group = input->group; ext4_group_t group = input->group;
ext4_fsblk_t itend = input->inode_table + sbi->s_itb_per_group; ext4_fsblk_t itend = input->inode_table + sbi->s_itb_per_group;
unsigned overhead = ext4_bg_has_super(sb, group) ? unsigned overhead = ext4_bg_has_super(sb, group) ?
(1 + ext4_bg_num_gdb(sb, group) + (1 + ext4_bg_num_gdb(sb, group) +
...@@ -357,7 +357,7 @@ static int verify_reserved_gdb(struct super_block *sb, ...@@ -357,7 +357,7 @@ static int verify_reserved_gdb(struct super_block *sb,
struct buffer_head *primary) struct buffer_head *primary)
{ {
const ext4_fsblk_t blk = primary->b_blocknr; const ext4_fsblk_t blk = primary->b_blocknr;
const unsigned long end = EXT4_SB(sb)->s_groups_count; const ext4_group_t end = EXT4_SB(sb)->s_groups_count;
unsigned three = 1; unsigned three = 1;
unsigned five = 5; unsigned five = 5;
unsigned seven = 7; unsigned seven = 7;
...@@ -656,12 +656,12 @@ static void update_backups(struct super_block *sb, ...@@ -656,12 +656,12 @@ static void update_backups(struct super_block *sb,
int blk_off, char *data, int size) int blk_off, char *data, int size)
{ {
struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_sb_info *sbi = EXT4_SB(sb);
const unsigned long last = sbi->s_groups_count; const ext4_group_t last = sbi->s_groups_count;
const int bpg = EXT4_BLOCKS_PER_GROUP(sb); const int bpg = EXT4_BLOCKS_PER_GROUP(sb);
unsigned three = 1; unsigned three = 1;
unsigned five = 5; unsigned five = 5;
unsigned seven = 7; unsigned seven = 7;
unsigned group; ext4_group_t group;
int rest = sb->s_blocksize - size; int rest = sb->s_blocksize - size;
handle_t *handle; handle_t *handle;
int err = 0, err2; int err = 0, err2;
...@@ -716,7 +716,7 @@ static void update_backups(struct super_block *sb, ...@@ -716,7 +716,7 @@ static void update_backups(struct super_block *sb,
exit_err: exit_err:
if (err) { if (err) {
ext4_warning(sb, __FUNCTION__, ext4_warning(sb, __FUNCTION__,
"can't update backup for group %d (err %d), " "can't update backup for group %lu (err %d), "
"forcing fsck on next reboot", group, err); "forcing fsck on next reboot", group, err);
sbi->s_mount_state &= ~EXT4_VALID_FS; sbi->s_mount_state &= ~EXT4_VALID_FS;
sbi->s_es->s_state &= cpu_to_le16(~EXT4_VALID_FS); sbi->s_es->s_state &= cpu_to_le16(~EXT4_VALID_FS);
...@@ -952,7 +952,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, ...@@ -952,7 +952,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
ext4_fsblk_t n_blocks_count) ext4_fsblk_t n_blocks_count)
{ {
ext4_fsblk_t o_blocks_count; ext4_fsblk_t o_blocks_count;
unsigned long o_groups_count; ext4_group_t o_groups_count;
ext4_grpblk_t last; ext4_grpblk_t last;
ext4_grpblk_t add; ext4_grpblk_t add;
struct buffer_head * bh; struct buffer_head * bh;
......
...@@ -1364,7 +1364,7 @@ static int ext4_check_descriptors (struct super_block * sb) ...@@ -1364,7 +1364,7 @@ static int ext4_check_descriptors (struct super_block * sb)
struct ext4_group_desc * gdp = NULL; struct ext4_group_desc * gdp = NULL;
int desc_block = 0; int desc_block = 0;
int flexbg_flag = 0; int flexbg_flag = 0;
int i; ext4_group_t i;
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
flexbg_flag = 1; flexbg_flag = 1;
...@@ -1386,7 +1386,7 @@ static int ext4_check_descriptors (struct super_block * sb) ...@@ -1386,7 +1386,7 @@ static int ext4_check_descriptors (struct super_block * sb)
if (block_bitmap < first_block || block_bitmap > last_block) if (block_bitmap < first_block || block_bitmap > last_block)
{ {
ext4_error (sb, "ext4_check_descriptors", ext4_error (sb, "ext4_check_descriptors",
"Block bitmap for group %d" "Block bitmap for group %lu"
" not in group (block %llu)!", " not in group (block %llu)!",
i, block_bitmap); i, block_bitmap);
return 0; return 0;
...@@ -1395,7 +1395,7 @@ static int ext4_check_descriptors (struct super_block * sb) ...@@ -1395,7 +1395,7 @@ static int ext4_check_descriptors (struct super_block * sb)
if (inode_bitmap < first_block || inode_bitmap > last_block) if (inode_bitmap < first_block || inode_bitmap > last_block)
{ {
ext4_error (sb, "ext4_check_descriptors", ext4_error (sb, "ext4_check_descriptors",
"Inode bitmap for group %d" "Inode bitmap for group %lu"
" not in group (block %llu)!", " not in group (block %llu)!",
i, inode_bitmap); i, inode_bitmap);
return 0; return 0;
...@@ -1405,17 +1405,16 @@ static int ext4_check_descriptors (struct super_block * sb) ...@@ -1405,17 +1405,16 @@ static int ext4_check_descriptors (struct super_block * sb)
inode_table + sbi->s_itb_per_group - 1 > last_block) inode_table + sbi->s_itb_per_group - 1 > last_block)
{ {
ext4_error (sb, "ext4_check_descriptors", ext4_error (sb, "ext4_check_descriptors",
"Inode table for group %d" "Inode table for group %lu"
" not in group (block %llu)!", " not in group (block %llu)!",
i, inode_table); i, inode_table);
return 0; return 0;
} }
if (!ext4_group_desc_csum_verify(sbi, i, gdp)) { if (!ext4_group_desc_csum_verify(sbi, i, gdp)) {
ext4_error(sb, __FUNCTION__, ext4_error(sb, __FUNCTION__,
"Checksum for group %d failed (%u!=%u)\n", i, "Checksum for group %lu failed (%u!=%u)\n",
le16_to_cpu(ext4_group_desc_csum(sbi, i, i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
gdp)), gdp)), le16_to_cpu(gdp->bg_checksum));
le16_to_cpu(gdp->bg_checksum));
return 0; return 0;
} }
if (!flexbg_flag) if (!flexbg_flag)
...@@ -1429,7 +1428,6 @@ static int ext4_check_descriptors (struct super_block * sb) ...@@ -1429,7 +1428,6 @@ static int ext4_check_descriptors (struct super_block * sb)
return 1; return 1;
} }
/* ext4_orphan_cleanup() walks a singly-linked list of inodes (starting at /* ext4_orphan_cleanup() walks a singly-linked list of inodes (starting at
* the superblock) which were deleted from all directories, but held open by * the superblock) which were deleted from all directories, but held open by
* a process at the time of a crash. We walk the list and try to delete these * a process at the time of a crash. We walk the list and try to delete these
...@@ -1570,7 +1568,7 @@ static ext4_fsblk_t descriptor_loc(struct super_block *sb, ...@@ -1570,7 +1568,7 @@ static ext4_fsblk_t descriptor_loc(struct super_block *sb,
ext4_fsblk_t logical_sb_block, int nr) ext4_fsblk_t logical_sb_block, int nr)
{ {
struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_sb_info *sbi = EXT4_SB(sb);
unsigned long bg, first_meta_bg; ext4_group_t bg, first_meta_bg;
int has_super = 0; int has_super = 0;
first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg); first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg);
...@@ -2678,7 +2676,7 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf) ...@@ -2678,7 +2676,7 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
if (test_opt(sb, MINIX_DF)) { if (test_opt(sb, MINIX_DF)) {
sbi->s_overhead_last = 0; sbi->s_overhead_last = 0;
} else if (sbi->s_blocks_last != ext4_blocks_count(es)) { } else if (sbi->s_blocks_last != ext4_blocks_count(es)) {
unsigned long ngroups = sbi->s_groups_count, i; ext4_group_t ngroups = sbi->s_groups_count, i;
ext4_fsblk_t overhead = 0; ext4_fsblk_t overhead = 0;
smp_rmb(); smp_rmb();
......
...@@ -830,7 +830,7 @@ struct ext4_iloc ...@@ -830,7 +830,7 @@ struct ext4_iloc
{ {
struct buffer_head *bh; struct buffer_head *bh;
unsigned long offset; unsigned long offset;
unsigned long block_group; ext4_group_t block_group;
}; };
static inline struct ext4_inode *ext4_raw_inode(struct ext4_iloc *iloc) static inline struct ext4_inode *ext4_raw_inode(struct ext4_iloc *iloc)
...@@ -855,7 +855,7 @@ struct dir_private_info { ...@@ -855,7 +855,7 @@ struct dir_private_info {
/* calculate the first block number of the group */ /* calculate the first block number of the group */
static inline ext4_fsblk_t static inline ext4_fsblk_t
ext4_group_first_block_no(struct super_block *sb, unsigned long group_no) ext4_group_first_block_no(struct super_block *sb, ext4_group_t group_no)
{ {
return group_no * (ext4_fsblk_t)EXT4_BLOCKS_PER_GROUP(sb) + return group_no * (ext4_fsblk_t)EXT4_BLOCKS_PER_GROUP(sb) +
le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
...@@ -886,8 +886,9 @@ extern unsigned int ext4_block_group(struct super_block *sb, ...@@ -886,8 +886,9 @@ extern unsigned int ext4_block_group(struct super_block *sb,
ext4_fsblk_t blocknr); ext4_fsblk_t blocknr);
extern ext4_grpblk_t ext4_block_group_offset(struct super_block *sb, extern ext4_grpblk_t ext4_block_group_offset(struct super_block *sb,
ext4_fsblk_t blocknr); ext4_fsblk_t blocknr);
extern int ext4_bg_has_super(struct super_block *sb, int group); extern int ext4_bg_has_super(struct super_block *sb, ext4_group_t group);
extern unsigned long ext4_bg_num_gdb(struct super_block *sb, int group); extern unsigned long ext4_bg_num_gdb(struct super_block *sb,
ext4_group_t group);
extern ext4_fsblk_t ext4_new_block (handle_t *handle, struct inode *inode, extern ext4_fsblk_t ext4_new_block (handle_t *handle, struct inode *inode,
ext4_fsblk_t goal, int *errp); ext4_fsblk_t goal, int *errp);
extern ext4_fsblk_t ext4_new_blocks (handle_t *handle, struct inode *inode, extern ext4_fsblk_t ext4_new_blocks (handle_t *handle, struct inode *inode,
...@@ -900,7 +901,7 @@ extern void ext4_free_blocks_sb (handle_t *handle, struct super_block *sb, ...@@ -900,7 +901,7 @@ extern void ext4_free_blocks_sb (handle_t *handle, struct super_block *sb,
extern ext4_fsblk_t ext4_count_free_blocks (struct super_block *); extern ext4_fsblk_t ext4_count_free_blocks (struct super_block *);
extern void ext4_check_blocks_bitmap (struct super_block *); extern void ext4_check_blocks_bitmap (struct super_block *);
extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb, extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
unsigned int block_group, ext4_group_t block_group,
struct buffer_head ** bh); struct buffer_head ** bh);
extern int ext4_should_retry_alloc(struct super_block *sb, int *retries); extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
extern void ext4_init_block_alloc_info(struct inode *); extern void ext4_init_block_alloc_info(struct inode *);
......
...@@ -30,6 +30,9 @@ typedef unsigned long long ext4_fsblk_t; ...@@ -30,6 +30,9 @@ typedef unsigned long long ext4_fsblk_t;
/* data type for file logical block number */ /* data type for file logical block number */
typedef __u32 ext4_lblk_t; typedef __u32 ext4_lblk_t;
/* data type for block group number */
typedef unsigned long ext4_group_t;
struct ext4_reserve_window { struct ext4_reserve_window {
ext4_fsblk_t _rsv_start; /* First byte reserved */ ext4_fsblk_t _rsv_start; /* First byte reserved */
ext4_fsblk_t _rsv_end; /* Last byte reserved or 0 */ ext4_fsblk_t _rsv_end; /* Last byte reserved or 0 */
...@@ -92,7 +95,7 @@ struct ext4_inode_info { ...@@ -92,7 +95,7 @@ struct ext4_inode_info {
* place a file's data blocks near its inode block, and new inodes * place a file's data blocks near its inode block, and new inodes
* near to their parent directory's inode. * near to their parent directory's inode.
*/ */
__u32 i_block_group; ext4_group_t i_block_group;
__u32 i_state; /* Dynamic state flags for ext4 */ __u32 i_state; /* Dynamic state flags for ext4 */
/* block reservation info */ /* block reservation info */
......
...@@ -35,7 +35,7 @@ struct ext4_sb_info { ...@@ -35,7 +35,7 @@ struct ext4_sb_info {
unsigned long s_itb_per_group; /* Number of inode table blocks per group */ unsigned long s_itb_per_group; /* Number of inode table blocks per group */
unsigned long s_gdb_count; /* Number of group descriptor blocks */ unsigned long s_gdb_count; /* Number of group descriptor blocks */
unsigned long s_desc_per_block; /* Number of group descriptors per block */ unsigned long s_desc_per_block; /* Number of group descriptors per block */
unsigned long s_groups_count; /* Number of groups in the fs */ ext4_group_t s_groups_count; /* Number of groups in the fs */
unsigned long s_overhead_last; /* Last calculated overhead */ unsigned long s_overhead_last; /* Last calculated overhead */
unsigned long s_blocks_last; /* Last seen block count */ unsigned long s_blocks_last; /* Last seen block count */
struct buffer_head * s_sbh; /* Buffer containing the super block */ struct buffer_head * s_sbh; /* Buffer containing the super block */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment