1 (* 'df' command for virtual domains.
2 (C) Copyright 2007 Richard W.M. Jones, Red Hat Inc.
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.
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.
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.
19 Support for EXT2/EXT3 filesystems.
29 let ( +* ) = Int32.add
30 let ( -* ) = Int32.sub
31 let ( ** ) = Int32.mul
32 let ( /* ) = Int32.div
34 let plugin_id = "ext2"
35 let superblock_offset = ~^1024
36 let superblock_len = ~^1024
39 (* Load the superblock. *)
40 let bits = dev#read_bitstring superblock_offset superblock_len in
42 (* The structure is straight from /usr/include/linux/ext3_fs.h *)
44 | { s_inodes_count : 32 : littleendian; (* Inodes count *)
45 s_blocks_count : 32 : littleendian; (* Blocks count *)
46 s_r_blocks_count : 32 : littleendian; (* Reserved blocks count *)
47 s_free_blocks_count : 32 : littleendian; (* Free blocks count *)
48 s_free_inodes_count : 32 : littleendian; (* Free inodes count *)
49 s_first_data_block : 32 : littleendian; (* First Data Block *)
50 s_log_block_size : 32 : littleendian; (* Block size *)
51 s_log_frag_size : 32 : littleendian; (* Fragment size *)
52 s_blocks_per_group : 32 : littleendian; (* # Blocks per group *)
53 s_frags_per_group : 32 : littleendian; (* # Fragments per group *)
54 s_inodes_per_group : 32 : littleendian; (* # Inodes per group *)
55 s_mtime : 32 : littleendian; (* Mount time *)
56 s_wtime : 32 : littleendian; (* Write time *)
57 s_mnt_count : 16 : littleendian; (* Mount count *)
58 s_max_mnt_count : 16 : littleendian; (* Maximal mount count *)
59 0xef53 : 16 : littleendian; (* Magic signature *)
60 s_state : 16 : littleendian; (* File system state *)
61 s_errors : 16 : littleendian; (* Behaviour when detecting errors *)
62 s_minor_rev_level : 16 : littleendian; (* minor revision level *)
63 s_lastcheck : 32 : littleendian; (* time of last check *)
64 s_checkinterval : 32 : littleendian; (* max. time between checks *)
65 s_creator_os : 32 : littleendian; (* OS *)
66 s_rev_level : 32 : littleendian; (* Revision level *)
67 s_def_resuid : 16 : littleendian; (* Default uid for reserved blocks *)
68 s_def_resgid : 16 : littleendian; (* Default gid for reserved blocks *)
69 s_first_ino : 32 : littleendian; (* First non-reserved inode *)
70 s_inode_size : 16 : littleendian; (* size of inode structure *)
71 s_block_group_nr : 16 : littleendian; (* block group # of this superblock *)
72 s_feature_compat : 32 : littleendian; (* compatible feature set *)
73 s_feature_incompat : 32 : littleendian; (* incompatible feature set *)
74 s_feature_ro_compat : 32 : littleendian; (* readonly-compatible feature set *)
75 s_uuid : 128 : string; (* 128-bit uuid for volume *)
76 s_volume_name : 128 : string; (* volume name *)
77 s_last_mounted : 512 : string; (* directory where last mounted *)
78 s_algorithm_usage_bitmap : 32 : littleendian; (* For compression *)
79 s_prealloc_blocks : 8; (* Nr of blocks to try to preallocate*)
80 s_prealloc_dir_blocks : 8; (* Nr to preallocate for dirs *)
81 s_reserved_gdt_blocks : 16 : littleendian;(* Per group desc for online growth *)
82 s_journal_uuid : 128 : string; (* uuid of journal superblock *)
83 s_journal_inum : 32 : littleendian; (* inode number of journal file *)
84 s_journal_dev : 32 : littleendian; (* device number of journal file *)
85 s_last_orphan : 32 : littleendian; (* start of list of inodes to delete *)
86 s_hash_seed0 : 32 : littleendian; (* HTREE hash seed *)
87 s_hash_seed1 : 32 : littleendian;
88 s_hash_seed2 : 32 : littleendian;
89 s_hash_seed3 : 32 : littleendian;
90 s_def_hash_version : 8; (* Default hash version to use *)
91 s_reserved_char_pad : 8;
92 s_reserved_word_pad : 16 : littleendian;
93 s_default_mount_opts : 32 : littleendian;
94 s_first_meta_bg : 32 : littleendian; (* First metablock block group *)
95 _ : 6080 : bitstring } -> (* Padding to the end of the block *)
97 (* Work out the block size in bytes. *)
98 let s_log_block_size = Int32.to_int s_log_block_size in
99 let block_size = ~^1024 <^< s_log_block_size in
101 (* Number of groups. *)
104 (s_blocks_count -* s_first_data_block -* 1l)
105 /* s_blocks_per_group +* 1l
109 (* Number of group descriptors per block. *)
110 let s_inodes_per_block = s_blocksize /
111 let s_desc_per_block = block_size / s_inodes_per_block in
113 (s_groups_count +^ s_desc_per_block -^ 1L)
117 (* Calculate the block overhead (used by superblocks, inodes, etc.)
118 * See fs/ext2/super.c.
120 let overhead = Int63.of_int32 s_first_data_block in
121 let overhead = (* XXX *) overhead in
123 (* The blocksize of the filesystem is likely to be quite different
124 * from that of the underlying device, so create an overlay device
125 * with the natural filesystem blocksize.
127 let fs_dev = new blocksize_overlay block_size dev in
130 fs_plugin_id = plugin_id;
133 fs_blocksize = block_size;
134 fs_blocks_total = Int63.of_int32 s_blocks_count -^ overhead;
138 fs_blocks_reserved = Int63.of_int32 s_r_blocks_count;
139 fs_blocks_avail = Int63.of_int32 s_free_blocks_count;
141 Int63.of_int32 s_blocks_count -^ overhead
142 -^ Int63.of_int32 s_free_blocks_count;
143 fs_inodes_total = Int63.of_int32 s_inodes_count;
144 fs_inodes_reserved = ~^0; (* XXX? *)
145 fs_inodes_avail = Int63.of_int32 s_free_inodes_count;
146 fs_inodes_used = Int63.of_int32 s_inodes_count
148 -^ Int63.of_int32 s_free_inodes_count;
152 raise Not_found (* Not an EXT2/3 superblock. *)
154 let offset_is_free _ _ = false
158 fs_cb_offset_is_free = offset_is_free;