@@ -141,13 +141,18 @@
* -- Extent-level locking
*/
+struct rsvd_info {
+ int ndelonly_clu; /* reserved clusters for delalloc es entry */
+ int ndelonly_blk; /* reserved blocks for delalloc es entry */
+};
+
static struct kmem_cache *ext4_es_cachep;
static struct kmem_cache *ext4_pending_cachep;
static int __es_insert_extent(struct inode *inode, struct extent_status *newes,
struct extent_status *prealloc);
static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
- ext4_lblk_t end, int *reserved,
+ ext4_lblk_t end, struct rsvd_info *rinfo,
struct extent_status *prealloc);
static int es_reclaim_extents(struct ext4_inode_info *ei, int *nr_to_scan);
static int __es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
@@ -1050,6 +1055,7 @@ int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk,
struct rsvd_count {
int ndelonly;
+ int ndelonly_blk;
bool first_do_lblk_found;
ext4_lblk_t first_do_lblk;
ext4_lblk_t last_do_lblk;
@@ -1076,6 +1082,7 @@ static void init_rsvd(struct inode *inode, ext4_lblk_t lblk,
struct rb_node *node;
rc->ndelonly = 0;
+ rc->ndelonly_blk = 0;
/*
* for bigalloc, note the first delonly block in the range has not
@@ -1124,10 +1131,12 @@ static void count_rsvd(struct inode *inode, ext4_lblk_t lblk, long len,
if (sbi->s_cluster_ratio == 1) {
rc->ndelonly += (int) len;
+ rc->ndelonly_blk = rc->ndelonly;
return;
}
/* bigalloc */
+ rc->ndelonly_blk += (int)len;
i = (lblk < es->es_lblk) ? es->es_lblk : lblk;
end = lblk + (ext4_lblk_t) len - 1;
@@ -1355,16 +1364,17 @@ static unsigned int get_rsvd(struct inode *inode, ext4_lblk_t end,
* @inode - file containing range
* @lblk - first block in range
* @end - last block in range
- * @reserved - number of cluster reservations released
+ * @rinfo - reserved information collected, includes number of
+ * block/cluster reservations released
* @prealloc - pre-allocated es to avoid memory allocation failures
*
- * If @reserved is not NULL and delayed allocation is enabled, counts
+ * If @rinfo is not NULL and delayed allocation is enabled, counts
* block/cluster reservations freed by removing range and if bigalloc
* enabled cancels pending reservations as needed. Returns 0 on success,
* error code on failure.
*/
static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
- ext4_lblk_t end, int *reserved,
+ ext4_lblk_t end, struct rsvd_info *rinfo,
struct extent_status *prealloc)
{
struct ext4_es_tree *tree = &EXT4_I(inode)->i_es_tree;
@@ -1374,11 +1384,15 @@ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
ext4_lblk_t len1, len2;
ext4_fsblk_t block;
int err = 0;
- bool count_reserved = true;
+ bool count_reserved = false;
struct rsvd_count rc;
- if (reserved == NULL || !test_opt(inode->i_sb, DELALLOC))
- count_reserved = false;
+ if (rinfo) {
+ rinfo->ndelonly_clu = 0;
+ rinfo->ndelonly_blk = 0;
+ if (test_opt(inode->i_sb, DELALLOC))
+ count_reserved = true;
+ }
es = __es_tree_search(&tree->root, lblk);
if (!es)
@@ -1476,8 +1490,10 @@ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
}
out_get_reserved:
- if (count_reserved)
- *reserved = get_rsvd(inode, end, es, &rc);
+ if (count_reserved) {
+ rinfo->ndelonly_clu = get_rsvd(inode, end, es, &rc);
+ rinfo->ndelonly_blk = rc.ndelonly_blk;
+ }
out:
return err;
}
@@ -1496,8 +1512,8 @@ void ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
ext4_lblk_t len)
{
ext4_lblk_t end;
+ struct rsvd_info rinfo;
int err = 0;
- int reserved = 0;
struct extent_status *es = NULL;
if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
@@ -1522,7 +1538,7 @@ void ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
* is reclaimed.
*/
write_lock(&EXT4_I(inode)->i_es_lock);
- err = __es_remove_extent(inode, lblk, end, &reserved, es);
+ err = __es_remove_extent(inode, lblk, end, &rinfo, es);
/* Free preallocated extent if it didn't get used. */
if (es) {
if (!es->es_len)
@@ -1534,7 +1550,7 @@ void ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
goto retry;
ext4_es_print_tree(inode);
- ext4_da_release_space(inode, reserved);
+ ext4_da_release_space(inode, rinfo.ndelonly_clu);
return;
}