X-Git-Url: http://git.annexia.org/?p=virt-top.git;a=blobdiff_plain;f=virt-df%2Fvirt_df_ext2.ml;fp=virt-df%2Fvirt_df_ext2.ml;h=0ea8a258e116059d54cb02c706e100297594f28c;hp=1acd85517640244ae2980ec6a2aca885596ec9ca;hb=e6050cae9eee80791c3bb26f34c61f7dc89b142f;hpb=f31c12ec325dd0f4f77e278c243d89da4ea228b8 diff --git a/virt-df/virt_df_ext2.ml b/virt-df/virt_df_ext2.ml index 1acd855..0ea8a25 100644 --- a/virt-df/virt_df_ext2.ml +++ b/virt-df/virt_df_ext2.ml @@ -21,46 +21,82 @@ open Unix open Printf + open Virt_df_gettext.Gettext +open Virt_df + +let superblock_offset = 1024L + +let probe_ext2 (dev : device) = + (* Load the superblock. *) + let bits = dev#read_bitstring superblock_offset 1024 in + + (* The structure is straight from /usr/include/linux/ext3_fs.h *) + bitmatch bits with + | s_inodes_count : 32 : littleendian; (* Inodes count *) + s_blocks_count : 32 : littleendian; (* Blocks count *) + s_r_blocks_count : 32 : littleendian; (* Reserved blocks count *) + s_free_blocks_count : 32 : littleendian; (* Free blocks count *) + s_free_inodes_count : 32 : littleendian; (* Free inodes count *) + s_first_data_block : 32 : littleendian; (* First Data Block *) + s_log_block_size : 32 : littleendian; (* Block size *) + s_log_frag_size : 32 : littleendian; (* Fragment size *) + s_blocks_per_group : 32 : littleendian; (* # Blocks per group *) + s_frags_per_group : 32 : littleendian; (* # Fragments per group *) + s_inodes_per_group : 32 : littleendian; (* # Inodes per group *) + s_mtime : 32 : littleendian; (* Mount time *) + s_wtime : 32 : littleendian; (* Write time *) + s_mnt_count : 16 : littleendian; (* Mount count *) + s_max_mnt_count : 16 : littleendian; (* Maximal mount count *) + 0xef53 : 16 : littleendian; (* Magic signature *) + s_state : 16 : littleendian; (* File system state *) + s_errors : 16 : littleendian; (* Behaviour when detecting errors *) + s_minor_rev_level : 16 : littleendian; (* minor revision level *) + s_lastcheck : 32 : littleendian; (* time of last check *) + s_checkinterval : 32 : littleendian; (* max. time between checks *) + s_creator_os : 32 : littleendian; (* OS *) + s_rev_level : 32 : littleendian; (* Revision level *) + s_def_resuid : 16 : littleendian; (* Default uid for reserved blocks *) + s_def_resgid : 16 : littleendian; (* Default gid for reserved blocks *) + s_first_ino : 32 : littleendian; (* First non-reserved inode *) + s_inode_size : 16 : littleendian; (* size of inode structure *) + s_block_group_nr : 16 : littleendian; (* block group # of this superblock *) + s_feature_compat : 32 : littleendian; (* compatible feature set *) + s_feature_incompat : 32 : littleendian; (* incompatible feature set *) + s_feature_ro_compat : 32 : littleendian; (* readonly-compatible feature set *) + s_uuid : 128 : bitstring; (* 128-bit uuid for volume *) + s_volume_name : 128 : bitstring; (* volume name XXX string *) + s_last_mounted : 512 : bitstring; (* directory where last mounted XXX string *) + s_algorithm_usage_bitmap : 32 : littleendian; (* For compression *) + s_prealloc_blocks : 8; (* Nr of blocks to try to preallocate*) + s_prealloc_dir_blocks : 8; (* Nr to preallocate for dirs *) + s_reserved_gdt_blocks : 16 : littleendian; (* Per group desc for online growth *) + s_journal_uuid : 128 : bitstring; (* uuid of journal superblock *) + s_journal_inum : 32 : littleendian; (* inode number of journal file *) + s_journal_dev : 32 : littleendian; (* device number of journal file *) + s_last_orphan : 32 : littleendian; (* start of list of inodes to delete *) + s_hash_seed0 : 32 : littleendian; (* HTREE hash seed *) + s_hash_seed1 : 32 : littleendian; + s_hash_seed2 : 32 : littleendian; + s_hash_seed3 : 32 : littleendian; + s_def_hash_version : 8; (* Default hash version to use *) + 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 *) + s_reserved : 6080 : bitstring -> (* Padding to the end of the block *) -(* Int64 operators for convenience. *) -let (+^) = Int64.add -let (-^) = Int64.sub -let ( *^ ) = Int64.mul -let (/^) = Int64.div - -let sector_size = Virt_df.sector_size -let read_int32_le = Virt_df.read_int32_le - -let probe_ext2 target part_type fd start size = - LargeFile.lseek fd ((start+^2L) *^ sector_size) SEEK_SET; - let str = String.create 128 in - if read fd str 0 128 <> 128 then - failwith (s_ "error reading ext2/ext3 magic") - else ( - if str.[56] != '\x53' || str.[57] != '\xEF' then ( - Virt_df.ProbeFailed (s_ "partition marked EXT2/3 but no valid filesystem") - ) else ( - (* Refer to *) - let s_inodes_count = read_int32_le str 0 in - let s_blocks_count = read_int32_le str 4 in - let s_r_blocks_count = read_int32_le str 8 in - let s_free_blocks_count = read_int32_le str 12 in - let s_free_inodes_count = read_int32_le str 16 in - let s_first_data_block = read_int32_le str 20 in - let s_log_block_size = read_int32_le str 24 in - (*let s_log_frag_size = read_int32_le str 28 in*) - let s_blocks_per_group = read_int32_le str 32 in - - (* Work out the block size in bytes. *) - let s_log_block_size = Int64.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 s_groups_count = - (s_blocks_count -^ s_first_data_block -^ 1L) - /^ s_blocks_per_group +^ 1L 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 s_groups_count = + Int64.of_int32 ( + (s_blocks_count -* s_first_data_block -* 1l) + /* s_blocks_per_group +* 1l + ) in (* (* Number of group descriptors per block. *) @@ -71,30 +107,32 @@ let probe_ext2 target part_type fd start size = /^ s_desc_per_block *) - (* Calculate the block overhead (used by superblocks, inodes, etc.) - * See fs/ext2/super.c. - *) - let overhead = s_first_data_block in - let overhead = (* XXX *) overhead in - - - Virt_df.Filesystem { - Virt_df.fs_name = s_ "Linux ext2/3"; - fs_block_size = block_size; - fs_blocks_total = s_blocks_count -^ overhead; - fs_blocks_reserved = s_r_blocks_count; - fs_blocks_avail = s_free_blocks_count; - fs_blocks_used = s_blocks_count -^ overhead -^ s_free_blocks_count; - fs_inodes_total = s_inodes_count; - fs_inodes_reserved = 0L; (* XXX? *) - fs_inodes_avail = s_free_inodes_count; - fs_inodes_used = s_inodes_count (*-^ 0L*) -^ s_free_inodes_count; - } - ) - ) + (* 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 = (* XXX *) overhead in + + { + fs_name = s_ "Linux ext2/3"; + fs_block_size = block_size; + fs_blocks_total = Int64.of_int32 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_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; + } + + | _ -> + raise Not_found (* Not an EXT2/3 superblock. *) (* Register with main code. *) -let () = - Virt_df.fs_register - [ 0x83 ] (* Partition type. *) - probe_ext2 +let () = filesystem_type_register "ext2" probe_ext2