We need to avoid ENOMEM due to unexpected long length.

Signed-off-by: Jaegeuk Kim <jaeg...@kernel.org>
---
 fs/f2fs/file.c | 46 ++++++++++++++++++++++++++++------------------
 1 file changed, 28 insertions(+), 18 deletions(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 17b3059..3573b07 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1039,33 +1039,43 @@ static int __clone_blkaddrs(struct inode *src_inode, 
struct inode *dst_inode,
 
 static int __exchange_data_block(struct inode *src_inode,
                        struct inode *dst_inode, pgoff_t src, pgoff_t dst,
-                       int len, bool full)
+                       pgoff_t len, bool full)
 {
        block_t *src_blkaddr;
        int *do_replace;
+       pgoff_t olen;
        int ret;
 
-       src_blkaddr = f2fs_kvzalloc(sizeof(block_t) * len, GFP_KERNEL);
-       if (!src_blkaddr)
-               return -ENOMEM;
+       while (len) {
+               olen = min((pgoff_t)4 * ADDRS_PER_BLOCK, len);
 
-       do_replace = f2fs_kvzalloc(sizeof(int) * len, GFP_KERNEL);
-       if (!do_replace) {
-               kvfree(src_blkaddr);
-               return -ENOMEM;
-       }
+               src_blkaddr = f2fs_kvzalloc(sizeof(block_t) * olen, GFP_KERNEL);
+               if (!src_blkaddr)
+                       return -ENOMEM;
 
-       ret = __read_out_blkaddrs(src_inode, src_blkaddr, do_replace, src, len);
-       if (ret)
-               goto roll_back;
+               do_replace = f2fs_kvzalloc(sizeof(int) * olen, GFP_KERNEL);
+               if (!do_replace) {
+                       kvfree(src_blkaddr);
+                       return -ENOMEM;
+               }
 
-       ret = __clone_blkaddrs(src_inode, dst_inode, src_blkaddr,
-                                       do_replace, src, dst, len, full);
-       if (ret)
-               goto roll_back;
+               ret = __read_out_blkaddrs(src_inode, src_blkaddr,
+                                       do_replace, src, olen);
+               if (ret)
+                       goto roll_back;
 
-       kvfree(src_blkaddr);
-       kvfree(do_replace);
+               ret = __clone_blkaddrs(src_inode, dst_inode, src_blkaddr,
+                                       do_replace, src, dst, olen, full);
+               if (ret)
+                       goto roll_back;
+
+               src += olen;
+               dst += olen;
+               len -= olen;
+
+               kvfree(src_blkaddr);
+               kvfree(do_replace);
+       }
        return 0;
 
 roll_back:
-- 
2.8.3


------------------------------------------------------------------------------
What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic
patterns at an interface-level. Reveals which users, apps, and protocols are 
consuming the most bandwidth. Provides multi-vendor support for NetFlow, 
J-Flow, sFlow and other flows. Make informed decisions using capacity planning
reports.http://sdm.link/zohodev2dev
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to