btrfs-convert: add reiserfs support
PATCH 1/1 btrfs-convert: add reiserfs support
Now that the semester's over, I've finally gotten around to finishing this. Ironically, I no longer have a ReiserFS partition I want to convert :P.
This depends on my previous four patches for btrfs-convert.
This version is usable and quite complete, but I'm unsure about the way it handles xattrs (which will end up both converted and left in the .reiserfs_priv directory) and some of the code that loops over btrfs trees. I've also found some problems with the generic conversion code that I'll look into later.
What should work:
- ReiserFS versions 3.5 and 3.6.
- Files with direct, indirect, and sparse blocks.
- All stat information, file types, and modes.
- Attributes, extended attributes, and ACLs.
- Everything else btrfs-convert supports for ext2.
What doesn't:
- The old, supposedly extinct ReiserFS layout with the superblock at 8K.
- xattrs too big to fit in a leaf block. This is a current limitation of btrfs.
What hasn't been tested:
- Multiple real-world filesystems (I only have one)
- 8192-byte blocks (ReiserFS crashes horribly on mount)
--- convert/convert.c | 140 ++++++++- convert/convert.h | 7 + convert/reiserfs.c | 890 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ctree.h | 11 + 4 files changed, 1046 insertions(+), 2 deletions(-) create mode 100644 convert/reiserfs.c
convert/convert.c +138 -2
@@ -171,8 +171,8 @@ struct btrfs_extent_ops extent_ops = { .free_extent = custom_free_extent, }; -static int read_disk_extent (struct btrfs_root *root,u64 bytenr, -u64 num_bytes,char *buffer) +int read_disk_extent (struct btrfs_root *root,u64 bytenr,u64 num_bytes, +char *buffer) {int ret;struct btrfs_fs_devices *fs_devs = root->fs_info->fs_devices;
@@ -1794,6 +1794,141 @@ err:return ret; } +static u8 imode_to_type (u32 imode) +{ +#define S_SHIFT 12 +static unsigned char btrfs_type_by_mode[S_IFMT >>S_SHIFT ] = { + [S_IFREG >>S_SHIFT ] =BTRFS_FT_REG_FILE , + [S_IFDIR >>S_SHIFT ] =BTRFS_FT_DIR , + [S_IFCHR >>S_SHIFT ] =BTRFS_FT_CHRDEV , + [S_IFBLK >>S_SHIFT ] =BTRFS_FT_BLKDEV , + [S_IFIFO >>S_SHIFT ] =BTRFS_FT_FIFO , + [S_IFSOCK >>S_SHIFT ] =BTRFS_FT_SOCK , + [S_IFLNK >>S_SHIFT ] =BTRFS_FT_SYMLINK , + }; + +return btrfs_type_by_mode[(imode &S_IFMT ) >>S_SHIFT ]; +#undef S_SHIFT +} + +static int fix_dir_item_type (struct btrfs_trans_handle *trans, +struct btrfs_root *root,u64 dir,u64 index, +const char *name,int name_len,int type) +{ +struct btrfs_path path; +struct btrfs_dir_item *di; + +btrfs_init_path (&path); + + di =btrfs_lookup_dir_item (trans, root, &path, dir, name, name_len,1 ); +if (IS_ERR (di)) +return PTR_ERR (di); +if (!di) +return -ENOENT ; +btrfs_set_dir_type (path.nodes[0 ], di, type); +btrfs_mark_buffer_dirty (path.nodes[0 ]); +btrfs_release_path (root, &path); + + di =btrfs_lookup_dir_index_item (trans, root, &path, dir, index, + name, name_len,1 ); +if (IS_ERR (di)) +return PTR_ERR (di); +if (!di) +return -ENOENT ; +btrfs_set_dir_type (path.nodes[0 ], di, type); +btrfs_mark_buffer_dirty (path.nodes[0 ]); +btrfs_release_path (root, &path); + +return 0 ; +} + +int fix_dir_item_types (struct btrfs_trans_handle *trans, +struct btrfs_root *root) +{ +struct btrfs_path path; +int ret; +struct btrfs_key key; +struct btrfs_key found_key; +struct extent_buffer *node; +int slot; +int cur_type =BTRFS_FT_UNKNOWN ; + +btrfs_init_path (&path); + + key.objectid =BTRFS_FIRST_FREE_OBJECTID ; + key.type =BTRFS_INODE_ITEM_KEY ; + key.offset =0 ; + +while (1 ) { + ret =btrfs_search_slot (trans, root, &key, &path,0 ,0 ); +if (ret <0 ) +return ret; + node = path.nodes[0 ]; + slot = path.slots[0 ]; +if (slot >=btrfs_header_nritems (node)) { + ret =btrfs_next_leaf (root, &path); +if (ret <0 ) +return ret; +if (ret >0 ) +break ;/* finished the whole tree */ + node = path.nodes[0 ]; + slot = path.slots[0 ]; + } +btrfs_item_key_to_cpu (node, &found_key, slot); + +if (btrfs_key_type (&found_key) ==BTRFS_INODE_ITEM_KEY ) { +/* found an inode, look for refs */ +struct btrfs_inode_item *ii = +btrfs_item_ptr (node, slot, + struct btrfs_inode_item); + cur_type =imode_to_type (btrfs_inode_mode (node, ii)); + key.objectid = found_key.objectid; + key.type =BTRFS_INODE_REF_KEY ; + key.offset =0 ; + goto next; + } +if (key.objectid != found_key.objectid + ||btrfs_key_type (&key) !=btrfs_key_type (&found_key)) { +/* no more refs, look for next inode */ + key.objectid = found_key.objectid +1 ; + key.type =BTRFS_INODE_ITEM_KEY ; + key.offset =0 ; + goto next; + } + key.offset = found_key.offset +1 ; +/* leave the root dir's ".." entry alone */ +if (found_key.objectid ==BTRFS_FIRST_FREE_OBJECTID + && found_key.offset ==BTRFS_FIRST_FREE_OBJECTID ) + goto next; + +struct btrfs_inode_ref *ref; + ref = btrfs_item_ptr(node, slot, struct btrfs_inode_ref); +u32 size =btrfs_item_size_nr (node, slot); +while (size) { +u64 index =btrfs_inode_ref_index (node, ref); +char namebuf[BTRFS_NAME_LEN ]; +u32 name_len =btrfs_inode_ref_name_len (node, ref); +BUG_ON (name_len >sizeof (namebuf)); +read_extent_buffer (node, namebuf, (u64)(ref +1 ), + name_len); + + ret =fix_dir_item_type (trans, root, found_key.offset, + index, namebuf, name_len, + cur_type); +if (ret) +return ret; + +u32 len =sizeof (*ref) + name_len; + ref = (struct btrfs_inode_ref *)((char *)ref + len); + size -= len; + } +next: +btrfs_release_path (root, &path); + } +btrfs_release_path (root, &path); +return 0 ; +} +static int copy_dirtiness (struct extent_io_tree *out,struct extent_io_tree *in) {
@@ -1818,6 +1953,7 @@ static int open_fs(struct convert_fs *fs, const char *devname) {"ext3", ext2_open}, {"ext4", ext2_open}, {"ext4dev", ext2_open}, + {"reiserfs", reiserfs_open}, };int i;
convert/convert.h +7 -0
@@ -41,6 +41,7 @@ struct convert_fs { };int ext2_open (struct convert_fs *fs,const char *name); +int reiserfs_open (struct convert_fs *fs,const char *name);struct extent_iterate_data {struct btrfs_trans_handle *trans;
@@ -73,4 +74,10 @@ int add_file_mem_extent(struct extent_iterate_data *priv, u64 file_off,int add_file_disk_extent (struct extent_iterate_data *priv,u64 file_off,u64 disk_off,u64 size); +int fix_dir_item_types (struct btrfs_trans_handle *trans, +struct btrfs_root *root); + +int read_disk_extent (struct btrfs_root *root,u64 bytenr,u64 num_bytes, +char *buffer); +#endif
convert/reiserfs.c new file +890 -0
890 lines not on this page · raw message
ctree.h +11 -0
@@ -290,6 +290,9 @@ struct btrfs_header {#define BTRFS_MAX_INLINE_DATA_SIZE (r) (BTRFS_LEAF_DATA_SIZE(r) - \ sizeof(struct btrfs_item) - \ sizeof(struct btrfs_file_extent_item)) +#define BTRFS_MAX_XATTR_SIZE (r) (BTRFS_LEAF_DATA_SIZE(r) - \ + sizeof(struct btrfs_item) -\ + sizeof(struct btrfs_dir_item))/*
@@ -858,6 +861,14 @@ struct btrfs_root {#define BTRFS_INODE_NODATASUM (1 << 0)#define BTRFS_INODE_NODATACOW (1 << 1)#define BTRFS_INODE_READONLY (1 << 2) +#define BTRFS_INODE_NOCOMPRESS (1 << 3) +#define BTRFS_INODE_PREALLOC (1 << 4) +#define BTRFS_INODE_SYNC (1 << 5) +#define BTRFS_INODE_IMMUTABLE (1 << 6) +#define BTRFS_INODE_APPEND (1 << 7) +#define BTRFS_INODE_NODUMP (1 << 8) +#define BTRFS_INODE_NOATIME (1 << 9) +#define BTRFS_INODE_DIRSYNC (1 << 10)#define read_eb_member (eb, ptr, type, member, result) ( \ read_extent_buffer(eb, (char *)(result), \
Signature · 1 line
1.7.1
Quoted 3 lines · On Monday 17 May 2010 08:26:00 Sean Bartell wrote:
What hasn't been tested:
- Multiple real-world filesystems (I only have one)
- 8192-byte blocks (ReiserFS crashes horribly on mount)
Well, AFAIK 8192 blocks are supported only on platforms that have 8kb m= emory=20
pages (e.g. Alpha), it's a bug it even tries to mount it on x86.
Regards,=20
--=20
Hubert Kario
QBS - Quality Business Software
02-656 Warszawa, ul. Ksawer=C3=B3w 30/85 tel. +48 (22) 646-61-51, 646-74-24 www.qbs.com.pl
System Zarz=C4=85dzania Jako=C5=9Bci=C4=85
zgodny z norm=C4=85 ISO 9001:2000
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" = in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html