X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=lib%2Fdiskimage_ext2.ml;h=3ce0819f31f96602cbf19041becdff9e8674c654;hb=0f681c012fd8eac3807f038c234969969fa1339f;hp=0457597147bccd551dfbc473f03430b3287fe6eb;hpb=9611aba66734efe3e2f1e0792a90003b657a89f5;p=virt-df.git diff --git a/lib/diskimage_ext2.ml b/lib/diskimage_ext2.ml index 0457597..3ce0819 100644 --- a/lib/diskimage_ext2.ml +++ b/lib/diskimage_ext2.ml @@ -22,13 +22,90 @@ open Unix open Printf -open Diskimage_utils +open Diskimage_impl -let superblock_offset = 1024L +open Int63.Operators -let probe_ext2 dev = +let ( +* ) = Int32.add +let ( -* ) = Int32.sub +let ( ** ) = Int32.mul +let ( /* ) = Int32.div + +(* The fields in an ext2/3 superblock. *) +type ext2_sb = { + s_inodes_count : int32; + s_blocks_count : int32; + s_r_blocks_count : int32; + s_free_blocks_count : int32; + s_free_inodes_count : int32; + s_first_data_block : int32; + s_log_block_size : int32; + s_log_frag_size : int32; + s_blocks_per_group : int32; + s_frags_per_group : int32; + s_inodes_per_group : int32; + s_mtime : int32; + s_wtime : int32; + s_mnt_count : int; + s_max_mnt_count : int; + s_state : int; + s_errors : int; + s_minor_rev_level : int; + s_lastcheck : int32; + s_checkinterval : int32; + s_creator_os : int32; + s_rev_level : int32; + s_def_resuid : int; + s_def_resgid : int; + s_first_ino : int32; + s_inode_size : int; + s_block_group_nr : int; + s_feature_compat : int32; + s_feature_incompat : int32; + s_feature_ro_compat : int32; + s_uuid : string; + s_volume_name : string; + s_last_mounted : string; + s_algorithm_usage_bitmap : int32; + s_prealloc_blocks : int; + s_prealloc_dir_blocks : int; + s_reserved_gdt_blocks : int; + s_journal_uuid : string; + s_journal_inum : int32; + s_journal_dev : int32; + s_last_orphan : int32; + s_hash_seed0 : int32; + s_hash_seed1 : int32; + s_hash_seed2 : int32; + s_hash_seed3 : int32; + s_def_hash_version : int; + s_reserved_char_pad : int; + s_reserved_word_pad : int; + s_default_mount_opts : int32; + s_first_meta_bg : int32; + + (* Computed fields, don't appear in superblock: *) + block_size : int63; + groups_count : int63; +} + +(* Private data functions. *) +let attach_private_data, get_private_data = + private_data_functions (fun {fs_cb = {fs_cb_uq = u}} -> u) + +let id = "ext2" +let superblock_offset = ~^1024 +let superblock_len = ~^1024 + +(* Parse ext2/3 superblock and return a big structure containing + * all the fields. Also there are some extra fields which don't + * appear in the superblock itself, but are computed from other fields. + * + * If the device doesn't contain a superblock, raises Not_found. + *) +let parse_ext2_sb dev = (* Load the superblock. *) - let bits = dev#read_bitstring superblock_offset 1024 in + let bits = dev#read_bitstring superblock_offset superblock_len in (* The structure is straight from /usr/include/linux/ext3_fs.h *) bitmatch bits with @@ -82,20 +159,76 @@ let probe_ext2 dev = s_reserved_char_pad : 8; s_reserved_word_pad : 16 : littleendian; s_default_mount_opts : 32 : littleendian; - s_first_meta_bg : 32 : littleendian; (* First metablock block group *) - _ : 6080 : bitstring } -> (* Padding to the end of the block *) + s_first_meta_bg : 32 : littleendian } -> (* First metablock block group *) + + (* Work out the block size in bytes. *) + let block_size = ~^1024 <^< Int32.to_int s_log_block_size in - (* Work out the block size in bytes. *) - let s_log_block_size = Int32.to_int s_log_block_size in - let block_size = 1024L in - let block_size = Int64.shift_left block_size s_log_block_size in + (* Number of groups. *) + let groups_count = + Int63.of_int32 ( + (s_blocks_count -* s_first_data_block -* 1l) + /* s_blocks_per_group +* 1l + ) in - (* Number of groups. *) - let s_groups_count = - Int64.of_int32 ( - (s_blocks_count -* s_first_data_block -* 1l) - /* s_blocks_per_group +* 1l - ) in + { s_inodes_count = s_inodes_count; + s_blocks_count = s_blocks_count; + s_r_blocks_count = s_r_blocks_count; + s_free_blocks_count = s_free_blocks_count; + s_free_inodes_count = s_free_inodes_count; + s_first_data_block = s_first_data_block; + s_log_block_size = s_log_block_size; + s_log_frag_size = s_log_frag_size; + s_blocks_per_group = s_blocks_per_group; + s_frags_per_group = s_frags_per_group; + s_inodes_per_group = s_inodes_per_group; + s_mtime = s_mtime; + s_wtime = s_wtime; + s_mnt_count = s_mnt_count; + s_max_mnt_count = s_max_mnt_count; + s_state = s_state; + s_errors = s_errors; + s_minor_rev_level = s_minor_rev_level; + s_lastcheck = s_lastcheck; + s_checkinterval = s_checkinterval; + s_creator_os = s_creator_os; + s_rev_level = s_rev_level; + s_def_resuid = s_def_resuid; + s_def_resgid = s_def_resgid; + s_first_ino = s_first_ino; + s_inode_size = s_inode_size; + s_block_group_nr = s_block_group_nr; + s_feature_compat = s_feature_compat; + s_feature_incompat = s_feature_incompat; + s_feature_ro_compat = s_feature_ro_compat; + s_uuid = s_uuid; + s_volume_name = s_volume_name; + s_last_mounted = s_last_mounted; + s_algorithm_usage_bitmap = s_algorithm_usage_bitmap; + s_prealloc_blocks = s_prealloc_blocks; + s_prealloc_dir_blocks = s_prealloc_dir_blocks; + s_reserved_gdt_blocks = s_reserved_gdt_blocks; + s_journal_uuid = s_journal_uuid; + s_journal_inum = s_journal_inum; + s_journal_dev = s_journal_dev; + s_last_orphan = s_last_orphan; + s_hash_seed0 = s_hash_seed0; + s_hash_seed1 = s_hash_seed1; + s_hash_seed2 = s_hash_seed2; + s_hash_seed3 = s_hash_seed3; + s_def_hash_version = s_def_hash_version; + s_reserved_char_pad = s_reserved_char_pad; + s_reserved_word_pad = s_reserved_word_pad; + s_default_mount_opts = s_default_mount_opts; + s_first_meta_bg = s_first_meta_bg; + block_size = block_size; + groups_count = groups_count } + + | { _ } -> + raise Not_found (* Not an EXT2/3 superblock. *) + +let rec probe dev = + let sb = parse_ext2_sb dev in (* May raise Not_found. *) (* (* Number of group descriptors per block. *) @@ -109,26 +242,53 @@ let probe_ext2 dev = (* Calculate the block overhead (used by superblocks, inodes, etc.) * See fs/ext2/super.c. *) - let overhead = Int64.of_int32 s_first_data_block in + let overhead = Int63.of_int32 sb.s_first_data_block in let overhead = (* XXX *) overhead in - { - fs_name = "Linux ext2/3"; - fs_block_size = block_size; - fs_blocks_total = Int64.of_int32 s_blocks_count -^ overhead; + (* The blocksize of the filesystem is likely to be quite different + * from that of the underlying device, so create an overlay device + * with the natural filesystem blocksize. + *) + let fs_dev = new blocksize_overlay sb.block_size dev in + + let fs = { + fs_cb = callbacks (); + fs_dev = fs_dev; + + fs_blocksize = sb.block_size; + fs_blocks_total = Int63.of_int32 sb.s_blocks_count -^ overhead; + fs_is_swap = false; - fs_blocks_reserved = Int64.of_int32 s_r_blocks_count; - fs_blocks_avail = Int64.of_int32 s_free_blocks_count; + + fs_blocks_reserved = Int63.of_int32 sb.s_r_blocks_count; + fs_blocks_avail = Int63.of_int32 sb.s_free_blocks_count; fs_blocks_used = - Int64.of_int32 s_blocks_count -^ overhead - -^ Int64.of_int32 s_free_blocks_count; - fs_inodes_total = Int64.of_int32 s_inodes_count; - fs_inodes_reserved = 0L; (* XXX? *) - fs_inodes_avail = Int64.of_int32 s_free_inodes_count; - fs_inodes_used = Int64.of_int32 s_inodes_count - (*-^ 0L*) - -^ Int64.of_int32 s_free_inodes_count; - } + Int63.of_int32 sb.s_blocks_count -^ overhead + -^ Int63.of_int32 sb.s_free_blocks_count; + fs_inodes_total = Int63.of_int32 sb.s_inodes_count; + fs_inodes_reserved = ~^0; (* XXX? *) + fs_inodes_avail = Int63.of_int32 sb.s_free_inodes_count; + fs_inodes_used = Int63.of_int32 sb.s_inodes_count + (*-^ 0*) + -^ Int63.of_int32 sb.s_free_inodes_count; + } in - | { _ } -> - raise Not_found (* Not an EXT2/3 superblock. *) + (* Attach the original superblock as private data so we can + * get to it quickly in other callbacks. + *) + attach_private_data fs sb; + fs + +and offset_is_free _ _ = false + +and callbacks = + let i = ref 0 in + fun () -> { + fs_cb_uq = (incr i; !i); + fs_cb_name = id; + fs_cb_printable_name = "Linux ext2/3"; + fs_cb_offset_is_free = offset_is_free; + } + +(* Register the plugin. *) +let () = register_plugin ~filesystem:probe id