--- /dev/null
+--- /dev/null
++++ b/ldiskfs/kernel_patches/patches/rhel6.3/ext4-notalloc_under_idatasem.patch
+@@ -0,0 +1,14 @@
++Index: linux-stage/fs/ext4/extents.c
++===================================================================
++--- linux-stage.orig/fs/ext4/extents.c 2015-07-13 22:22:56.000000000 +0300
+++++ linux-stage/fs/ext4/extents.c 2015-07-13 22:24:05.000000000 +0300
++@@ -4318,7 +4318,8 @@ static int ext4_find_delayed_extent(stru
++ struct buffer_head *head = NULL;
++ unsigned int nr_pages = PAGE_SIZE / sizeof(struct page *);
++
++- pages = kmalloc(PAGE_SIZE, GFP_KERNEL);
+++ /* we are running under i_data_sem so don't re-enter fs code */
+++ pages = kmalloc(PAGE_SIZE, GFP_NOFS);
++ if (pages == NULL)
++ return -ENOMEM;
++
RETURN(rc);
}
-/* Check if a block is allocated or not */
-static int osd_is_mapped(struct inode *inode, u64 offset)
-{
- sector_t (*fs_bmap)(struct address_space *, sector_t);
+struct osd_fextent {
+ sector_t start;
+ sector_t end;
+ unsigned int mapped:1;
+};
- fs_bmap = inode->i_mapping->a_ops->bmap;
+static int osd_is_mapped(struct dt_object *dt, __u64 offset,
+ struct osd_fextent *cached_extent)
+{
+ struct inode *inode = osd_dt_obj(dt)->oo_inode;
+ sector_t block = offset >> inode->i_blkbits;
+ sector_t start;
+ struct fiemap_extent_info fei = { 0 };
+ struct fiemap_extent fe = { 0 };
+ mm_segment_t saved_fs;
+ int rc;
- /* We can't know if we are overwriting or not */
- if (unlikely(fs_bmap == NULL))
- return 0;
+ if (block >= cached_extent->start && block < cached_extent->end)
+ return cached_extent->mapped;
if (i_size_read(inode) == 0)
return 0;
/* Beyond EOF, must not be mapped */
- if (((i_size_read(inode) - 1) >> inode->i_blkbits) <
- (offset >> inode->i_blkbits))
+ if (((i_size_read(inode) - 1) >> inode->i_blkbits) < block)
return 0;
- if (fs_bmap(inode->i_mapping, offset >> inode->i_blkbits) == 0)
+ fei.fi_extents_max = 1;
+ fei.fi_extents_start = &fe;
+
+ saved_fs = get_fs();
+ set_fs(get_ds());
+ rc = inode->i_op->fiemap(inode, &fei, offset, FIEMAP_MAX_OFFSET-offset);
+ set_fs(saved_fs);
+ if (rc != 0)
return 0;
- return 1;
+ start = fe.fe_logical >> inode->i_blkbits;
+
+ if (start > block) {
+ cached_extent->start = block;
+ cached_extent->end = start;
+ cached_extent->mapped = 0;
+ } else {
+ cached_extent->start = start;
+ cached_extent->end = (fe.fe_logical + fe.fe_length) >>
+ inode->i_blkbits;
+ cached_extent->mapped = 1;
+ }
+
+ return cached_extent->mapped;
}
static int osd_declare_write_commit(const struct lu_env *env,
int credits = 0;
bool ignore_quota = false;
long long quota_space = 0;
+ struct osd_fextent extent = { 0 };
ENTRY;
LASSERT(handle != NULL);
lnb[i - 1].lnb_file_offset + lnb[i - 1].lnb_len)
extents++;
- if (!osd_is_mapped(inode, lnb[i].lnb_file_offset))
+ if (!osd_is_mapped(dt, lnb[i].lnb_file_offset, &extent))
quota_space += PAGE_CACHE_SIZE;
/* ignore quota for the whole request if any page is from
struct osd_device *osd = osd_obj2dev(osd_dt_obj(dt));
loff_t isize;
int rc = 0, i;
+ struct osd_fextent extent = { 0 };
LASSERT(inode);
for (i = 0; i < npages; i++) {
if (lnb[i].lnb_rc == -ENOSPC &&
- osd_is_mapped(inode, lnb[i].lnb_file_offset)) {
+ osd_is_mapped(dt, lnb[i].lnb_file_offset, &extent)) {
/* Allow the write to proceed if overwriting an
* existing block */
lnb[i].lnb_rc = 0;