From: Hyojun Kim <hyo...@google.com>

This patch adds f2fs_read() and f2fs_filesize_update(). It also refactors
f2fs_write_block() and renamed as f2fs_write().

Signed-off-by: Hyojun Kim <hyo...@google.com>
Signed-off-by: Jaegeuk Kim <jaeg...@google.com>
---
 fsck/fsck.h    |   6 ++
 fsck/segment.c | 248 ++++++++++++++++++++++++++++++++++++++-------------------
 2 files changed, 171 insertions(+), 83 deletions(-)

diff --git a/fsck/fsck.h b/fsck/fsck.h
index 1e8ed0b..5628906 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -219,6 +219,12 @@ void f2fs_alloc_nid(struct f2fs_sb_info *, nid_t *, int);
 void set_data_blkaddr(struct dnode_of_data *);
 block_t new_node_block(struct f2fs_sb_info *,
                                        struct dnode_of_data *, unsigned int);
+
+/* segment.c */
+u64 f2fs_read(struct f2fs_sb_info *, nid_t, void *, u64, pgoff_t);
+u64 f2fs_write(struct f2fs_sb_info *, nid_t, void *, u64, pgoff_t);
+void f2fs_filesize_update(struct f2fs_sb_info *, nid_t, u64);
+
 void get_dnode_of_data(struct f2fs_sb_info *, struct dnode_of_data *,
                                        pgoff_t, int);
 void make_dentry_ptr(struct f2fs_dentry_ptr *, struct f2fs_node *, void *, 
int);
diff --git a/fsck/segment.c b/fsck/segment.c
index 2ea5bf1..e13f147 100644
--- a/fsck/segment.c
+++ b/fsck/segment.c
@@ -68,111 +68,193 @@ void new_data_block(struct f2fs_sb_info *sbi, void *block,
        set_data_blkaddr(dn);
 }
 
