Metadata parser.
[virt-top.git] / virt-df / virt_df_ext2.ml
1 (* 'df' command for virtual domains.
2    (C) Copyright 2007 Richard W.M. Jones, Red Hat Inc.
3    http://libvirt.org/
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19    Support for EXT2/EXT3 filesystems.
20 *)
21
22 open Unix
23 open Printf
24
25 open Virt_df_gettext.Gettext
26 open Virt_df
27
28 let superblock_offset = 1024L
29
30 let probe_ext2 dev =
31   (* Load the superblock. *)
32   let bits = dev#read_bitstring superblock_offset 1024 in
33
34   (* The structure is straight from /usr/include/linux/ext3_fs.h *)
35   bitmatch bits with
36   | s_inodes_count : 32 : littleendian;         (* Inodes count *)
37     s_blocks_count : 32 : littleendian;         (* Blocks count *)
38     s_r_blocks_count : 32 : littleendian;       (* Reserved blocks count *)
39     s_free_blocks_count : 32 : littleendian;    (* Free blocks count *)
40     s_free_inodes_count : 32 : littleendian;    (* Free inodes count *)
41     s_first_data_block : 32 : littleendian;     (* First Data Block *)
42     s_log_block_size : 32 : littleendian;       (* Block size *)
43     s_log_frag_size : 32 : littleendian;        (* Fragment size *)
44     s_blocks_per_group : 32 : littleendian;     (* # Blocks per group *)
45     s_frags_per_group : 32 : littleendian;      (* # Fragments per group *)
46     s_inodes_per_group : 32 : littleendian;     (* # Inodes per group *)
47     s_mtime : 32 : littleendian;                (* Mount time *)
48     s_wtime : 32 : littleendian;                (* Write time *)
49     s_mnt_count : 16 : littleendian;            (* Mount count *)
50     s_max_mnt_count : 16 : littleendian;        (* Maximal mount count *)
51     0xef53 : 16 : littleendian;                 (* Magic signature *)
52     s_state : 16 : littleendian;                (* File system state *)
53     s_errors : 16 : littleendian;               (* Behaviour when detecting errors *)
54     s_minor_rev_level : 16 : littleendian;      (* minor revision level *)
55     s_lastcheck : 32 : littleendian;            (* time of last check *)
56     s_checkinterval : 32 : littleendian;        (* max. time between checks *)
57     s_creator_os : 32 : littleendian;           (* OS *)
58     s_rev_level : 32 : littleendian;            (* Revision level *)
59     s_def_resuid : 16 : littleendian;           (* Default uid for reserved blocks *)
60     s_def_resgid : 16 : littleendian;           (* Default gid for reserved blocks *)
61     s_first_ino : 32 : littleendian;            (* First non-reserved inode *)
62     s_inode_size : 16 : littleendian;           (* size of inode structure *)
63     s_block_group_nr : 16 : littleendian;       (* block group # of this superblock *)
64     s_feature_compat : 32 : littleendian;       (* compatible feature set *)
65     s_feature_incompat : 32 : littleendian;     (* incompatible feature set *)
66     s_feature_ro_compat : 32 : littleendian;    (* readonly-compatible feature set *)
67     s_uuid : 128 : bitstring;                   (* 128-bit uuid for volume *)
68     s_volume_name : 128 : bitstring;            (* volume name XXX string *)
69     s_last_mounted : 512 : bitstring;           (* directory where last mounted XXX string *)
70     s_algorithm_usage_bitmap : 32 : littleendian; (* For compression *)
71     s_prealloc_blocks : 8;                      (* Nr of blocks to try to preallocate*)
72     s_prealloc_dir_blocks : 8;                  (* Nr to preallocate for dirs *)
73     s_reserved_gdt_blocks : 16 : littleendian;  (* Per group desc for online growth *)
74     s_journal_uuid : 128 : bitstring;           (* uuid of journal superblock *)
75     s_journal_inum : 32 : littleendian;         (* inode number of journal file *)
76     s_journal_dev : 32 : littleendian;          (* device number of journal file *)
77     s_last_orphan : 32 : littleendian;          (* start of list of inodes to delete *)
78     s_hash_seed0 : 32 : littleendian;           (* HTREE hash seed *)
79     s_hash_seed1 : 32 : littleendian;
80     s_hash_seed2 : 32 : littleendian;
81     s_hash_seed3 : 32 : littleendian;
82     s_def_hash_version : 8;                     (* Default hash version to use *)
83     s_reserved_char_pad : 8;
84     s_reserved_word_pad : 16 : littleendian;
85     s_default_mount_opts : 32 : littleendian;
86     s_first_meta_bg : 32 : littleendian;        (* First metablock block group *)
87     s_reserved : 6080 : bitstring ->            (* Padding to the end of the block *)
88
89    (* Work out the block size in bytes. *)
90    let s_log_block_size = Int32.to_int s_log_block_size in
91    let block_size = 1024L in
92    let block_size = Int64.shift_left block_size s_log_block_size in
93
94    (* Number of groups. *)
95    let s_groups_count =
96      Int64.of_int32 (
97        (s_blocks_count -* s_first_data_block -* 1l)
98        /* s_blocks_per_group +* 1l
99      ) in
100
101 (*
102       (* Number of group descriptors per block. *)
103       let s_inodes_per_block = s_blocksize / 
104         let s_desc_per_block = block_size / s_inodes_per_block in
105         let db_count =
106           (s_groups_count +^ s_desc_per_block -^ 1L)
107           /^ s_desc_per_block
108 *)
109
110    (* Calculate the block overhead (used by superblocks, inodes, etc.)
111     * See fs/ext2/super.c.
112     *)
113    let overhead = Int64.of_int32 s_first_data_block in
114    let overhead = (* XXX *) overhead in
115
116    {
117      fs_name = s_ "Linux ext2/3";
118      fs_block_size = block_size;
119      fs_blocks_total = Int64.of_int32 s_blocks_count -^ overhead;
120      fs_is_swap = false;
121      fs_blocks_reserved = Int64.of_int32 s_r_blocks_count;
122      fs_blocks_avail = Int64.of_int32 s_free_blocks_count;
123      fs_blocks_used =
124        Int64.of_int32 s_blocks_count -^ overhead
125        -^ Int64.of_int32 s_free_blocks_count;
126      fs_inodes_total = Int64.of_int32 s_inodes_count;
127      fs_inodes_reserved = 0L;   (* XXX? *)
128      fs_inodes_avail = Int64.of_int32 s_free_inodes_count;
129      fs_inodes_used = Int64.of_int32 s_inodes_count
130        (*-^ 0L*)
131        -^ Int64.of_int32 s_free_inodes_count;
132    }
133
134   | _ ->
135       raise Not_found                   (* Not an EXT2/3 superblock. *)
136
137 (* Register with main code. *)
138 let () = filesystem_type_register "ext2" probe_ext2