[syslinux:pathbased] btrfs: Implement next_extent and call generic_getfssec

syslinux-bot for Alek Du alek.du at intel.com
Tue Mar 2 19:12:12 PST 2010


Commit-ID:  19cf2a0eb61fb18ad4c30adda831b69ff0380323
Gitweb:     http://syslinux.zytor.com/commit/19cf2a0eb61fb18ad4c30adda831b69ff0380323
Author:     Alek Du <alek.du at intel.com>
AuthorDate: Tue, 2 Mar 2010 14:35:22 +0800
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Tue, 2 Mar 2010 19:09:57 -0800

btrfs: Implement next_extent and call generic_getfssec

Now multiple extent allocation is supported.
Also fixed the symlink file handling and fs_init typo.

Signed-off-by: Alek Du <alek.du at intel.com>
Signed-off-by: H. Peter Anvin <hpa at zytor.com>


---
 core/fs/btrfs/btrfs.c |   89 ++++++++++++++++++++++++++++++++++---------------
 1 files changed, 62 insertions(+), 27 deletions(-)

diff --git a/core/fs/btrfs/btrfs.c b/core/fs/btrfs/btrfs.c
index 5aa6935..04633f4 100644
--- a/core/fs/btrfs/btrfs.c
+++ b/core/fs/btrfs/btrfs.c
@@ -458,7 +458,7 @@ static struct inode *btrfs_iget_by_inr(struct fs_info *fs, u64 inr)
 	inode->size = inode_item.size;
 	inode->mode = get_inode_mode(inode_item.mode);
 
-	if (inode->mode == I_FILE) {
+	if (inode->mode == I_FILE || inode->mode == I_SYMLINK) {
 		struct btrfs_file_extent_item extent_item;
 		u64 offset;
 
@@ -514,33 +514,65 @@ static int btrfs_readlink(struct inode *inode, char *buf)
 	return inode->size;
 }
 
+static int btrfs_next_extent(struct inode *inode, uint32_t lstart)
+{
+	struct btrfs_disk_key search_key;
+	struct btrfs_file_extent_item extent_item;
+	struct btrfs_path path;
+	int ret;
+	u64 offset;
+	u32 sec_shift = SECTOR_SHIFT(fs);
+	u32 sec_size = SECTOR_SIZE(fs);
+
+	search_key.objectid = inode->ino;
+	search_key.type = BTRFS_EXTENT_DATA_KEY;
+	search_key.offset = lstart << sec_shift;
+	clear_path(&path);
+	ret = search_tree(fs_tree, &search_key, &path);
+	if (ret) { /* impossible */
+		printf("btrfs: search extent data error!\n");
+		return 0;
+	}
+	extent_item = *(struct btrfs_file_extent_item *)path.data;
+
+	if (extent_item.type == BTRFS_FILE_EXTENT_INLINE) {/* inline file */
+		/* we fake a extent here, and PVT of inode will tell us */
+		offset = path.offsets[0] + sizeof(struct btrfs_header)
+			+ path.item.offset
+			+ offsetof(struct btrfs_file_extent_item, disk_bytenr);
+		inode->next_extent.len =
+			(inode->size + sec_size -1) >> sec_shift;
+	} else {
+		offset = extent_item.disk_bytenr + extent_item.offset;
+		inode->next_extent.len =
+			(extent_item.num_bytes + sec_size - 1) >> sec_shift;
+	}
+	inode->next_extent.pstart =
+		logical_physical(offset) >> sec_shift;
+	PVT(inode)->offset = offset;
+	return 0;
+}
+
 static uint32_t btrfs_getfssec(struct file *file, char *buf, int sectors,
 					bool *have_more)
 {
-	struct inode *inode = file->inode;
-	struct disk *disk = fs->fs_dev->disk;
-	u32 sec_shift = fs->fs_dev->disk->sector_shift;
-	u32 phy = logical_physical(PVT(inode)->offset + file->offset);
-	u32 sec = phy >> sec_shift;
-	u32 off = phy - (sec << sec_shift);
-	u32 remain = file->file_len - file->offset;
-	u32 remain_sec = (remain + (1 << sec_shift) - 1) >> sec_shift;
-	u32 size;
-
-	if (sectors > remain_sec)
-		sectors = remain_sec;
-	/* btrfs extent is continus */
-	disk->rdwr_sectors(disk, buf, sec, sectors, 0);
-	size = sectors << sec_shift;
-	if (size > remain)
-		size = remain;
-	file->offset += size;
-	*have_more = remain - size;
-
-	if (off)/* inline file is not started with sector boundary */
-		memcpy(buf, buf + off, size);
-
-	return size;
+	u32 ret;
+	u32 off = PVT(file->inode)->offset % SECTOR_SIZE(fs);
+	bool handle_inline = false;
+
+	if (off && !file->offset) {/* inline file first read patch */
+		file->inode->size += off;
+		handle_inline = true;
+	}
+	ret = generic_getfssec(file, buf, sectors, have_more);
+	if (!ret)
+		return ret;
+	off = PVT(file->inode)->offset % SECTOR_SIZE(fs);
+	if (handle_inline) {/* inline file patch */
+		ret -= off;
+		memcpy(buf, buf + off, ret);
+	}
+	return ret;
 }
 
 static void btrfs_get_fs_tree(void)
@@ -595,7 +627,10 @@ static void btrfs_get_fs_tree(void)
 /* init. the fs meta data, return the block size shift bits. */
 static int btrfs_fs_init(struct fs_info *_fs)
 {
-	struct disk *disk = fs->fs_dev->disk;
+	struct disk *disk;
+
+	fs = _fs;
+	disk = fs->fs_dev->disk;
     
 	btrfs_init_crc32c();
 
@@ -604,7 +639,6 @@ static int btrfs_fs_init(struct fs_info *_fs)
 	fs->block_shift  = BTRFS_BLOCK_SHIFT;
 	fs->block_size   = 1 << fs->block_shift;
 
-	fs = _fs;
 	btrfs_read_super_block();
 	if (strncmp((char *)(&sb.magic), BTRFS_MAGIC, sizeof(sb.magic)))
 		return -1;
@@ -629,5 +663,6 @@ const struct fs_ops btrfs_fs_ops = {
     .getfssec      = btrfs_getfssec,
     .close_file    = generic_close_file,
     .mangle_name   = generic_mangle_name,
+    .next_extent   = btrfs_next_extent,
     .load_config   = generic_load_config
 };



More information about the Syslinux-commits mailing list