浏览代码

xfs: improve kmem_realloc

Use krealloc to implement our realloc function.  This helps to avoid
new allocations if we are still in the slab bucket.  At least for the
bmap btree root that's actually the common case.

This also allows removing the now unused oldsize argument.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Christoph Hellwig 9 年之前
父节点
当前提交
664b60f6ba
共有 5 个文件被更改,包括 20 次插入21 次删除
  1. 15 11
      fs/xfs/kmem.c
  2. 1 1
      fs/xfs/kmem.h
  3. 3 7
      fs/xfs/libxfs/xfs_inode_fork.c
  4. 1 1
      fs/xfs/xfs_log_recover.c
  5. 0 1
      fs/xfs/xfs_mount.c

+ 15 - 11
fs/xfs/kmem.c

@@ -93,19 +93,23 @@ kmem_zalloc_large(size_t size, xfs_km_flags_t flags)
 }
 }
 
 
 void *
 void *
-kmem_realloc(const void *ptr, size_t newsize, size_t oldsize,
-	     xfs_km_flags_t flags)
+kmem_realloc(const void *old, size_t newsize, xfs_km_flags_t flags)
 {
 {
-	void	*new;
+	int	retries = 0;
+	gfp_t	lflags = kmem_flags_convert(flags);
+	void	*ptr;
 
 
-	new = kmem_alloc(newsize, flags);
-	if (ptr) {
-		if (new)
-			memcpy(new, ptr,
-				((oldsize < newsize) ? oldsize : newsize));
-		kmem_free(ptr);
-	}
-	return new;
+	do {
+		ptr = krealloc(old, newsize, lflags);
+		if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
+			return ptr;
+		if (!(++retries % 100))
+			xfs_err(NULL,
+	"%s(%u) possible memory allocation deadlock size %zu in %s (mode:0x%x)",
+				current->comm, current->pid,
+				newsize, __func__, lflags);
+		congestion_wait(BLK_RW_ASYNC, HZ/50);
+	} while (1);
 }
 }
 
 
 void *
 void *

+ 1 - 1
fs/xfs/kmem.h

@@ -62,7 +62,7 @@ kmem_flags_convert(xfs_km_flags_t flags)
 
 
 extern void *kmem_alloc(size_t, xfs_km_flags_t);
 extern void *kmem_alloc(size_t, xfs_km_flags_t);
 extern void *kmem_zalloc_large(size_t size, xfs_km_flags_t);
 extern void *kmem_zalloc_large(size_t size, xfs_km_flags_t);
-extern void *kmem_realloc(const void *, size_t, size_t, xfs_km_flags_t);
+extern void *kmem_realloc(const void *, size_t, xfs_km_flags_t);
 static inline void  kmem_free(const void *ptr)
 static inline void  kmem_free(const void *ptr)
 {
 {
 	kvfree(ptr);
 	kvfree(ptr);

+ 3 - 7
fs/xfs/libxfs/xfs_inode_fork.c

@@ -516,7 +516,6 @@ xfs_iroot_realloc(
 		new_max = cur_max + rec_diff;
 		new_max = cur_max + rec_diff;
 		new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
 		new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
 		ifp->if_broot = kmem_realloc(ifp->if_broot, new_size,
 		ifp->if_broot = kmem_realloc(ifp->if_broot, new_size,
-				XFS_BMAP_BROOT_SPACE_CALC(mp, cur_max),
 				KM_SLEEP | KM_NOFS);
 				KM_SLEEP | KM_NOFS);
 		op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
 		op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
 						     ifp->if_broot_bytes);
 						     ifp->if_broot_bytes);
@@ -660,7 +659,6 @@ xfs_idata_realloc(
 				ifp->if_u1.if_data =
 				ifp->if_u1.if_data =
 					kmem_realloc(ifp->if_u1.if_data,
 					kmem_realloc(ifp->if_u1.if_data,
 							real_size,
 							real_size,
-							ifp->if_real_bytes,
 							KM_SLEEP | KM_NOFS);
 							KM_SLEEP | KM_NOFS);
 			}
 			}
 		} else {
 		} else {
@@ -1376,8 +1374,7 @@ xfs_iext_realloc_direct(
 		if (rnew_size != ifp->if_real_bytes) {
 		if (rnew_size != ifp->if_real_bytes) {
 			ifp->if_u1.if_extents =
 			ifp->if_u1.if_extents =
 				kmem_realloc(ifp->if_u1.if_extents,
 				kmem_realloc(ifp->if_u1.if_extents,
-						rnew_size,
-						ifp->if_real_bytes, KM_NOFS);
+						rnew_size, KM_NOFS);
 		}
 		}
 		if (rnew_size > ifp->if_real_bytes) {
 		if (rnew_size > ifp->if_real_bytes) {
 			memset(&ifp->if_u1.if_extents[ifp->if_bytes /
 			memset(&ifp->if_u1.if_extents[ifp->if_bytes /
@@ -1461,9 +1458,8 @@ xfs_iext_realloc_indirect(
 	if (new_size == 0) {
 	if (new_size == 0) {
 		xfs_iext_destroy(ifp);
 		xfs_iext_destroy(ifp);
 	} else {
 	} else {
-		ifp->if_u1.if_ext_irec = (xfs_ext_irec_t *)
-			kmem_realloc(ifp->if_u1.if_ext_irec,
-				new_size, size, KM_NOFS);
+		ifp->if_u1.if_ext_irec =
+			kmem_realloc(ifp->if_u1.if_ext_irec, new_size, KM_NOFS);
 	}
 	}
 }
 }
 
 

+ 1 - 1
fs/xfs/xfs_log_recover.c

@@ -3843,7 +3843,7 @@ xlog_recover_add_to_cont_trans(
 	old_ptr = item->ri_buf[item->ri_cnt-1].i_addr;
 	old_ptr = item->ri_buf[item->ri_cnt-1].i_addr;
 	old_len = item->ri_buf[item->ri_cnt-1].i_len;
 	old_len = item->ri_buf[item->ri_cnt-1].i_len;
 
 
-	ptr = kmem_realloc(old_ptr, len+old_len, old_len, KM_SLEEP);
+	ptr = kmem_realloc(old_ptr, len + old_len, KM_SLEEP);
 	memcpy(&ptr[old_len], dp, len);
 	memcpy(&ptr[old_len], dp, len);
 	item->ri_buf[item->ri_cnt-1].i_len += len;
 	item->ri_buf[item->ri_cnt-1].i_len += len;
 	item->ri_buf[item->ri_cnt-1].i_addr = ptr;
 	item->ri_buf[item->ri_cnt-1].i_addr = ptr;

+ 0 - 1
fs/xfs/xfs_mount.c

@@ -89,7 +89,6 @@ xfs_uuid_mount(
 	if (hole < 0) {
 	if (hole < 0) {
 		xfs_uuid_table = kmem_realloc(xfs_uuid_table,
 		xfs_uuid_table = kmem_realloc(xfs_uuid_table,
 			(xfs_uuid_table_size + 1) * sizeof(*xfs_uuid_table),
 			(xfs_uuid_table_size + 1) * sizeof(*xfs_uuid_table),
-			xfs_uuid_table_size  * sizeof(*xfs_uuid_table),
 			KM_SLEEP);
 			KM_SLEEP);
 		hole = xfs_uuid_table_size++;
 		hole = xfs_uuid_table_size++;
 	}
 	}