-static void f2fs_write_block(struct f2fs_sb_info *sbi, nid_t ino, void *buffer,
+u64 f2fs_read(struct f2fs_sb_info *sbi, nid_t ino, void *buffer,
                                        u64 count, pgoff_t offset)
 {
-       u64 start = F2FS_BYTES_TO_BLK(offset);
-       u64 len = F2FS_BYTES_TO_BLK(count);
-       u64 end_offset;
-       u64 off_in_block, len_in_block, len_already;
-       struct dnode_of_data dn = {0};
-       void *data_blk;
+       struct dnode_of_data dn;
        struct node_info ni;
        struct f2fs_node *inode;
-       int idirty = 0;
-       int ret = -1;
-
+       char *blk_buffer;
+       u64 filesize;
+       u64 off_in_blk;
+       u64 len_in_blk;
+       u64 read_count;
+       u64 remained_blkentries;
+       block_t blkaddr;
+       void *index_node = NULL;
+
+       memset(&dn, 0, sizeof(dn));
+
+       /* Memory allocation for block buffer and inode. */
+       blk_buffer = calloc(BLOCK_SZ, 2);
+       ASSERT(blk_buffer);
+       inode = (struct f2fs_node*)(blk_buffer + BLOCK_SZ);
+
+       /* Read inode */
        get_node_info(sbi, ino, &ni);
-       inode = calloc(BLOCK_SZ, 1);
-       ASSERT(inode);
-
-       ret = dev_read_block(inode, ni.blk_addr);
-       ASSERT(ret >= 0);
-
-       if (S_ISDIR(le16_to_cpu(inode->i.i_mode)) ||
-                       S_ISLNK(le16_to_cpu(inode->i.i_mode)))
-               ASSERT(0);
-
-       off_in_block = offset & ((1 << F2FS_BLKSIZE_BITS) - 1);
-       len_in_block = (1 << F2FS_BLKSIZE_BITS) - off_in_block;
-       if (len_in_block > count)
-               len_in_block = count;
-       len_already = 0;
-
-       /*
-        * When calculate how many blocks this 'count' stride accross,
-        * We should take offset in a block in account.
-        */
-       len = F2FS_BYTES_TO_BLK(count + off_in_block
-                       + ((1 << F2FS_BLKSIZE_BITS) - 1));
-
-       data_blk = calloc(BLOCK_SZ, 1);
-       ASSERT(data_blk);
-
-       set_new_dnode(&dn, inode, NULL, ino);
+       ASSERT(dev_read_block(inode, ni.blk_addr) >= 0);
+       ASSERT(!S_ISDIR(le16_to_cpu(inode->i.i_mode)));
+       ASSERT(!S_ISLNK(le16_to_cpu(inode->i.i_mode)));
+
+       /* Adjust count with file length. */
+       filesize = le64_to_cpu(inode->i.i_size);
+       if (offset > filesize)
+               count = 0;
+       else if (count + offset > filesize)
+               count = filesize - offset;
+
+       /* Main loop for file blocks */
+       read_count = remained_blkentries = 0;
+       while (count > 0) {
+               if (remained_blkentries == 0) {
+                       set_new_dnode(&dn, inode, NULL, ino);
+                       get_dnode_of_data(sbi, &dn, F2FS_BYTES_TO_BLK(offset),
+                                       LOOKUP_NODE);
+                       if (index_node)
+                               free(index_node);
+                       index_node = (dn.node_blk == dn.inode_blk) ?
+                                                       NULL : dn.node_blk;
+                       remained_blkentries = ADDRS_PER_PAGE(dn.node_blk);
+               }
+               ASSERT(remained_blkentries > 0);
+
+               blkaddr = datablock_addr(dn.node_blk, dn.ofs_in_node);
+               if (blkaddr == NULL_ADDR || blkaddr == NEW_ADDR)
+                       break;
+
+               off_in_blk = offset % BLOCK_SZ;
+               len_in_blk = BLOCK_SZ - off_in_blk;
+               if (len_in_blk > count)
+                       len_in_blk = count;
+
+               /* Read data from single block. */
+               if (len_in_blk < BLOCK_SZ) {
+                       ASSERT(dev_read_block(blk_buffer, blkaddr) >= 0);
+                       memcpy(buffer, blk_buffer + off_in_blk, len_in_blk);
+               } else {
+                       /* Direct read */
+                       ASSERT(dev_read_block(buffer, blkaddr) >= 0);
+               }
 
-       while (len) {
-               if (dn.node_blk != dn.inode_blk)
-                       free(dn.node_blk);
+               offset += len_in_blk;
+               count -= len_in_blk;
+               buffer += len_in_blk;
+               read_count += len_in_blk;
 
-               set_new_dnode(&dn, inode, NULL, ino);
-               get_dnode_of_data(sbi, &dn, start, ALLOC_NODE);
+               dn.ofs_in_node++;
+               remained_blkentries--;
+       }
+       if (index_node)
+               free(index_node);
+       free(blk_buffer);
 
-               end_offset = ADDRS_PER_PAGE(dn.node_blk);
+       return read_count;
+}
 
-               while (dn.ofs_in_node < end_offset && len) {
-                       block_t blkaddr;
+u64 f2fs_write(struct f2fs_sb_info *sbi, nid_t ino, void *buffer,
+                                       u64 count, pgoff_t offset)
+{
+       struct dnode_of_data dn;
+       struct node_info ni;
+       struct f2fs_node *inode;
+       char *blk_buffer;
+       u64 off_in_blk;
+       u64 len_in_blk;
+       u64 written_count;
+       u64 remained_blkentries;
+       block_t blkaddr;
+       void* index_node = NULL;
+       int idirty = 0;
 
-                       blkaddr = datablock_addr(dn.node_blk, dn.ofs_in_node);
+       /* Memory allocation for block buffer and inode. */
+       blk_buffer = calloc(BLOCK_SZ, 2);
+       ASSERT(blk_buffer);
+       inode = (struct f2fs_node*)(blk_buffer + BLOCK_SZ);
 
-                       /* A new page from WARM_DATA */
-                       if (blkaddr == NULL_ADDR) {
-                               new_data_block(sbi, data_blk, &dn,
-                                                       CURSEG_WARM_DATA);
-                               blkaddr = dn.data_blkaddr;
-                               idirty |= dn.idirty;
-                       }
+       /* Read inode */
+       get_node_info(sbi, ino, &ni);
+       ASSERT(dev_read_block(inode, ni.blk_addr) >= 0);
+       ASSERT(!S_ISDIR(le16_to_cpu(inode->i.i_mode)));
+       ASSERT(!S_ISLNK(le16_to_cpu(inode->i.i_mode)));
+
+       /* Main loop for file blocks */
+       written_count = remained_blkentries = 0;
+       while (count > 0) {
+               if (remained_blkentries == 0) {
+                       set_new_dnode(&dn, inode, NULL, ino);
+                       get_dnode_of_data(sbi, &dn, F2FS_BYTES_TO_BLK(offset),
+                                       ALLOC_NODE);
+                       idirty |= dn.idirty;
+                       if (index_node)
+                               free(index_node);
+                       index_node = (dn.node_blk == dn.inode_blk) ?
+                                                       NULL : dn.node_blk;
+                       remained_blkentries = ADDRS_PER_PAGE(dn.node_blk);
+               }
+               ASSERT(remained_blkentries > 0);
 
-                       /* Copy data from buffer to file */
-                       ret = dev_read_block(data_blk, blkaddr);
-                       ASSERT(ret >= 0);
+               blkaddr = datablock_addr(dn.node_blk, dn.ofs_in_node);
+               if (blkaddr == NULL_ADDR || blkaddr == NEW_ADDR) {
+                       new_data_block(sbi, blk_buffer, &dn, CURSEG_WARM_DATA);
+                       blkaddr = dn.data_blkaddr;
+               }
 
-                       memcpy(data_blk + off_in_block, buffer, len_in_block);
+               off_in_blk = offset % BLOCK_SZ;
+               len_in_blk = BLOCK_SZ - off_in_blk;
+               if (len_in_blk > count)
+                       len_in_blk = count;
+
+               /* Write data to single block. */
+               if (len_in_blk < BLOCK_SZ) {
+                       ASSERT(dev_read_block(blk_buffer, blkaddr) >= 0);
+                       memcpy(blk_buffer + off_in_blk, buffer, len_in_blk);
+                       ASSERT(dev_write_block(blk_buffer, blkaddr) >= 0);
+               } else {
+                       /* Direct write */
+                       ASSERT(dev_write_block(buffer, blkaddr) >= 0);
+               }
 
-                       ret = dev_write_block(data_blk, blkaddr);
-                       ASSERT(ret >= 0);
+               offset += len_in_blk;
+               count -= len_in_blk;
+               buffer += len_in_blk;
+               written_count += len_in_blk;
 
-                       off_in_block = 0;
-                       len_already += len_in_block;
-                       if ((count - len_already) > (1 << F2FS_BLKSIZE_BITS))
-                               len_in_block = 1 << F2FS_BLKSIZE_BITS;
-                       else
-                               len_in_block = count - len_already;
-                       len--;
-                       start++;
-                       dn.ofs_in_node++;
-               }
-               /* Update the direct node */
-               if (dn.ndirty) {
-                       ret = dev_write_block(dn.node_blk, dn.node_blkaddr);
-                       ASSERT(ret >= 0);
-               }
+               dn.ofs_in_node++;
+               if ((--remained_blkentries == 0 || count == 0) && (dn.ndirty))
+                       ASSERT(dev_write_block(dn.node_blk, dn.node_blkaddr) >= 
0);
        }
-
-       /* Update the inode info */
-       if (le64_to_cpu(inode->i.i_size) < offset + count) {
-               inode->i.i_size = cpu_to_le64(offset + count);
+       if (offset > le64_to_cpu(inode->i.i_size)) {
+               inode->i.i_size = cpu_to_le64(offset);
                idirty = 1;
        }
-
        if (idirty) {
                ASSERT(inode == dn.inode_blk);
                write_inode(ni.blk_addr, inode);
        }
+       if (index_node)
+               free(index_node);
+       free(blk_buffer);
+
+       return written_count;
+}
+
+/* This function updates only inode->i.i_size */
+void f2fs_filesize_update(struct f2fs_sb_info *sbi, nid_t ino, u64 filesize)
+{
+       struct node_info ni;
+       struct f2fs_node *inode;
+
+       inode = calloc(BLOCK_SZ, 1);
+       ASSERT(inode);
+       get_node_info(sbi, ino, &ni);
+
+       ASSERT(dev_read_block(inode, ni.blk_addr) >= 0);
+       ASSERT(!S_ISDIR(le16_to_cpu(inode->i.i_mode)));
+       ASSERT(!S_ISLNK(le16_to_cpu(inode->i.i_mode)));
+
+       inode->i.i_size = cpu_to_le64(filesize);
 
-       if (dn.node_blk && dn.node_blk != dn.inode_blk)
-               free(dn.node_blk);
-       free(data_blk);
+       write_inode(ni.blk_addr, inode);
        free(inode);
 }
 
@@ -221,7 +303,7 @@ int f2fs_build_file(struct f2fs_sb_info *sbi, struct dentry 
*de)
                free(node_blk);
        } else {
                while ((n = read(fd, buffer, BLOCK_SZ)) > 0) {
-                       f2fs_write_block(sbi, de->ino, buffer, n, off);
+                       f2fs_write(sbi, de->ino, buffer, n, off);
                        off += n;
                }
        }
-- 
2.14.0.rc1.383.gd1ce394fe2-goog


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to