@@ -3892,6 +3892,7 @@
INIT_LIST_HEAD(&pa->pa_group_list);
pa->pa_deleted = 0;
- pa->pa_linear = 0;
+ pa->pa_type = MB_INODE_PA;
+ pa->pa_error = 0;
mb_debug("new inode pa %p: %llu/%u for %u\n", pa,
@@ -3956,6 +3957,7 @@
INIT_LIST_HEAD(&pa->pa_group_list);
pa->pa_deleted = 0;
- pa->pa_linear = 1;
+ pa->pa_type = MB_GROUP_PA;
+ pa->pa_error = 0;
mb_debug("new group pa %p: %llu/%u for %u\n", pa,
pa->pa_pstart, pa->pa_len, pa->pa_lstart);
-@@ -4019,7 +4021,10 @@
+@@ -4019,7 +4021,9 @@
int err = 0;
int free = 0;
-+ BUG_ON(!ext4_is_group_locked(sb, e4b->bd_group));
++ assert_spin_locked(ext4_group_lock_ptr(sb, e4b->bd_group));
BUG_ON(pa->pa_deleted == 0);
-+ BUG_ON(pa->pa_linear != 0);
+ BUG_ON(pa->pa_inode == NULL);
ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
grp_blk_start = pa->pa_pstart - bit;
+ /* "free < pa->pa_free" means we maybe double alloc the same blocks,
+ * otherwise maybe leave some free blocks unavailable, no need to BUG.*/
+ if ((free > pa->pa_free && !pa->pa_error) || (free < pa->pa_free)) {
-+ ext4_error(sb, __FUNCTION__, "pa free mismatch: [pa %p] "
++ ext4_error(sb,"pa free mismatch: [pa %p] "
+ "[phy %lu] [logic %lu] [len %u] [free %u] "
+ "[error %u] [inode %lu] [freed %u]", pa,
+ (unsigned long)pa->pa_pstart,
return err;
@@ -4800,6 +4813,24 @@
- *errp = -EDQUOT;
- goto out3;
- }
+ }
+ }
+
+
+ if (dev_check_rdonly(sb->s_bdev)) {
+ struct block_device *bdev = sb->s_bdev;
+ ar->len, ar->flags);
+ }
+
- inquota = ar->len;
-
- if (EXT4_I(ar->inode)->i_delalloc_reserved_flag)
+ ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+ if (!ac) {
+ ar->len = 0;
@@ -4850,6 +4881,25 @@
ac->ac_b_ex.fe_len = 0;
ar->len = 0;
+ * been updated or not when fail case. So can
+ * not revert pa_free back, just mark pa_error*/
+ pa->pa_error++;
-+ ext4_error(sb, __FUNCTION__,
++ ext4_error(sb,
+ "Updating bitmap error: [err %d] "
+ "[pa %p] [phy %lu] [logic %lu] "
+ "[len %u] [free %u] [error %u] "
+ printk(KERN_WARNING "Release to readonly device %s (%#x): "
+ "[inode %lu] [block %lu] [count %lu] [is_meta %d]\n",
+ bdev->bd_disk ? bdev->bd_disk->disk_name : "",
-+ bdev->bd_dev, inode->i_ino, block, count, metadata);
++ bdev->bd_dev, inode->i_ino, (unsigned long)block, count, metadata);
+ }
+
- ext4_debug("freeing block %lu\n", block);
+ ext4_debug("freeing block %llu\n", block);
trace_mark(ext4_free_blocks,
"dev %s block %llu count %lu metadata %d ino %lu",
Index: linux-stage/fs/ext4/mballoc.h
#include "ext4.h"
#include "group.h"
@@ -134,6 +135,7 @@
- unsigned short pa_free; /* how many blocks are free */
- unsigned short pa_linear; /* consumed in one direction
- * strictly, for grp prealloc */
+ ext4_grpblk_t pa_len; /* len of preallocated chunk */
+ ext4_grpblk_t pa_free; /* how many blocks are free */
+ unsigned short pa_type; /* pa type. inode or group */
+ unsigned short pa_error;
spinlock_t *pa_obj_lock;
struct inode *pa_inode; /* hack, for history only */