]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd_recover_tool/metadata_h
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / tools / rbd_recover_tool / metadata_h
1 #!/bin/bash
2 # file: metadata_h
3 #
4 # Copyright (C) 2015 Ubuntu Kylin
5 #
6 # Author: Min Chen <minchen@ubuntukylin.com>
7 #
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU Library Public License as published by
10 # the Free Software Foundation; either version 2, or (at your option)
11 # any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU Library Public License for more details.
17 #
18
19 my_dir=$(dirname "$0")
20 . $my_dir/common_h
21 . $my_dir/epoch_h
22
23 # put origin name in $image_name_in: for output
24 # put convert "_" name in $image_name: for grep image hobjects from database
25 image_name_in=
26 image_name=
27 function input_image()
28 {
29 local func="input_image"
30 if [ "$1"x = ""x ];then
31 echo "$func: no image name input"
32 exit
33 fi
34
35 image_name_in=$1
36 # "_" -> "\u"
37 image_name=`convert_underline $image_name_in`
38 }
39
40 #======================================== distinguish v1 or v2 ===================================
41 #image_list_v1=$single_node/$cluster-$id/image_list_v1
42 #image_list_v2=$single_node/$cluster-$id/image_list_v2
43 function get_image_list()
44 {
45 find $osd_data/current/ -type f|grep ".rbd__" >$image_list_v1
46 find $osd_data/current/ -type f|grep "rbd\\\\uid." >$image_list_v2
47 }
48
49 function get_image_format_by_hobject()
50 {
51 local func="get_image_format"
52 if [ "$1"x = ""x ];then
53 exit
54 fi
55 local res1=`cat $image_list_v1|grep $1`
56 if [ "$res1"x != ""x ];then
57 echo 1
58 exit
59 fi
60
61 local res2=`cat $image_list_v2|grep $1`
62 if [ "$res2"x = ""x ];then
63 echo 2
64 exit
65 fi
66 }
67
68 #======================================== image format v1 ========================================
69 # <image_name>.rbd inlude 3 parts:
70 # header + snap_count*snapshot + snap_count*snap_name
71 #
72 # struct rbd_obj_header_ondisk {
73 # 40 char text[40];
74 # 24 char block_name[RBD_MAX_BLOCK_NAME_SIZE];
75 # 4 char signature[4];
76 # 8 char version[8];
77 # struct {
78 # 1 __u8 order;
79 # 1 __u8 crypt_type;
80 # 1 __u8 comp_type;
81 # 1 __u8 unused;
82 # } __attribute__((packed)) options;
83 # 8 __le64 image_size;//hexdump -C s=80 n=8
84 # 8 __le64 snap_seq; //hexdump -C s=88 n=8
85 # 4 __le32 snap_count;//hexdump -C s=96 n=4
86 # 4 __le32 reserved;
87 # 8 __le64 snap_names_len;//hexdump -C s=104 n=8
88 # struct rbd_obj_snap_ondisk snaps[0];
89 # } __attribute__((packed));
90 #
91 # sizeof(rbd_obj_header_ondisk): 112
92 #
93 # struct rbd_obj_snap_ondisk {
94 # 8 __le64 id; //hexdump -C s=112+i*16 n=8 , i=[0, snap_count)
95 # 8 __le64 image_size;//hexdump -C s=112+i*16+8 n=8, i=[0, snap_count)
96 # } __attribute__((packed));
97 # sizeof(rbd_obj_snap_ondisk): 16
98 #
99 # get snap_names form <image_nane>.rbd
100 # hexdump -e '10/1 "%_c"' -s $((112 + $snap_count*16)) -n $snap_names_len <image_name>.rbd
101 # then split snap_names into array
102
103 function get_image_metadata_v1()
104 {
105 local func="get_image_metadata_v1"
106 if [ "$1"x = ""x ];then
107 echo "$func: no image head object input"
108 exit
109 fi
110 local snap_name=
111 if [ "$2"x != ""x ];then
112 snap_name=$2
113 fi
114
115 if [ ! -e $1 ];then
116 echo "$func: $1 not exists"
117 exit
118 fi
119 local hobject_path=$1
120 d_hobject_path=`dump_backslash $1`
121 local image_format=`get_image_format_by_hobject $d_hobject_path`
122 if [ $image_format != 1 ];then
123 echo "$func: image_format must be 1"
124 exit
125 fi
126
127 if [ ! -e $hobject_path ];then
128 echo "$func: $hobject_path not exists"
129 exit
130 fi
131
132 # decode rbd_obj_header_ondisk of <image_name>.rbd
133 local block_name=`hexdump -e '10/1 "%c"' -s 40 -n 24 $hobject_path`
134 local order=`hexdump -e '10/4 "%u"' -s 76 -n 1 $hobject_path`
135 local image_size=`hexdump -C -s 80 -n 8 $hobject_path|head -n 1|awk '{for (i=9; i>1; i--) {printf $i}}'`
136 image_size=$((16#$image_size))
137 local snap_seq=`hexdump -C -s 88 -n 8 $hobject_path|head -n 1|
138 awk '{num=""; for(i=9; i>1; i--){ num=num""$i;} print strtonum("0x"num);}'`
139 local snap_count=`hexdump -C -s 96 -n 4 $hobject_path|head -n 1|
140 awk '{num=""; for(i=5; i>1; i--){ num=num""$i;} print strtonum("0x"num);}'`
141 local snap_names_len=`hexdump -C -s 104 -n 8 $hobject_path|head -n 1|
142 awk '{num=""; for(i=9; i>1; i--){ num=num""$i;} print strtonum("0x"num);}'`
143
144 echo -e "block_name:\t$block_name"
145 echo -e "order:\t\t$order"
146 echo -e "image_size:\t$image_size"
147 echo -e "snap_seq:\t$snap_seq"
148
149 # decode N rbd_obj_snap_ondisk of <image_name>.rbd
150 declare -a snap_ids
151 declare -a snap_names
152 declare -a snap_image_sizes
153 local size_header=112 #sizeof(rbd_obj_header_ondisk)
154 local size_snap=16 #sizeof(rbd_obj_snap_ondisk)
155 local offset=0
156 local id_off=0
157 local size_off=0
158 for ((i=0; i<$snap_count; i++))
159 do
160 offset=$(($size_header + $i * $size_snap))
161 id_off=$offset
162 size_off=$(($offset + 8))
163 snap_ids[$i]=`hexdump -C -s $id_off -n 8 $hobject_path|head -n 1|
164 awk '{num=""; for(i=9; i>1; i--){num=num""$i;} print strtonum("0x"num);}'`
165 snap_image_sizes[$i]=`hexdump -C -s $size_off -n 8 $hobject_path|head -n 1|
166 awk '{num=""; for(i=9; i>1; i--){num=num""$i;} print strtonum("0x"num);}'`
167 done
168 offset=$(($size_header + $snap_count * $size_snap))
169 snap_names=(`hexdump -e '10/1 "%_c"' -s $offset -n $snap_names_len $hobject_path|
170 awk -F "\\\\\\\\\\\\\\\\0" '{for(i=1; i<=NF; i++) {print $i" "} }'`);
171
172 echo -e "\t\tID\tNAME\t\tSIZE"
173 for ((i=0; i<$snap_count; i++))
174 do
175 if [ "$snap_name"x = ""x ];then
176 echo -n -e "snapshot:\t"
177 echo -e "${snap_ids[$i]}\t${snap_names[$i]}\t\t${snap_image_sizes[$i]}"
178 continue
179 fi
180 if [ "$snap_name"x = "${snap_names[$i]}"x ];then
181 echo -n -e "snapshot:\t"
182 echo -e "${snap_ids[$i]}\t${snap_names[$i]}\t\t${snap_image_sizes[$i]}"
183 return
184 fi
185 done
186 }
187
188 #======================================== end image format v1 ========================================
189
190 #======================================== image format v2 ========================================
191
192 # map_header, header_seq, header, key/value
193 # eg.
194 # map_header _HOBJTOSEQ_:rbd%uheader%e139a6b8b4567...head.2.68E826B6
195 # meta_header_seq 17426
196 # header: _USER_0000000000017426_USER_:object_prefix
197 # _USER_0000000000017426_USER_:order
198 # _USER_0000000000017426_USER_:size
199 # _USER_0000000000017426_USER_:snap_seq
200 # key/value ceph-kvstore-tool /storepath get _USER_0000000000017426_USER_ (object_prefix|order|size|snap_seq)
201
202 # decode image id from image_id_hobject
203 function get_image_id()
204 {
205 local func="get_image_id"
206 if [ "$1"x = ""x ];then
207 exit;
208 fi
209 local image_id_hobject=$1 #from admin node's database
210
211 if [ ! -e $image_id_hobject ];then
212 #echo "$func: $image_id_hobject not exists"
213 exit;
214 fi
215
216 # get len of string
217 local n=`hexdump -e '10/4 "%u"' -s 0 -n 4 $image_id_hobject`
218 # get string
219 hexdump -e '10/1 "%c"' -s 4 -n $n $image_id_hobject
220 }
221
222 #find image_id omap entry in omaplist
223 map_header_prefix=
224 map_header_key=
225 function get_map_header()
226 {
227 local func="get_map_header"
228 local image_id=$1
229 if [ "$image_id"x = ""x ];then
230 echo "$func: no image_id input"
231 exit;
232 fi
233 map_header_prefix=`get_map_header_prefix`
234 local keyword="header%e"$image_id
235 map_header_key=`get_map_header_key $keyword`
236 if [ "$map_header_key"x = ""x ];then
237 echo "$func: map_header_key is NULL(not in omaplist)"
238 exit
239 fi
240 }
241
242 #get meta header seq from map_header
243 meta_header_seq=
244 function get_meta_header_seq()
245 {
246 local func="get_meta_header_seq"
247 if [ "$1"x == ""x ];then
248 echo "$func: no prefix input"
249 exit;
250 elif [ "$2"x == ""x ];then
251 echo "$func: no key input"
252 exit;
253 fi
254 local prefix=$1;
255 local key=$2;
256 meta_header_seq=`get_header_seq $prefix $key`
257 }
258
259 # get image metadata : object_prefix, order, image_size, snap_seq
260 object_prefix=
261 order=
262 image_size=
263 snap_seq=
264 function get_image_metadata_v2()
265 {
266 local func="get_image_metadata_v2"
267 if [ "$1"x = ""x ];then
268 echo "$func: no meta_header_seq input"
269 exit;
270 fi
271 local meta_header_seq=`printf "%016d" $1`
272 #echo "$func: meta_header_seq = "$meta_header_seq
273 local ghobject_key="_USER_"$meta_header_seq"_USER_"
274 local prefix=$ghobject_key
275
276 object_prefix=`get_header_kv $prefix object_prefix string`
277 #object_prefix="rbd_data.$image_id"
278 order=`get_header_kv $prefix order int`
279 image_size=`get_header_kv $prefix size int`
280 snap_seq=`get_header_kv $prefix snap_seq int`
281
282 echo -e "object_prefix:\t$object_prefix"
283 echo -e "order:\t\t$order"
284 echo -e "image_size:\t$image_size"
285 echo -e "snap_seq:\t$snap_seq"
286
287 # list snapshot
288 list_snaps_v2 $1 $2
289 }
290
291 # struct cls_rbd_snap {
292 # snapid_t id;
293 # string name;
294 # uint64_t image_size;
295 # uint64_t features;
296 # uint8_t protection_status;
297 # cls_rbd_parent parent;
298 # }
299 # decode cls_rbd_snap
300 # 1 u8 struct_v
301 # 1 u8 struct_compat
302 # 4 u32 struct_len
303 # 8 u64 snapid_t id //s=6 n=8
304 # 4 u32 len of name //s=14 n=4
305 # len char name //s=18 n=len
306 # 8 u64 image_size
307 # 8 u64 features
308 # ......
309 #
310 function list_snaps_v2()
311 {
312 local func="list_snaps_v2"
313 if [ "$1"x = ""x ];then
314 exit
315 fi
316 local sname=
317 if [ $# -eq 2 ];then
318 sname=$2
319 fi
320 local meta_header_seq=`printf "%016d" $1`
321 local prefix="_USER_"$meta_header_seq"_USER_"
322 local keys=(`awk -F ":" '/snapshot_/ && $1 == "'"$prefix"'" {if ($2 == "") exit; split($2, arr, "_");
323 print arr[2];}' $omap_list|sort -r`)
324 echo -e "\t\tID\tNAME\t\tSIZE"
325 for key in ${keys[@]}
326 do
327 key="snapshot_$key"
328 local arr=(`ceph-kvstore-tool $omap_path get $prefix $key|awk -F ":" '{print $2}'`);
329 # get snap_name
330 tmp=
331 for ((i=17; i>13; i--))
332 do
333 tmp="$tmp${arr[$i]}"
334 done
335 local len=$((16#$tmp))
336 local snap_name=
337 for ((i=18; i<$((18+$len)); i++))
338 do
339 # convert ascii to char
340 local char=`echo -e "\x${arr[$i]}"`
341 snap_name="$snap_name$char"
342 done
343 # get snap_id (little endian)
344 local tmp=
345 for ((i=13; i>5; i--))
346 do
347 tmp="$tmp${arr[$i]}"
348 done
349 local snap_id=$((16#$tmp))
350 # get image_size of current snap (little endian)
351 tmp=
352 for ((i=$((25+$len)); i>$((17+$len)); i--))
353 do
354 tmp="$tmp${arr[$i]}"
355 done
356 local image_size=$((16#$tmp))
357 if [ "$sname"x = ""x ];then
358 echo -e "snapshot:\t$snap_id\t$snap_name\t\t$image_size"
359 continue
360 fi
361 if [ "$sname"x = "$snap_name"x ];then
362 echo -e "snapshot:\t$snap_id\t$snap_name\t\t$image_size"
363 return
364 fi
365 done
366 }
367
368 #======================================== end image format v2 ========================================