Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / qa / standalone / scrub / osd-scrub-repair.sh
1 #!/bin/bash -x
2 #
3 # Copyright (C) 2014 Red Hat <contact@redhat.com>
4 #
5 # Author: Loic Dachary <loic@dachary.org>
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU Library Public License as published by
9 # the Free Software Foundation; either version 2, or (at your option)
10 # any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU Library Public License for more details.
16 #
17 source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
18
19 if [ `uname` = FreeBSD ]; then
20     # erasure coding overwrites are only tested on Bluestore
21     # erasure coding on filestore is unsafe
22     # http://docs.ceph.com/docs/master/rados/operations/erasure-code/#erasure-coding-with-overwrites
23     use_ec_overwrite=false
24 else
25     use_ec_overwrite=true
26 fi
27
28 # Test development and debugging
29 # Set to "yes" in order to ignore diff errors and save results to update test
30 getjson="no"
31
32 # Ignore the epoch and filter out the attr '_' value because it has date information and won't match
33 if [ "$(jq --version 2>&1 | awk '{ print $3}')" = "1.3" ]; then # Not sure all versions that apply here
34     jqfilter='.inconsistents | (.[].shards[].attrs[] | select(.name == "_") | .value) |= "----Stripped-by-test----"'
35 else
36     jqfilter='.inconsistents | (.[].shards[].attrs[]? | select(.name == "_") | .value) |= "----Stripped-by-test----"'
37 fi
38 sortkeys='import json; import sys ; JSON=sys.stdin.read() ; ud = json.loads(JSON) ; print json.dumps(ud, sort_keys=True, indent=2)'
39
40 # Remove items are not consistent across runs, the pg interval and client
41 sedfilter='s/\([ ]*\"\(selected_\)*object_info\":.*head[(]\)[^[:space:]]* [^[:space:]]* \(.*\)/\1\3/'
42
43 function run() {
44     local dir=$1
45     shift
46
47     export CEPH_MON="127.0.0.1:7107" # git grep '\<7107\>' : there must be only one
48     export CEPH_ARGS
49     CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
50     CEPH_ARGS+="--mon-host=$CEPH_MON "
51
52     local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
53     for func in $funcs ; do
54         $func $dir || return 1
55     done
56 }
57
58 function add_something() {
59     local dir=$1
60     local poolname=$2
61     local obj=${3:-SOMETHING}
62     local scrub=${4:-noscrub}
63
64     if [ "$scrub" = "noscrub" ];
65     then
66         ceph osd set noscrub || return 1
67         ceph osd set nodeep-scrub || return 1
68     else
69         ceph osd unset noscrub || return 1
70         ceph osd unset nodeep-scrub || return 1
71     fi
72
73     local payload=ABCDEF
74     echo $payload > $dir/ORIGINAL
75     rados --pool $poolname put $obj $dir/ORIGINAL || return 1
76 }
77
78 #
79 # Corrupt one copy of a replicated pool
80 #
81 function TEST_corrupt_and_repair_replicated() {
82     local dir=$1
83     local poolname=rbd
84
85     setup $dir || return 1
86     run_mon $dir a --osd_pool_default_size=2 || return 1
87     run_mgr $dir x || return 1
88     run_osd $dir 0 || return 1
89     run_osd $dir 1 || return 1
90     create_rbd_pool || return 1
91     wait_for_clean || return 1
92
93     add_something $dir $poolname || return 1
94     corrupt_and_repair_one $dir $poolname $(get_not_primary $poolname SOMETHING) || return 1
95     # Reproduces http://tracker.ceph.com/issues/8914
96     corrupt_and_repair_one $dir $poolname $(get_primary $poolname SOMETHING) || return 1
97
98     teardown $dir || return 1
99 }
100
101 function corrupt_and_repair_two() {
102     local dir=$1
103     local poolname=$2
104     local first=$3
105     local second=$4
106
107     #
108     # 1) remove the corresponding file from the OSDs
109     #
110     pids=""
111     run_in_background pids objectstore_tool $dir $first SOMETHING remove
112     run_in_background pids objectstore_tool $dir $second SOMETHING remove
113     wait_background pids
114     return_code=$?
115     if [ $return_code -ne 0 ]; then return $return_code; fi
116
117     #
118     # 2) repair the PG
119     #
120     local pg=$(get_pg $poolname SOMETHING)
121     repair $pg
122     #
123     # 3) The files must be back
124     #
125     pids=""
126     run_in_background pids objectstore_tool $dir $first SOMETHING list-attrs
127     run_in_background pids objectstore_tool $dir $second SOMETHING list-attrs
128     wait_background pids
129     return_code=$?
130     if [ $return_code -ne 0 ]; then return $return_code; fi
131
132     rados --pool $poolname get SOMETHING $dir/COPY || return 1
133     diff $dir/ORIGINAL $dir/COPY || return 1
134 }
135
136 #
137 # 1) add an object
138 # 2) remove the corresponding file from a designated OSD
139 # 3) repair the PG
140 # 4) check that the file has been restored in the designated OSD
141 #
142 function corrupt_and_repair_one() {
143     local dir=$1
144     local poolname=$2
145     local osd=$3
146
147     #
148     # 1) remove the corresponding file from the OSD
149     #
150     objectstore_tool $dir $osd SOMETHING remove || return 1
151     #
152     # 2) repair the PG
153     #
154     local pg=$(get_pg $poolname SOMETHING)
155     repair $pg
156     #
157     # 3) The file must be back
158     #
159     objectstore_tool $dir $osd SOMETHING list-attrs || return 1
160     rados --pool $poolname get SOMETHING $dir/COPY || return 1
161     diff $dir/ORIGINAL $dir/COPY || return 1
162 }
163
164 function corrupt_and_repair_erasure_coded() {
165     local dir=$1
166     local poolname=$2
167
168     add_something $dir $poolname || return 1
169
170     local primary=$(get_primary $poolname SOMETHING)
171     local -a osds=($(get_osds $poolname SOMETHING | sed -e "s/$primary//"))
172     local not_primary_first=${osds[0]}
173     local not_primary_second=${osds[1]}
174
175     # Reproduces http://tracker.ceph.com/issues/10017
176     corrupt_and_repair_one $dir $poolname $primary  || return 1
177     # Reproduces http://tracker.ceph.com/issues/10409
178     corrupt_and_repair_one $dir $poolname $not_primary_first || return 1
179     corrupt_and_repair_two $dir $poolname $not_primary_first $not_primary_second || return 1
180     corrupt_and_repair_two $dir $poolname $primary $not_primary_first || return 1
181
182 }
183
184 function create_ec_pool() {
185     local pool_name=$1
186     local allow_overwrites=$2
187
188     ceph osd erasure-code-profile set myprofile crush-failure-domain=osd $3 $4 $5 $6 $7 || return 1
189
190     create_pool "$poolname" 1 1 erasure myprofile || return 1
191
192     if [ "$allow_overwrites" = "true" ]; then
193         ceph osd pool set "$poolname" allow_ec_overwrites true || return 1
194     fi
195
196     wait_for_clean || return 1
197     return 0
198 }
199
200 function auto_repair_erasure_coded() {
201     local dir=$1
202     local allow_overwrites=$2
203     local poolname=ecpool
204
205     # Launch a cluster with 5 seconds scrub interval
206     setup $dir || return 1
207     run_mon $dir a || return 1
208     run_mgr $dir x || return 1
209     local ceph_osd_args="--osd-scrub-auto-repair=true \
210             --osd-deep-scrub-interval=5 \
211             --osd-scrub-max-interval=5 \
212             --osd-scrub-min-interval=5 \
213             --osd-scrub-interval-randomize-ratio=0"
214     for id in $(seq 0 2) ; do
215         if [ "$allow_overwrites" = "true" ]; then
216             run_osd_bluestore $dir $id $ceph_osd_args || return 1
217         else
218             run_osd $dir $id $ceph_osd_args || return 1
219         fi
220     done
221     create_rbd_pool || return 1
222     wait_for_clean || return 1
223
224     # Create an EC pool
225     create_ec_pool $poolname $allow_overwrites k=2 m=1 || return 1
226
227     # Put an object
228     local payload=ABCDEF
229     echo $payload > $dir/ORIGINAL
230     rados --pool $poolname put SOMETHING $dir/ORIGINAL || return 1
231
232     # Remove the object from one shard physically
233     # Restarted osd get $ceph_osd_args passed
234     objectstore_tool $dir $(get_not_primary $poolname SOMETHING) SOMETHING remove || return 1
235     # Wait for auto repair
236     local pgid=$(get_pg $poolname SOMETHING)
237     wait_for_scrub $pgid "$(get_last_scrub_stamp $pgid)"
238     wait_for_clean || return 1
239     # Verify - the file should be back
240     # Restarted osd get $ceph_osd_args passed
241     objectstore_tool $dir $(get_not_primary $poolname SOMETHING) SOMETHING list-attrs || return 1
242     rados --pool $poolname get SOMETHING $dir/COPY || return 1
243     diff $dir/ORIGINAL $dir/COPY || return 1
244
245     # Tear down
246     teardown $dir || return 1
247 }
248
249 function TEST_auto_repair_erasure_coded_appends() {
250     auto_repair_erasure_coded $1 false
251 }
252
253 function TEST_auto_repair_erasure_coded_overwrites() {
254     if [ "$use_ec_overwrite" = "true" ]; then
255         auto_repair_erasure_coded $1 true
256     fi
257 }
258
259 function corrupt_and_repair_jerasure() {
260     local dir=$1
261     local allow_overwrites=$2
262     local poolname=ecpool
263
264     setup $dir || return 1
265     run_mon $dir a || return 1
266     run_mgr $dir x || return 1
267     for id in $(seq 0 3) ; do
268         if [ "$allow_overwrites" = "true" ]; then
269             run_osd_bluestore $dir $id || return 1
270         else
271             run_osd $dir $id || return 1
272         fi
273     done
274     create_rbd_pool || return 1
275     wait_for_clean || return 1
276
277     create_ec_pool $poolname $allow_overwrites k=2 m=2 || return 1
278     corrupt_and_repair_erasure_coded $dir $poolname || return 1
279
280     teardown $dir || return 1
281 }
282
283 function TEST_corrupt_and_repair_jerasure_appends() {
284     corrupt_and_repair_jerasure $1
285 }
286
287 function TEST_corrupt_and_repair_jerasure_overwrites() {
288     if [ "$use_ec_overwrite" = "true" ]; then
289         corrupt_and_repair_jerasure $1 true
290     fi
291 }
292
293 function corrupt_and_repair_lrc() {
294     local dir=$1
295     local allow_overwrites=$2
296     local poolname=ecpool
297
298     setup $dir || return 1
299     run_mon $dir a || return 1
300     run_mgr $dir x || return 1
301     for id in $(seq 0 9) ; do
302         if [ "$allow_overwrites" = "true" ]; then
303             run_osd_bluestore $dir $id || return 1
304         else
305             run_osd $dir $id || return 1
306         fi
307     done
308     create_rbd_pool || return 1
309     wait_for_clean || return 1
310
311     create_ec_pool $poolname $allow_overwrites k=4 m=2 l=3 plugin=lrc || return 1
312     corrupt_and_repair_erasure_coded $dir $poolname || return 1
313
314     teardown $dir || return 1
315 }
316
317 function TEST_corrupt_and_repair_lrc_appends() {
318     corrupt_and_repair_jerasure $1
319 }
320
321 function TEST_corrupt_and_repair_lrc_overwrites() {
322     if [ "$use_ec_overwrite" = "true" ]; then
323         corrupt_and_repair_jerasure $1 true
324     fi
325 }
326
327 function unfound_erasure_coded() {
328     local dir=$1
329     local allow_overwrites=$2
330     local poolname=ecpool
331     local payload=ABCDEF
332
333     setup $dir || return 1
334     run_mon $dir a || return 1
335     run_mgr $dir x || return 1
336     for id in $(seq 0 3) ; do
337         if [ "$allow_overwrites" = "true" ]; then
338             run_osd_bluestore $dir $id || return 1
339         else
340             run_osd $dir $id || return 1
341         fi
342     done
343     create_rbd_pool || return 1
344     wait_for_clean || return 1
345
346     create_ec_pool $poolname $allow_overwrites k=2 m=2 || return 1
347
348     add_something $dir $poolname || return 1
349
350     local primary=$(get_primary $poolname SOMETHING)
351     local -a osds=($(get_osds $poolname SOMETHING | sed -e "s/$primary//"))
352     local not_primary_first=${osds[0]}
353     local not_primary_second=${osds[1]}
354     local not_primary_third=${osds[2]}
355
356     #
357     # 1) remove the corresponding file from the OSDs
358     #
359     pids=""
360     run_in_background pids objectstore_tool $dir $not_primary_first SOMETHING remove
361     run_in_background pids objectstore_tool $dir $not_primary_second SOMETHING remove
362     run_in_background pids objectstore_tool $dir $not_primary_third SOMETHING remove
363     wait_background pids
364     return_code=$?
365     if [ $return_code -ne 0 ]; then return $return_code; fi
366
367     #
368     # 2) repair the PG
369     #
370     local pg=$(get_pg $poolname SOMETHING)
371     repair $pg
372     #
373     # 3) check pg state
374     #
375     # it may take a bit to appear due to mon/mgr asynchrony
376     for f in `seq 1 60`; do
377         ceph -s | grep "1/1 objects unfound" && break
378         sleep 1
379     done
380     ceph -s|grep "4 osds: 4 up, 4 in" || return 1
381     ceph -s|grep "1/1 objects unfound" || return 1
382
383     teardown $dir || return 1
384 }
385
386 function TEST_unfound_erasure_coded_appends() {
387     unfound_erasure_coded $1
388 }
389
390 function TEST_unfound_erasure_coded_overwrites() {
391     if [ "$use_ec_overwrite" = "true" ]; then
392         unfound_erasure_coded $1 true
393     fi
394 }
395
396 #
397 # list_missing for EC pool
398 #
399 function list_missing_erasure_coded() {
400     local dir=$1
401     local allow_overwrites=$2
402     local poolname=ecpool
403
404     setup $dir || return 1
405     run_mon $dir a || return 1
406     run_mgr $dir x || return 1
407     for id in $(seq 0 2) ; do
408         if [ "$allow_overwrites" = "true" ]; then
409             run_osd_bluestore $dir $id || return 1
410         else
411             run_osd $dir $id || return 1
412         fi
413     done
414     create_rbd_pool || return 1
415     wait_for_clean || return 1
416
417     create_ec_pool $poolname $allow_overwrites k=2 m=1 || return 1
418
419     # Put an object and remove the two shards (including primary)
420     add_something $dir $poolname MOBJ0 || return 1
421     local -a osds0=($(get_osds $poolname MOBJ0))
422
423     # Put another object and remove two shards (excluding primary)
424     add_something $dir $poolname MOBJ1 || return 1
425     local -a osds1=($(get_osds $poolname MOBJ1))
426
427     # Stop all osd daemons
428     for id in $(seq 0 2) ; do
429         kill_daemons $dir TERM osd.$id >&2 < /dev/null || return 1
430     done
431
432     id=${osds0[0]}
433     ceph-objectstore-tool --data-path $dir/$id \
434         MOBJ0 remove || return 1
435     id=${osds0[1]}
436     ceph-objectstore-tool --data-path $dir/$id \
437         MOBJ0 remove || return 1
438
439     id=${osds1[1]}
440     ceph-objectstore-tool --data-path $dir/$id \
441         MOBJ1 remove || return 1
442     id=${osds1[2]}
443     ceph-objectstore-tool --data-path $dir/$id \
444         MOBJ1 remove || return 1
445
446     for id in $(seq 0 2) ; do
447         activate_osd $dir $id >&2 || return 1
448     done
449     create_rbd_pool || return 1
450     wait_for_clean || return 1
451
452     # Get get - both objects should in the same PG
453     local pg=$(get_pg $poolname MOBJ0)
454
455     # Repair the PG, which triggers the recovering,
456     # and should mark the object as unfound
457     repair $pg
458
459     for i in $(seq 0 120) ; do
460         [ $i -lt 60 ] || return 1
461         matches=$(ceph pg $pg list_missing | egrep "MOBJ0|MOBJ1" | wc -l)
462         [ $matches -eq 2 ] && break
463     done
464
465     teardown $dir || return 1
466 }
467
468 function TEST_list_missing_erasure_coded_appends() {
469     list_missing_erasure_coded $1 false
470 }
471
472 function TEST_list_missing_erasure_coded_overwrites() {
473     if [ "$use_ec_overwrite" = "true" ]; then
474         list_missing_erasure_coded $1 true
475     fi
476 }
477
478 #
479 # Corrupt one copy of a replicated pool
480 #
481 function TEST_corrupt_scrub_replicated() {
482     local dir=$1
483     local poolname=csr_pool
484     local total_objs=16
485
486     setup $dir || return 1
487     run_mon $dir a --osd_pool_default_size=2 || return 1
488     run_mgr $dir x || return 1
489     run_osd $dir 0 || return 1
490     run_osd $dir 1 || return 1
491     create_rbd_pool || return 1
492     wait_for_clean || return 1
493
494     create_pool foo 1 || return 1
495     create_pool $poolname 1 1 || return 1
496     wait_for_clean || return 1
497
498     for i in $(seq 1 $total_objs) ; do
499         objname=ROBJ${i}
500         add_something $dir $poolname $objname || return 1
501
502         rados --pool $poolname setomapheader $objname hdr-$objname || return 1
503         rados --pool $poolname setomapval $objname key-$objname val-$objname || return 1
504     done
505
506     local pg=$(get_pg $poolname ROBJ0)
507
508     # Compute an old omap digest and save oi
509     CEPH_ARGS='' ceph daemon $(get_asok_path osd.0) \
510         config set osd_deep_scrub_update_digest_min_age 0
511     CEPH_ARGS='' ceph daemon $(get_asok_path osd.1) \
512         config set osd_deep_scrub_update_digest_min_age 0
513     pg_deep_scrub $pg
514
515     for i in $(seq 1 $total_objs) ; do
516         objname=ROBJ${i}
517
518         # Alternate corruption between osd.0 and osd.1
519         local osd=$(expr $i % 2)
520
521         case $i in
522         1)
523             # Size (deep scrub data_digest too)
524             local payload=UVWXYZZZ
525             echo $payload > $dir/CORRUPT
526             objectstore_tool $dir $osd $objname set-bytes $dir/CORRUPT || return 1
527             ;;
528
529         2)
530             # digest (deep scrub only)
531             local payload=UVWXYZ
532             echo $payload > $dir/CORRUPT
533             objectstore_tool $dir $osd $objname set-bytes $dir/CORRUPT || return 1
534             ;;
535
536         3)
537              # missing
538              objectstore_tool $dir $osd $objname remove || return 1
539              ;;
540
541          4)
542              # Modify omap value (deep scrub only)
543              objectstore_tool $dir $osd $objname set-omap key-$objname $dir/CORRUPT || return 1
544              ;;
545
546          5)
547             # Delete omap key (deep scrub only)
548             objectstore_tool $dir $osd $objname rm-omap key-$objname || return 1
549             ;;
550
551          6)
552             # Add extra omap key (deep scrub only)
553             echo extra > $dir/extra-val
554             objectstore_tool $dir $osd $objname set-omap key2-$objname $dir/extra-val || return 1
555             rm $dir/extra-val
556             ;;
557
558          7)
559             # Modify omap header (deep scrub only)
560             echo -n newheader > $dir/hdr
561             objectstore_tool $dir $osd $objname set-omaphdr $dir/hdr || return 1
562             rm $dir/hdr
563             ;;
564
565          8)
566             rados --pool $poolname setxattr $objname key1-$objname val1-$objname || return 1
567             rados --pool $poolname setxattr $objname key2-$objname val2-$objname || return 1
568
569             # Break xattrs
570             echo -n bad-val > $dir/bad-val
571             objectstore_tool $dir $osd $objname set-attr _key1-$objname $dir/bad-val || return 1
572             objectstore_tool $dir $osd $objname rm-attr _key2-$objname || return 1
573             echo -n val3-$objname > $dir/newval
574             objectstore_tool $dir $osd $objname set-attr _key3-$objname $dir/newval || return 1
575             rm $dir/bad-val $dir/newval
576             ;;
577
578         9)
579             objectstore_tool $dir $osd $objname get-attr _ > $dir/robj9-oi
580             echo -n D > $dir/change
581             rados --pool $poolname put $objname $dir/change
582             objectstore_tool $dir $osd $objname set-attr _ $dir/robj9-oi
583             rm $dir/oi $dir/change
584             ;;
585
586           # ROBJ10 must be handled after digests are re-computed by a deep scrub below
587           # ROBJ11 must be handled with config change before deep scrub
588           # ROBJ12 must be handled with config change before scrubs
589           # ROBJ13 must be handled before scrubs
590
591         14)
592             echo -n bad-val > $dir/bad-val
593             objectstore_tool $dir 0 $objname set-attr _ $dir/bad-val || return 1
594             objectstore_tool $dir 1 $objname rm-attr _ || return 1
595             rm $dir/bad-val
596             ;;
597
598         15)
599             objectstore_tool $dir $osd $objname rm-attr _ || return 1
600             ;;
601
602         16)
603             objectstore_tool $dir 0 $objname rm-attr snapset || return 1
604             echo -n bad-val > $dir/bad-val
605             objectstore_tool $dir 1 $objname set-attr snapset $dir/bad-val || return 1
606
607         esac
608     done
609
610     local pg=$(get_pg $poolname ROBJ0)
611
612     inject_eio rep data $poolname ROBJ11 $dir 0 || return 1 # shard 0 of [1, 0], osd.1
613     inject_eio rep mdata $poolname ROBJ12 $dir 1 || return 1 # shard 1 of [1, 0], osd.0
614     inject_eio rep mdata $poolname ROBJ13 $dir 1 || return 1 # shard 1 of [1, 0], osd.0
615     inject_eio rep data $poolname ROBJ13 $dir 0 || return 1 # shard 0 of [1, 0], osd.1
616
617     pg_scrub $pg
618
619     rados list-inconsistent-pg $poolname > $dir/json || return 1
620     # Check pg count
621     test $(jq '. | length' $dir/json) = "1" || return 1
622     # Check pgid
623     test $(jq -r '.[0]' $dir/json) = $pg || return 1
624
625     rados list-inconsistent-obj $pg > $dir/json || return 1
626     # Get epoch for repair-get requests
627     epoch=$(jq .epoch $dir/json)
628
629     jq "$jqfilter" << EOF | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/checkcsjson
630 {
631   "inconsistents": [
632     {
633       "shards": [
634         {
635           "size": 7,
636           "errors": [],
637           "osd": 0,
638           "primary": false
639         },
640         {
641           "size": 9,
642           "errors": [
643             "size_mismatch_oi",
644             "obj_size_oi_mismatch"
645           ],
646           "osd": 1,
647           "primary": true
648         }
649       ],
650       "selected_object_info": "3:ce3f1d6a:::ROBJ1:head(47'54 osd.0.0:53 dirty|omap|data_digest|omap_digest s 7 uv 3 dd 2ddbf8f5 od f5fba2c6 alloc_hint [0 0 0])",
651       "union_shard_errors": [
652         "size_mismatch_oi",
653         "obj_size_oi_mismatch"
654       ],
655       "errors": [
656         "size_mismatch"
657       ],
658       "object": {
659         "version": 3,
660         "snap": "head",
661         "locator": "",
662         "nspace": "",
663         "name": "ROBJ1"
664       }
665     },
666     {
667       "shards": [
668         {
669           "errors": [
670             "stat_error"
671           ],
672           "osd": 0,
673           "primary": false
674         },
675         {
676           "size": 7,
677           "errors": [],
678           "osd": 1,
679           "primary": true
680         }
681       ],
682       "selected_object_info": "3:bc819597:::ROBJ12:head(47'52 osd.0.0:51 dirty|omap|data_digest|omap_digest s 7 uv 36 dd 2ddbf8f5 od 67f306a alloc_hint [0 0 0])",
683       "union_shard_errors": [
684         "stat_error"
685       ],
686       "errors": [],
687       "object": {
688         "version": 36,
689         "snap": "head",
690         "locator": "",
691         "nspace": "",
692         "name": "ROBJ12"
693       }
694     },
695     {
696       "shards": [
697         {
698           "errors": [
699             "stat_error"
700           ],
701           "osd": 0,
702           "primary": false
703         },
704         {
705           "size": 7,
706           "errors": [],
707           "osd": 1,
708           "primary": true
709         }
710       ],
711       "selected_object_info": "3:d60617f9:::ROBJ13:head(47'55 osd.0.0:54 dirty|omap|data_digest|omap_digest s 7 uv 39 dd 2ddbf8f5 od 6441854d alloc_hint [0 0 0])",
712       "union_shard_errors": [
713         "stat_error"
714       ],
715       "errors": [],
716       "object": {
717         "version": 39,
718         "snap": "head",
719         "locator": "",
720         "nspace": "",
721         "name": "ROBJ13"
722       }
723     },
724     {
725       "shards": [
726         {
727           "size": 7,
728           "attrs": [
729             {
730               "Base64": false,
731               "value": "",
732               "name": "_"
733             },
734             {
735               "Base64": true,
736               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
737               "name": "snapset"
738             }
739           ],
740           "errors": [
741             "oi_attr_corrupted"
742           ],
743           "osd": 0,
744           "primary": false
745         },
746         {
747           "size": 7,
748           "attrs": [
749             {
750               "Base64": true,
751               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
752               "name": "snapset"
753             }
754           ],
755           "errors": [
756             "oi_attr_missing"
757           ],
758           "osd": 1,
759           "primary": true
760         }
761       ],
762       "union_shard_errors": [
763         "oi_attr_missing",
764         "oi_attr_corrupted"
765       ],
766       "errors": [],
767       "object": {
768         "version": 0,
769         "snap": "head",
770         "locator": "",
771         "nspace": "",
772         "name": "ROBJ14"
773       }
774     },
775     {
776       "shards": [
777         {
778           "attrs": [
779             {
780               "Base64": true,
781               "value": "",
782               "name": "_"
783             },
784             {
785               "Base64": true,
786               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
787               "name": "snapset"
788             }
789           ],
790           "size": 7,
791           "errors": [],
792           "osd": 0,
793           "primary": false
794         },
795         {
796           "attrs": [
797             {
798               "Base64": true,
799               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
800               "name": "snapset"
801             }
802           ],
803           "size": 7,
804           "errors": [
805             "oi_attr_missing"
806           ],
807           "osd": 1,
808           "primary": true
809         }
810       ],
811       "selected_object_info": "3:30259878:::ROBJ15:head(47'46 osd.0.0:45 dirty|omap|data_digest|omap_digest s 7 uv 45 dd 2ddbf8f5 od 2d2a4d6e alloc_hint [0 0 0])",
812       "union_shard_errors": [
813         "oi_attr_missing"
814       ],
815       "errors": [],
816       "object": {
817         "version": 45,
818         "snap": "head",
819         "locator": "",
820         "nspace": "",
821         "name": "ROBJ15"
822       }
823     },
824     {
825       "errors": [],
826       "object": {
827       "locator": "",
828       "name": "ROBJ16",
829       "nspace": "",
830       "snap": "head",
831       "version": 0
832        },
833         "shards": [
834       {
835         "attrs": [
836           {
837             "Base64": true,
838             "name": "_",
839             "value": ""
840           }
841         ],
842         "errors": [
843           "ss_attr_missing"
844         ],
845         "osd": 0,
846         "primary": false,
847         "size": 7
848       },
849       {
850         "attrs": [
851           {
852             "Base64": true,
853             "name": "_",
854             "value": ""
855           },
856           {
857             "Base64": false,
858             "name": "snapset",
859             "value": "bad-val"
860           }
861         ],
862         "errors": [
863           "ss_attr_corrupted"
864         ],
865         "osd": 1,
866         "primary": true,
867         "size": 7
868       }
869       ],
870       "union_shard_errors": [
871         "ss_attr_missing",
872         "ss_attr_corrupted"
873       ]
874     },
875     {
876       "shards": [
877         {
878           "size": 7,
879           "errors": [],
880           "osd": 0,
881           "primary": false
882         },
883         {
884           "errors": [
885             "missing"
886           ],
887           "osd": 1,
888           "primary": true
889         }
890       ],
891       "selected_object_info": "3:f2a5b2a4:::ROBJ3:head(47'57 osd.0.0:56 dirty|omap|data_digest|omap_digest s 7 uv 9 dd 2ddbf8f5 od b35dfd alloc_hint [0 0 0])",
892       "union_shard_errors": [
893         "missing"
894       ],
895       "errors": [],
896       "object": {
897         "version": 9,
898         "snap": "head",
899         "locator": "",
900         "nspace": "",
901         "name": "ROBJ3"
902       }
903     },
904     {
905       "shards": [
906         {
907           "attrs": [
908             {
909               "Base64": true,
910               "value": "",
911               "name": "_"
912             },
913             {
914               "Base64": false,
915               "value": "bad-val",
916               "name": "_key1-ROBJ8"
917             },
918             {
919               "Base64": false,
920               "value": "val3-ROBJ8",
921               "name": "_key3-ROBJ8"
922             },
923             {
924               "Base64": true,
925               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
926               "name": "snapset"
927             }
928           ],
929           "size": 7,
930           "errors": [],
931           "osd": 0,
932           "primary": false
933         },
934         {
935           "attrs": [
936             {
937               "Base64": true,
938               "value": "",
939               "name": "_"
940             },
941             {
942               "Base64": false,
943               "value": "val1-ROBJ8",
944               "name": "_key1-ROBJ8"
945             },
946             {
947               "Base64": false,
948               "value": "val2-ROBJ8",
949               "name": "_key2-ROBJ8"
950             },
951             {
952               "Base64": true,
953               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
954               "name": "snapset"
955             }
956           ],
957           "size": 7,
958           "errors": [],
959           "osd": 1,
960           "primary": true
961         }
962       ],
963       "selected_object_info": "3:86586531:::ROBJ8:head(82'62 client.4351.0:1 dirty|omap|data_digest|omap_digest s 7 uv 66 dd 2ddbf8f5 od d6be81dc alloc_hint [0 0 0])",
964       "union_shard_errors": [],
965       "errors": [
966         "attr_value_mismatch",
967         "attr_name_mismatch"
968       ],
969       "object": {
970         "version": 66,
971         "snap": "head",
972         "locator": "",
973         "nspace": "",
974         "name": "ROBJ8"
975       }
976     },
977     {
978       "shards": [
979         {
980           "object_info": "3:ffdb2004:::ROBJ9:head(102'63 client.4433.0:1 dirty|omap|data_digest|omap_digest s 1 uv 67 dd 2b63260d od 2eecc539 alloc_hint [0 0 0])",
981           "size": 1,
982           "errors": [],
983           "osd": 0,
984           "primary": false
985         },
986         {
987           "object_info": "3:ffdb2004:::ROBJ9:head(47'60 osd.0.0:59 dirty|omap|data_digest|omap_digest s 7 uv 27 dd 2ddbf8f5 od 2eecc539 alloc_hint [0 0 0])",
988           "size": 1,
989           "errors": [
990             "obj_size_oi_mismatch"
991           ],
992           "osd": 1,
993           "primary": true
994         }
995       ],
996       "selected_object_info": "3:ffdb2004:::ROBJ9:head(102'63 client.4433.0:1 dirty|omap|data_digest|omap_digest s 1 uv 67 dd 2b63260d od 2eecc539 alloc_hint [0 0 0])",
997       "union_shard_errors": [
998          "obj_size_oi_mismatch"
999       ],
1000       "errors": [
1001         "object_info_inconsistency"
1002       ],
1003       "object": {
1004         "version": 67,
1005         "snap": "head",
1006         "locator": "",
1007         "nspace": "",
1008         "name": "ROBJ9"
1009       }
1010     }
1011   ],
1012   "epoch": 0
1013 }
1014 EOF
1015
1016     jq "$jqfilter" $dir/json | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/csjson
1017     diff ${DIFFCOLOPTS} $dir/checkcsjson $dir/csjson || test $getjson = "yes" || return 1
1018     if test $getjson = "yes"
1019     then
1020         jq '.' $dir/json > save1.json
1021     fi
1022
1023     if which jsonschema > /dev/null;
1024     then
1025       jsonschema -i $dir/json $CEPH_ROOT/doc/rados/command/list-inconsistent-obj.json || return 1
1026     fi
1027
1028     objname=ROBJ9
1029     # Change data and size again because digest was recomputed
1030     echo -n ZZZ > $dir/change
1031     rados --pool $poolname put $objname $dir/change
1032     # Set one to an even older value
1033     objectstore_tool $dir 0 $objname set-attr _ $dir/robj9-oi
1034     rm $dir/oi $dir/change
1035
1036     objname=ROBJ10
1037     objectstore_tool $dir 1 $objname get-attr _ > $dir/oi
1038     rados --pool $poolname setomapval $objname key2-$objname val2-$objname
1039     objectstore_tool $dir 0 $objname set-attr _ $dir/oi
1040     objectstore_tool $dir 1 $objname set-attr _ $dir/oi
1041     rm $dir/oi
1042
1043     inject_eio rep data $poolname ROBJ11 $dir 0 || return 1 # shard 0 of [1, 0], osd.1
1044     inject_eio rep mdata $poolname ROBJ12 $dir 1 || return 1 # shard 1 of [1, 0], osd.0
1045     inject_eio rep mdata $poolname ROBJ13 $dir 1 || return 1 # shard 1 of [1, 0], osd.0
1046     inject_eio rep data $poolname ROBJ13 $dir 0 || return 1 # shard 0 of [1, 0], osd.1
1047     pg_deep_scrub $pg
1048
1049     rados list-inconsistent-pg $poolname > $dir/json || return 1
1050     # Check pg count
1051     test $(jq '. | length' $dir/json) = "1" || return 1
1052     # Check pgid
1053     test $(jq -r '.[0]' $dir/json) = $pg || return 1
1054
1055     rados list-inconsistent-obj $pg > $dir/json || return 1
1056     # Get epoch for repair-get requests
1057     epoch=$(jq .epoch $dir/json)
1058
1059     jq "$jqfilter" << EOF | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/checkcsjson
1060 {
1061   "inconsistents": [
1062     {
1063       "shards": [
1064         {
1065           "data_digest": "0x2ddbf8f5",
1066           "omap_digest": "0xf5fba2c6",
1067           "size": 7,
1068           "errors": [],
1069           "osd": 0,
1070           "primary": false
1071         },
1072         {
1073           "data_digest": "0x2d4a11c2",
1074           "omap_digest": "0xf5fba2c6",
1075           "size": 9,
1076           "errors": [
1077             "data_digest_mismatch_oi",
1078             "size_mismatch_oi",
1079             "obj_size_oi_mismatch"
1080           ],
1081           "osd": 1,
1082           "primary": true
1083         }
1084       ],
1085       "selected_object_info": "3:ce3f1d6a:::ROBJ1:head(47'54 osd.0.0:53 dirty|omap|data_digest|omap_digest s 7 uv 3 dd 2ddbf8f5 od f5fba2c6 alloc_hint [0 0 0])",
1086       "union_shard_errors": [
1087         "data_digest_mismatch_oi",
1088         "size_mismatch_oi",
1089         "obj_size_oi_mismatch"
1090       ],
1091       "errors": [
1092         "data_digest_mismatch",
1093         "size_mismatch"
1094       ],
1095       "object": {
1096         "version": 3,
1097         "snap": "head",
1098         "locator": "",
1099         "nspace": "",
1100         "name": "ROBJ1"
1101       }
1102     },
1103     {
1104       "shards": [
1105         {
1106           "data_digest": "0x2ddbf8f5",
1107           "omap_digest": "0xa8dd5adc",
1108           "size": 7,
1109           "errors": [
1110             "omap_digest_mismatch_oi"
1111           ],
1112           "osd": 0,
1113           "primary": false
1114         },
1115         {
1116           "data_digest": "0x2ddbf8f5",
1117           "omap_digest": "0xa8dd5adc",
1118           "size": 7,
1119           "errors": [
1120             "omap_digest_mismatch_oi"
1121           ],
1122           "osd": 1,
1123           "primary": true
1124         }
1125       ],
1126       "selected_object_info": "3:b1f19cbd:::ROBJ10:head(47'51 osd.0.0:50 dirty|omap|data_digest|omap_digest s 7 uv 30 dd 2ddbf8f5 od c2025a24 alloc_hint [0 0 0])",
1127       "union_shard_errors": [
1128         "omap_digest_mismatch_oi"
1129       ],
1130       "errors": [],
1131       "object": {
1132         "version": 30,
1133         "snap": "head",
1134         "locator": "",
1135         "nspace": "",
1136         "name": "ROBJ10"
1137       }
1138     },
1139     {
1140       "shards": [
1141         {
1142           "data_digest": "0x2ddbf8f5",
1143           "omap_digest": "0xa03cef03",
1144           "size": 7,
1145           "errors": [],
1146           "osd": 0,
1147           "primary": false
1148         },
1149         {
1150           "size": 7,
1151           "errors": [
1152             "read_error"
1153           ],
1154           "osd": 1,
1155           "primary": true
1156         }
1157       ],
1158       "selected_object_info": "3:87abbf36:::ROBJ11:head(47'48 osd.0.0:47 dirty|omap|data_digest|omap_digest s 7 uv 33 dd 2ddbf8f5 od a03cef03 alloc_hint [0 0 0])",
1159       "union_shard_errors": [
1160         "read_error"
1161       ],
1162       "errors": [],
1163       "object": {
1164         "version": 33,
1165         "snap": "head",
1166         "locator": "",
1167         "nspace": "",
1168         "name": "ROBJ11"
1169       }
1170     },
1171     {
1172       "shards": [
1173         {
1174           "errors": [
1175             "stat_error"
1176           ],
1177           "osd": 0,
1178           "primary": false
1179         },
1180         {
1181           "data_digest": "0x2ddbf8f5",
1182           "omap_digest": "0x067f306a",
1183           "size": 7,
1184           "errors": [],
1185           "osd": 1,
1186           "primary": true
1187         }
1188       ],
1189       "selected_object_info": "3:bc819597:::ROBJ12:head(47'52 osd.0.0:51 dirty|omap|data_digest|omap_digest s 7 uv 36 dd 2ddbf8f5 od 67f306a alloc_hint [0 0 0])",
1190       "union_shard_errors": [
1191         "stat_error"
1192       ],
1193       "errors": [],
1194       "object": {
1195         "version": 36,
1196         "snap": "head",
1197         "locator": "",
1198         "nspace": "",
1199         "name": "ROBJ12"
1200       }
1201     },
1202     {
1203       "shards": [
1204         {
1205           "errors": [
1206             "stat_error"
1207           ],
1208           "osd": 0,
1209           "primary": false
1210         },
1211         {
1212           "size": 7,
1213           "errors": [
1214             "read_error"
1215           ],
1216           "osd": 1,
1217           "primary": true
1218         }
1219       ],
1220       "union_shard_errors": [
1221         "stat_error",
1222         "read_error"
1223       ],
1224       "errors": [],
1225       "object": {
1226         "version": 0,
1227         "snap": "head",
1228         "locator": "",
1229         "nspace": "",
1230         "name": "ROBJ13"
1231       }
1232     },
1233     {
1234       "shards": [
1235         {
1236           "attrs": [
1237             {
1238               "Base64": false,
1239               "value": "",
1240               "name": "_"
1241             },
1242             {
1243               "Base64": true,
1244               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
1245               "name": "snapset"
1246             }
1247           ],
1248           "data_digest": "0x2ddbf8f5",
1249           "omap_digest": "0x4f14f849",
1250           "size": 7,
1251           "errors": [
1252             "oi_attr_corrupted"
1253           ],
1254           "osd": 0,
1255           "primary": false
1256         },
1257         {
1258           "attrs": [
1259             {
1260               "Base64": true,
1261               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
1262               "name": "snapset"
1263             }
1264           ],
1265           "data_digest": "0x2ddbf8f5",
1266           "omap_digest": "0x4f14f849",
1267           "size": 7,
1268           "errors": [
1269             "oi_attr_missing"
1270           ],
1271           "osd": 1,
1272           "primary": true
1273         }
1274       ],
1275       "union_shard_errors": [
1276         "oi_attr_missing",
1277         "oi_attr_corrupted"
1278       ],
1279       "errors": [],
1280       "object": {
1281         "version": 0,
1282         "snap": "head",
1283         "locator": "",
1284         "nspace": "",
1285         "name": "ROBJ14"
1286       }
1287     },
1288     {
1289       "shards": [
1290         {
1291           "attrs": [
1292             {
1293               "Base64": true,
1294               "value": "",
1295               "name": "_"
1296             },
1297             {
1298               "Base64": true,
1299               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
1300               "name": "snapset"
1301             }
1302           ],
1303           "data_digest": "0x2ddbf8f5",
1304           "omap_digest": "0x2d2a4d6e",
1305           "size": 7,
1306           "errors": [],
1307           "osd": 0,
1308           "primary": false
1309         },
1310         {
1311           "attrs": [
1312             {
1313               "Base64": true,
1314               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
1315               "name": "snapset"
1316             }
1317           ],
1318           "data_digest": "0x2ddbf8f5",
1319           "omap_digest": "0x2d2a4d6e",
1320           "size": 7,
1321           "errors": [
1322             "oi_attr_missing"
1323           ],
1324           "osd": 1,
1325           "primary": true
1326         }
1327       ],
1328       "selected_object_info": "3:30259878:::ROBJ15:head(47'46 osd.0.0:45 dirty|omap|data_digest|omap_digest s 7 uv 45 dd 2ddbf8f5 od 2d2a4d6e alloc_hint [0 0 0])",
1329       "union_shard_errors": [
1330         "oi_attr_missing"
1331       ],
1332       "errors": [],
1333       "object": {
1334         "version": 45,
1335         "snap": "head",
1336         "locator": "",
1337         "nspace": "",
1338         "name": "ROBJ15"
1339       }
1340     },
1341     {
1342       "errors": [],
1343       "object": {
1344       "locator": "",
1345       "name": "ROBJ16",
1346       "nspace": "",
1347       "snap": "head",
1348       "version": 0
1349        },
1350         "shards": [
1351       {
1352         "attrs": [
1353           {
1354             "Base64": true,
1355             "name": "_",
1356             "value": ""
1357           }
1358         ],
1359         "data_digest": "0x2ddbf8f5",
1360         "errors": [
1361           "ss_attr_missing"
1362         ],
1363         "omap_digest": "0x8b699207",
1364         "osd": 0,
1365         "primary": false,
1366         "size": 7
1367       },
1368       {
1369         "attrs": [
1370           {
1371             "Base64": true,
1372             "name": "_",
1373             "value": ""
1374           },
1375           {
1376             "Base64": false,
1377             "name": "snapset",
1378             "value": "bad-val"
1379           }
1380         ],
1381         "data_digest": "0x2ddbf8f5",
1382         "errors": [
1383           "ss_attr_corrupted"
1384         ],
1385         "omap_digest": "0x8b699207",
1386         "osd": 1,
1387         "primary": true,
1388         "size": 7
1389       }
1390       ],
1391       "union_shard_errors": [
1392         "ss_attr_missing",
1393         "ss_attr_corrupted"
1394       ]
1395     },
1396     {
1397       "shards": [
1398         {
1399           "data_digest": "0x578a4830",
1400           "omap_digest": "0xf8e11918",
1401           "size": 7,
1402           "errors": [
1403             "data_digest_mismatch_oi"
1404           ],
1405           "osd": 0,
1406           "primary": false
1407         },
1408         {
1409           "data_digest": "0x2ddbf8f5",
1410           "omap_digest": "0xf8e11918",
1411           "size": 7,
1412           "errors": [],
1413           "osd": 1,
1414           "primary": true
1415         }
1416       ],
1417       "selected_object_info": "3:e97ce31e:::ROBJ2:head(47'56 osd.0.0:55 dirty|omap|data_digest|omap_digest s 7 uv 6 dd 2ddbf8f5 od f8e11918 alloc_hint [0 0 0])",
1418       "union_shard_errors": [
1419         "data_digest_mismatch_oi"
1420       ],
1421       "errors": [
1422         "data_digest_mismatch"
1423       ],
1424       "object": {
1425         "version": 6,
1426         "snap": "head",
1427         "locator": "",
1428         "nspace": "",
1429         "name": "ROBJ2"
1430       }
1431     },
1432     {
1433       "shards": [
1434         {
1435           "data_digest": "0x2ddbf8f5",
1436           "omap_digest": "0x00b35dfd",
1437           "size": 7,
1438           "errors": [],
1439           "osd": 0,
1440           "primary": false
1441         },
1442         {
1443           "errors": [
1444             "missing"
1445           ],
1446           "osd": 1,
1447           "primary": true
1448         }
1449       ],
1450       "selected_object_info": "3:f2a5b2a4:::ROBJ3:head(47'57 osd.0.0:56 dirty|omap|data_digest|omap_digest s 7 uv 9 dd 2ddbf8f5 od b35dfd alloc_hint [0 0 0])",
1451       "union_shard_errors": [
1452         "missing"
1453       ],
1454       "errors": [],
1455       "object": {
1456         "version": 9,
1457         "snap": "head",
1458         "locator": "",
1459         "nspace": "",
1460         "name": "ROBJ3"
1461       }
1462     },
1463     {
1464       "shards": [
1465         {
1466           "data_digest": "0x2ddbf8f5",
1467           "omap_digest": "0xd7178dfe",
1468           "size": 7,
1469           "errors": [
1470             "omap_digest_mismatch_oi"
1471           ],
1472           "osd": 0,
1473           "primary": false
1474         },
1475         {
1476           "data_digest": "0x2ddbf8f5",
1477           "omap_digest": "0xe2d46ea4",
1478           "size": 7,
1479           "errors": [],
1480           "osd": 1,
1481           "primary": true
1482         }
1483       ],
1484       "selected_object_info": "3:f4981d31:::ROBJ4:head(47'58 osd.0.0:57 dirty|omap|data_digest|omap_digest s 7 uv 12 dd 2ddbf8f5 od e2d46ea4 alloc_hint [0 0 0])",
1485       "union_shard_errors": [
1486         "omap_digest_mismatch_oi"
1487       ],
1488       "errors": [
1489         "omap_digest_mismatch"
1490       ],
1491       "object": {
1492         "version": 12,
1493         "snap": "head",
1494         "locator": "",
1495         "nspace": "",
1496         "name": "ROBJ4"
1497       }
1498     },
1499     {
1500       "shards": [
1501         {
1502           "data_digest": "0x2ddbf8f5",
1503           "omap_digest": "0x1a862a41",
1504           "size": 7,
1505           "errors": [],
1506           "osd": 0,
1507           "primary": false
1508         },
1509         {
1510           "data_digest": "0x2ddbf8f5",
1511           "omap_digest": "0x06cac8f6",
1512           "size": 7,
1513           "errors": [
1514             "omap_digest_mismatch_oi"
1515           ],
1516           "osd": 1,
1517           "primary": true
1518         }
1519       ],
1520       "selected_object_info": "3:f4bfd4d1:::ROBJ5:head(47'59 osd.0.0:58 dirty|omap|data_digest|omap_digest s 7 uv 15 dd 2ddbf8f5 od 1a862a41 alloc_hint [0 0 0])",
1521       "union_shard_errors": [
1522         "omap_digest_mismatch_oi"
1523       ],
1524       "errors": [
1525         "omap_digest_mismatch"
1526       ],
1527       "object": {
1528         "version": 15,
1529         "snap": "head",
1530         "locator": "",
1531         "nspace": "",
1532         "name": "ROBJ5"
1533       }
1534     },
1535     {
1536       "shards": [
1537         {
1538           "data_digest": "0x2ddbf8f5",
1539           "omap_digest": "0x689ee887",
1540           "size": 7,
1541           "errors": [
1542             "omap_digest_mismatch_oi"
1543           ],
1544           "osd": 0,
1545           "primary": false
1546         },
1547         {
1548           "data_digest": "0x2ddbf8f5",
1549           "omap_digest": "0x179c919f",
1550           "size": 7,
1551           "errors": [],
1552           "osd": 1,
1553           "primary": true
1554         }
1555       ],
1556       "selected_object_info": "3:a53c12e8:::ROBJ6:head(47'50 osd.0.0:49 dirty|omap|data_digest|omap_digest s 7 uv 18 dd 2ddbf8f5 od 179c919f alloc_hint [0 0 0])",
1557       "union_shard_errors": [
1558         "omap_digest_mismatch_oi"
1559       ],
1560       "errors": [
1561         "omap_digest_mismatch"
1562       ],
1563       "object": {
1564         "version": 18,
1565         "snap": "head",
1566         "locator": "",
1567         "nspace": "",
1568         "name": "ROBJ6"
1569       }
1570     },
1571     {
1572       "shards": [
1573         {
1574           "data_digest": "0x2ddbf8f5",
1575           "omap_digest": "0xefced57a",
1576           "size": 7,
1577           "errors": [],
1578           "osd": 0,
1579           "primary": false
1580         },
1581         {
1582           "data_digest": "0x2ddbf8f5",
1583           "omap_digest": "0x6a73cc07",
1584           "size": 7,
1585           "errors": [
1586             "omap_digest_mismatch_oi"
1587           ],
1588           "osd": 1,
1589           "primary": true
1590         }
1591       ],
1592       "selected_object_info": "3:8b55fa4b:::ROBJ7:head(47'49 osd.0.0:48 dirty|omap|data_digest|omap_digest s 7 uv 21 dd 2ddbf8f5 od efced57a alloc_hint [0 0 0])",
1593       "union_shard_errors": [
1594         "omap_digest_mismatch_oi"
1595       ],
1596       "errors": [
1597         "omap_digest_mismatch"
1598       ],
1599       "object": {
1600         "version": 21,
1601         "snap": "head",
1602         "locator": "",
1603         "nspace": "",
1604         "name": "ROBJ7"
1605       }
1606     },
1607     {
1608       "shards": [
1609         {
1610           "attrs": [
1611             {
1612               "Base64": true,
1613               "value": "",
1614               "name": "_"
1615             },
1616             {
1617               "Base64": false,
1618               "value": "bad-val",
1619               "name": "_key1-ROBJ8"
1620             },
1621             {
1622               "Base64": false,
1623               "value": "val3-ROBJ8",
1624               "name": "_key3-ROBJ8"
1625             },
1626             {
1627               "Base64": true,
1628               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
1629               "name": "snapset"
1630             }
1631           ],
1632           "data_digest": "0x2ddbf8f5",
1633           "omap_digest": "0xd6be81dc",
1634           "size": 7,
1635           "errors": [],
1636           "osd": 0,
1637           "primary": false
1638         },
1639         {
1640           "attrs": [
1641             {
1642               "Base64": true,
1643               "value": "",
1644               "name": "_"
1645             },
1646             {
1647               "Base64": false,
1648               "value": "val1-ROBJ8",
1649               "name": "_key1-ROBJ8"
1650             },
1651             {
1652               "Base64": false,
1653               "value": "val2-ROBJ8",
1654               "name": "_key2-ROBJ8"
1655             },
1656             {
1657               "Base64": true,
1658               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
1659               "name": "snapset"
1660             }
1661           ],
1662           "data_digest": "0x2ddbf8f5",
1663           "omap_digest": "0xd6be81dc",
1664           "size": 7,
1665           "errors": [],
1666           "osd": 1,
1667           "primary": true
1668         }
1669       ],
1670       "selected_object_info": "3:86586531:::ROBJ8:head(82'62 client.4351.0:1 dirty|omap|data_digest|omap_digest s 7 uv 66 dd 2ddbf8f5 od d6be81dc alloc_hint [0 0 0])",
1671       "union_shard_errors": [],
1672       "errors": [
1673         "attr_value_mismatch",
1674         "attr_name_mismatch"
1675       ],
1676       "object": {
1677         "version": 66,
1678         "snap": "head",
1679         "locator": "",
1680         "nspace": "",
1681         "name": "ROBJ8"
1682       }
1683     },
1684     {
1685       "shards": [
1686         {
1687           "object_info": "3:ffdb2004:::ROBJ9:head(47'60 osd.0.0:59 dirty|omap|data_digest|omap_digest s 7 uv 27 dd 2ddbf8f5 od 2eecc539 alloc_hint [0 0 0])",
1688           "data_digest": "0x1f26fb26",
1689           "omap_digest": "0x2eecc539",
1690           "size": 3,
1691           "errors": [
1692             "obj_size_oi_mismatch"
1693           ],
1694           "osd": 0,
1695           "primary": false
1696         },
1697         {
1698           "object_info": "3:ffdb2004:::ROBJ9:head(122'64 client.4532.0:1 dirty|omap|data_digest|omap_digest s 3 uv 68 dd 1f26fb26 od 2eecc539 alloc_hint [0 0 0])",
1699           "data_digest": "0x1f26fb26",
1700           "omap_digest": "0x2eecc539",
1701           "size": 3,
1702           "errors": [],
1703           "osd": 1,
1704           "primary": true
1705         }
1706       ],
1707       "selected_object_info": "3:ffdb2004:::ROBJ9:head(122'64 client.4532.0:1 dirty|omap|data_digest|omap_digest s 3 uv 68 dd 1f26fb26 od 2eecc539 alloc_hint [0 0 0])",
1708       "union_shard_errors": [
1709         "obj_size_oi_mismatch"
1710       ],
1711       "errors": [
1712         "object_info_inconsistency"
1713       ],
1714       "object": {
1715         "version": 68,
1716         "snap": "head",
1717         "locator": "",
1718         "nspace": "",
1719         "name": "ROBJ9"
1720       }
1721     }
1722   ],
1723   "epoch": 0
1724 }
1725 EOF
1726
1727     jq "$jqfilter" $dir/json | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/csjson
1728     diff ${DIFFCOLOPTS} $dir/checkcsjson $dir/csjson || test $getjson = "yes" || return 1
1729     if test $getjson = "yes"
1730     then
1731         jq '.' $dir/json > save2.json
1732     fi
1733
1734     if which jsonschema > /dev/null;
1735     then
1736       jsonschema -i $dir/json $CEPH_ROOT/doc/rados/command/list-inconsistent-obj.json || return 1
1737     fi
1738
1739     rados rmpool $poolname $poolname --yes-i-really-really-mean-it
1740     teardown $dir || return 1
1741 }
1742
1743
1744 #
1745 # Test scrub errors for an erasure coded pool
1746 #
1747 function corrupt_scrub_erasure() {
1748     local dir=$1
1749     local allow_overwrites=$2
1750     local poolname=ecpool
1751     local total_objs=5
1752
1753     setup $dir || return 1
1754     run_mon $dir a || return 1
1755     run_mgr $dir x || return 1
1756     for id in $(seq 0 2) ; do
1757         if [ "$allow_overwrites" = "true" ]; then
1758             run_osd_bluestore $dir $id || return 1
1759         else
1760             run_osd $dir $id || return 1
1761         fi
1762     done
1763     create_rbd_pool || return 1
1764     create_pool foo 1
1765
1766     create_ec_pool $poolname $allow_overwrites k=2 m=1 stripe_unit=2K --force || return 1
1767     wait_for_clean || return 1
1768
1769     for i in $(seq 1 $total_objs) ; do
1770         objname=EOBJ${i}
1771         add_something $dir $poolname $objname || return 1
1772
1773         local osd=$(expr $i % 2)
1774
1775         case $i in
1776         1)
1777             # Size (deep scrub data_digest too)
1778             local payload=UVWXYZZZ
1779             echo $payload > $dir/CORRUPT
1780             objectstore_tool $dir $osd $objname set-bytes $dir/CORRUPT || return 1
1781             ;;
1782
1783         2)
1784             # Corrupt EC shard
1785             dd if=/dev/urandom of=$dir/CORRUPT bs=2048 count=1
1786             objectstore_tool $dir $osd $objname set-bytes $dir/CORRUPT || return 1
1787             ;;
1788
1789         3)
1790              # missing
1791              objectstore_tool $dir $osd $objname remove || return 1
1792              ;;
1793
1794         4)
1795             rados --pool $poolname setxattr $objname key1-$objname val1-$objname || return 1
1796             rados --pool $poolname setxattr $objname key2-$objname val2-$objname || return 1
1797
1798             # Break xattrs
1799             echo -n bad-val > $dir/bad-val
1800             objectstore_tool $dir $osd $objname set-attr _key1-$objname $dir/bad-val || return 1
1801             objectstore_tool $dir $osd $objname rm-attr _key2-$objname || return 1
1802             echo -n val3-$objname > $dir/newval
1803             objectstore_tool $dir $osd $objname set-attr _key3-$objname $dir/newval || return 1
1804             rm $dir/bad-val $dir/newval
1805             ;;
1806
1807         5)
1808             # Corrupt EC shard
1809             dd if=/dev/urandom of=$dir/CORRUPT bs=2048 count=2
1810             objectstore_tool $dir $osd $objname set-bytes $dir/CORRUPT || return 1
1811             ;;
1812
1813         esac
1814     done
1815
1816     local pg=$(get_pg $poolname EOBJ0)
1817
1818     pg_scrub $pg
1819
1820     rados list-inconsistent-pg $poolname > $dir/json || return 1
1821     # Check pg count
1822     test $(jq '. | length' $dir/json) = "1" || return 1
1823     # Check pgid
1824     test $(jq -r '.[0]' $dir/json) = $pg || return 1
1825
1826     rados list-inconsistent-obj $pg > $dir/json || return 1
1827     # Get epoch for repair-get requests
1828     epoch=$(jq .epoch $dir/json)
1829
1830     jq "$jqfilter" << EOF | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/checkcsjson
1831 {
1832   "inconsistents": [
1833     {
1834       "shards": [
1835         {
1836           "size": 2048,
1837           "errors": [],
1838           "shard": 2,
1839           "osd": 0,
1840           "primary": false
1841         },
1842         {
1843           "size": 9,
1844           "shard": 0,
1845           "errors": [
1846             "size_mismatch_oi",
1847             "obj_size_oi_mismatch"
1848           ],
1849           "osd": 1,
1850           "primary": true
1851         },
1852         {
1853           "size": 2048,
1854           "shard": 1,
1855           "errors": [],
1856           "osd": 2,
1857           "primary": false
1858         }
1859       ],
1860       "selected_object_info": "3:9175b684:::EOBJ1:head(21'1 client.4179.0:1 dirty|data_digest|omap_digest s 7 uv 1 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
1861       "union_shard_errors": [
1862         "size_mismatch_oi",
1863         "obj_size_oi_mismatch"
1864       ],
1865       "errors": [
1866         "size_mismatch"
1867       ],
1868       "object": {
1869         "version": 1,
1870         "snap": "head",
1871         "locator": "",
1872         "nspace": "",
1873         "name": "EOBJ1"
1874       }
1875     },
1876     {
1877       "shards": [
1878         {
1879           "size": 2048,
1880           "errors": [],
1881           "shard": 2,
1882           "osd": 0,
1883           "primary": false
1884         },
1885         {
1886           "shard": 0,
1887           "errors": [
1888             "missing"
1889           ],
1890           "osd": 1,
1891           "primary": true
1892         },
1893         {
1894           "size": 2048,
1895           "shard": 1,
1896           "errors": [],
1897           "osd": 2,
1898           "primary": false
1899         }
1900       ],
1901       "selected_object_info": "3:b197b25d:::EOBJ3:head(37'3 client.4251.0:1 dirty|data_digest|omap_digest s 7 uv 3 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
1902       "union_shard_errors": [
1903         "missing"
1904       ],
1905       "errors": [],
1906       "object": {
1907         "version": 3,
1908         "snap": "head",
1909         "locator": "",
1910         "nspace": "",
1911         "name": "EOBJ3"
1912       }
1913     },
1914     {
1915       "shards": [
1916         {
1917           "attrs": [
1918             {
1919               "Base64": true,
1920               "value": "",
1921               "name": "_"
1922             },
1923             {
1924               "Base64": false,
1925               "value": "bad-val",
1926               "name": "_key1-EOBJ4"
1927             },
1928             {
1929               "Base64": false,
1930               "value": "val3-EOBJ4",
1931               "name": "_key3-EOBJ4"
1932             },
1933             {
1934               "Base64": true,
1935               "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
1936               "name": "hinfo_key"
1937             },
1938             {
1939               "Base64": true,
1940               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
1941               "name": "snapset"
1942             }
1943           ],
1944           "size": 2048,
1945           "errors": [],
1946           "shard": 2,
1947           "osd": 0,
1948           "primary": false
1949         },
1950         {
1951           "osd": 1,
1952           "primary": true,
1953           "shard": 0,
1954           "errors": [],
1955           "size": 2048,
1956           "attrs": [
1957             {
1958               "Base64": true,
1959               "value": "",
1960               "name": "_"
1961             },
1962             {
1963               "Base64": false,
1964               "value": "val1-EOBJ4",
1965               "name": "_key1-EOBJ4"
1966             },
1967             {
1968               "Base64": false,
1969               "value": "val2-EOBJ4",
1970               "name": "_key2-EOBJ4"
1971             },
1972             {
1973               "Base64": true,
1974               "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
1975               "name": "hinfo_key"
1976             },
1977             {
1978               "Base64": true,
1979               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
1980               "name": "snapset"
1981             }
1982           ]
1983         },
1984         {
1985           "osd": 2,
1986           "primary": false,
1987           "shard": 1,
1988           "errors": [],
1989           "size": 2048,
1990           "attrs": [
1991             {
1992               "Base64": true,
1993               "value": "",
1994               "name": "_"
1995             },
1996             {
1997               "Base64": false,
1998               "value": "val1-EOBJ4",
1999               "name": "_key1-EOBJ4"
2000             },
2001             {
2002               "Base64": false,
2003               "value": "val2-EOBJ4",
2004               "name": "_key2-EOBJ4"
2005             },
2006             {
2007               "Base64": true,
2008               "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
2009               "name": "hinfo_key"
2010             },
2011             {
2012               "Base64": true,
2013               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
2014               "name": "snapset"
2015             }
2016           ]
2017         }
2018       ],
2019       "selected_object_info": "3:5e723e06:::EOBJ4:head(45'6 client.4289.0:1 dirty|data_digest|omap_digest s 7 uv 6 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
2020       "union_shard_errors": [],
2021       "errors": [
2022         "attr_value_mismatch",
2023         "attr_name_mismatch"
2024       ],
2025       "object": {
2026         "version": 6,
2027         "snap": "head",
2028         "locator": "",
2029         "nspace": "",
2030         "name": "EOBJ4"
2031       }
2032     },
2033     {
2034       "shards": [
2035         {
2036           "size": 2048,
2037           "errors": [],
2038           "shard": 2,
2039           "osd": 0,
2040           "primary": false
2041         },
2042         {
2043           "size": 4096,
2044           "shard": 0,
2045           "errors": [
2046             "size_mismatch_oi",
2047             "obj_size_oi_mismatch"
2048           ],
2049           "osd": 1,
2050           "primary": true
2051         },
2052         {
2053           "size": 2048,
2054           "shard": 1,
2055           "errors": [],
2056           "osd": 2,
2057           "primary": false
2058         }
2059       ],
2060       "selected_object_info": "3:8549dfb5:::EOBJ5:head(65'7 client.4441.0:1 dirty|data_digest|omap_digest s 7 uv 7 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
2061       "union_shard_errors": [
2062         "size_mismatch_oi",
2063         "obj_size_oi_mismatch"
2064       ],
2065       "errors": [
2066         "size_mismatch"
2067       ],
2068       "object": {
2069         "version": 7,
2070         "snap": "head",
2071         "locator": "",
2072         "nspace": "",
2073         "name": "EOBJ5"
2074       }
2075     }
2076   ],
2077   "epoch": 0
2078 }
2079 EOF
2080
2081     jq "$jqfilter" $dir/json | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/csjson
2082     diff ${DIFFCOLOPTS} $dir/checkcsjson $dir/csjson || test $getjson = "yes" || return 1
2083     if test $getjson = "yes"
2084     then
2085         jq '.' $dir/json > save3.json
2086     fi
2087
2088     if which jsonschema > /dev/null;
2089     then
2090       jsonschema -i $dir/json $CEPH_ROOT/doc/rados/command/list-inconsistent-obj.json || return 1
2091     fi
2092
2093     pg_deep_scrub $pg
2094
2095     rados list-inconsistent-pg $poolname > $dir/json || return 1
2096     # Check pg count
2097     test $(jq '. | length' $dir/json) = "1" || return 1
2098     # Check pgid
2099     test $(jq -r '.[0]' $dir/json) = $pg || return 1
2100
2101     rados list-inconsistent-obj $pg > $dir/json || return 1
2102     # Get epoch for repair-get requests
2103     epoch=$(jq .epoch $dir/json)
2104
2105     if [ "$allow_overwrites" = "true" ]
2106     then
2107       jq "$jqfilter" << EOF | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/checkcsjson
2108 {
2109   "inconsistents": [
2110     {
2111       "shards": [
2112         {
2113           "data_digest": "0x00000000",
2114           "omap_digest": "0xffffffff",
2115           "size": 2048,
2116           "errors": [],
2117           "shard": 2,
2118           "osd": 0,
2119           "primary": false
2120         },
2121         {
2122           "size": 9,
2123           "shard": 0,
2124           "errors": [
2125             "read_error",
2126             "size_mismatch_oi",
2127             "obj_size_oi_mismatch"
2128           ],
2129           "osd": 1,
2130           "primary": true
2131         },
2132         {
2133           "data_digest": "0x00000000",
2134           "omap_digest": "0xffffffff",
2135           "size": 2048,
2136           "shard": 1,
2137           "errors": [],
2138           "osd": 2,
2139           "primary": false
2140         }
2141       ],
2142       "selected_object_info": "3:9175b684:::EOBJ1:head(27'1 client.4155.0:1 dirty|data_digest|omap_digest s 7 uv 1 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
2143       "union_shard_errors": [
2144         "read_error",
2145         "size_mismatch_oi",
2146         "obj_size_oi_mismatch"
2147       ],
2148       "errors": [
2149         "size_mismatch"
2150       ],
2151       "object": {
2152         "version": 1,
2153         "snap": "head",
2154         "locator": "",
2155         "nspace": "",
2156         "name": "EOBJ1"
2157       }
2158     },
2159     {
2160       "shards": [
2161         {
2162           "data_digest": "0x00000000",
2163           "omap_digest": "0xffffffff",
2164           "size": 2048,
2165           "errors": [],
2166           "shard": 2,
2167           "osd": 0,
2168           "primary": false
2169         },
2170         {
2171           "shard": 0,
2172           "errors": [
2173             "missing"
2174           ],
2175           "osd": 1,
2176           "primary": true
2177         },
2178         {
2179           "data_digest": "0x00000000",
2180           "omap_digest": "0xffffffff",
2181           "size": 2048,
2182           "shard": 1,
2183           "errors": [],
2184           "osd": 2,
2185           "primary": false
2186         }
2187       ],
2188       "selected_object_info": "3:b197b25d:::EOBJ3:head(41'3 client.4199.0:1 dirty|data_digest|omap_digest s 7 uv 3 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
2189       "union_shard_errors": [
2190         "missing"
2191       ],
2192       "errors": [],
2193       "object": {
2194         "version": 3,
2195         "snap": "head",
2196         "locator": "",
2197         "nspace": "",
2198         "name": "EOBJ3"
2199       }
2200     },
2201     {
2202       "shards": [
2203         {
2204           "attrs": [
2205             {
2206               "Base64": true,
2207               "value": "",
2208               "name": "_"
2209             },
2210             {
2211               "Base64": false,
2212               "value": "bad-val",
2213               "name": "_key1-EOBJ4"
2214             },
2215             {
2216               "Base64": false,
2217               "value": "val3-EOBJ4",
2218               "name": "_key3-EOBJ4"
2219             },
2220             {
2221               "Base64": true,
2222               "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
2223               "name": "hinfo_key"
2224             },
2225             {
2226               "Base64": true,
2227               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
2228               "name": "snapset"
2229             }
2230           ],
2231           "data_digest": "0x00000000",
2232           "omap_digest": "0xffffffff",
2233           "size": 2048,
2234           "errors": [],
2235           "shard": 2,
2236           "osd": 0,
2237           "primary": false
2238         },
2239         {
2240           "attrs": [
2241             {
2242               "Base64": true,
2243               "value": "",
2244               "name": "_"
2245             },
2246             {
2247               "Base64": false,
2248               "value": "val1-EOBJ4",
2249               "name": "_key1-EOBJ4"
2250             },
2251             {
2252               "Base64": false,
2253               "value": "val2-EOBJ4",
2254               "name": "_key2-EOBJ4"
2255             },
2256             {
2257               "Base64": true,
2258               "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
2259               "name": "hinfo_key"
2260             },
2261             {
2262               "Base64": true,
2263               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
2264               "name": "snapset"
2265             }
2266           ],
2267           "data_digest": "0x00000000",
2268           "omap_digest": "0xffffffff",
2269           "size": 2048,
2270           "errors": [],
2271           "shard": 0,
2272           "osd": 1,
2273           "primary": true
2274         },
2275         {
2276           "attrs": [
2277             {
2278               "Base64": true,
2279               "value": "",
2280               "name": "_"
2281             },
2282             {
2283               "Base64": false,
2284               "value": "val1-EOBJ4",
2285               "name": "_key1-EOBJ4"
2286             },
2287             {
2288               "Base64": false,
2289               "value": "val2-EOBJ4",
2290               "name": "_key2-EOBJ4"
2291             },
2292             {
2293               "Base64": true,
2294               "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
2295               "name": "hinfo_key"
2296             },
2297             {
2298               "Base64": true,
2299               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
2300               "name": "snapset"
2301             }
2302           ],
2303           "data_digest": "0x00000000",
2304           "omap_digest": "0xffffffff",
2305           "size": 2048,
2306           "errors": [],
2307           "shard": 1,
2308           "osd": 2,
2309           "primary": false
2310         }
2311       ],
2312       "selected_object_info": "3:5e723e06:::EOBJ4:head(48'6 client.4223.0:1 dirty|data_digest|omap_digest s 7 uv 6 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
2313       "union_shard_errors": [],
2314       "errors": [
2315         "attr_value_mismatch",
2316         "attr_name_mismatch"
2317       ],
2318       "object": {
2319         "version": 6,
2320         "snap": "head",
2321         "locator": "",
2322         "nspace": "",
2323         "name": "EOBJ4"
2324       }
2325     },
2326     {
2327       "shards": [
2328         {
2329           "data_digest": "0x00000000",
2330           "omap_digest": "0xffffffff",
2331           "size": 2048,
2332           "errors": [],
2333           "shard": 2,
2334           "osd": 0,
2335           "primary": false
2336         },
2337         {
2338           "data_digest": "0x00000000",
2339           "omap_digest": "0xffffffff",
2340           "size": 4096,
2341           "errors": [
2342             "size_mismatch_oi",
2343             "obj_size_oi_mismatch"
2344           ],
2345           "shard": 0,
2346           "osd": 1,
2347           "primary": true
2348         },
2349         {
2350           "data_digest": "0x00000000",
2351           "omap_digest": "0xffffffff",
2352           "size": 2048,
2353           "errors": [],
2354           "shard": 1,
2355           "osd": 2,
2356           "primary": false
2357         }
2358       ],
2359       "selected_object_info": "3:8549dfb5:::EOBJ5:head(65'7 client.4288.0:1 dirty|data_digest|omap_digest s 7 uv 7 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
2360       "union_shard_errors": [
2361         "size_mismatch_oi",
2362         "obj_size_oi_mismatch"
2363       ],
2364       "errors": [
2365         "size_mismatch"
2366       ],
2367       "object": {
2368         "version": 7,
2369         "snap": "head",
2370         "locator": "",
2371         "nspace": "",
2372         "name": "EOBJ5"
2373       }
2374     }
2375   ],
2376   "epoch": 0
2377 }
2378 EOF
2379
2380     else
2381
2382       jq "$jqfilter" << EOF | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/checkcsjson
2383 {
2384   "inconsistents": [
2385     {
2386       "shards": [
2387         {
2388           "data_digest": "0x04cfa72f",
2389           "omap_digest": "0xffffffff",
2390           "size": 2048,
2391           "errors": [],
2392           "shard": 2,
2393           "osd": 0,
2394           "primary": false
2395         },
2396         {
2397           "size": 9,
2398           "shard": 0,
2399           "errors": [
2400             "read_error",
2401             "size_mismatch_oi",
2402             "obj_size_oi_mismatch"
2403           ],
2404           "osd": 1,
2405           "primary": true
2406         },
2407         {
2408           "data_digest": "0x04cfa72f",
2409           "omap_digest": "0xffffffff",
2410           "size": 2048,
2411           "shard": 1,
2412           "errors": [],
2413           "osd": 2,
2414           "primary": false
2415         }
2416       ],
2417       "selected_object_info": "3:9175b684:::EOBJ1:head(21'1 client.4179.0:1 dirty|data_digest|omap_digest s 7 uv 1 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
2418       "union_shard_errors": [
2419         "read_error",
2420         "size_mismatch_oi",
2421         "obj_size_oi_mismatch"
2422       ],
2423       "errors": [
2424         "size_mismatch"
2425       ],
2426       "object": {
2427         "version": 1,
2428         "snap": "head",
2429         "locator": "",
2430         "nspace": "",
2431         "name": "EOBJ1"
2432       }
2433     },
2434     {
2435       "shards": [
2436         {
2437           "size": 2048,
2438           "errors": [
2439             "ec_hash_error"
2440           ],
2441           "shard": 2,
2442           "osd": 0,
2443           "primary": false
2444         },
2445         {
2446           "data_digest": "0x04cfa72f",
2447           "omap_digest": "0xffffffff",
2448           "size": 2048,
2449           "errors": [],
2450           "shard": 0,
2451           "osd": 1,
2452           "primary": true
2453         },
2454         {
2455           "data_digest": "0x04cfa72f",
2456           "omap_digest": "0xffffffff",
2457           "size": 2048,
2458           "errors": [],
2459           "shard": 1,
2460           "osd": 2,
2461           "primary": false
2462         }
2463       ],
2464       "selected_object_info": "3:9babd184:::EOBJ2:head(29'2 client.4217.0:1 dirty|data_digest|omap_digest s 7 uv 2 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
2465       "union_shard_errors": [
2466         "ec_hash_error"
2467       ],
2468       "errors": [],
2469       "object": {
2470         "version": 2,
2471         "snap": "head",
2472         "locator": "",
2473         "nspace": "",
2474         "name": "EOBJ2"
2475       }
2476     },
2477     {
2478       "shards": [
2479         {
2480           "data_digest": "0x04cfa72f",
2481           "omap_digest": "0xffffffff",
2482           "size": 2048,
2483           "errors": [],
2484           "shard": 2,
2485           "osd": 0,
2486           "primary": false
2487         },
2488         {
2489           "osd": 1,
2490           "primary": true,
2491           "shard": 0,
2492           "errors": [
2493             "missing"
2494           ]
2495         },
2496         {
2497           "data_digest": "0x04cfa72f",
2498           "omap_digest": "0xffffffff",
2499           "size": 2048,
2500           "shard": 1,
2501           "errors": [],
2502           "osd": 2,
2503           "primary": false
2504         }
2505       ],
2506       "selected_object_info": "3:b197b25d:::EOBJ3:head(37'3 client.4251.0:1 dirty|data_digest|omap_digest s 7 uv 3 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
2507       "union_shard_errors": [
2508         "missing"
2509       ],
2510       "errors": [],
2511       "object": {
2512         "version": 3,
2513         "snap": "head",
2514         "locator": "",
2515         "nspace": "",
2516         "name": "EOBJ3"
2517       }
2518     },
2519     {
2520       "shards": [
2521         {
2522           "attrs": [
2523             {
2524               "Base64": true,
2525               "value": "",
2526               "name": "_"
2527             },
2528             {
2529               "Base64": false,
2530               "value": "bad-val",
2531               "name": "_key1-EOBJ4"
2532             },
2533             {
2534               "Base64": false,
2535               "value": "val3-EOBJ4",
2536               "name": "_key3-EOBJ4"
2537             },
2538             {
2539               "Base64": true,
2540               "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
2541               "name": "hinfo_key"
2542             },
2543             {
2544               "Base64": true,
2545               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
2546               "name": "snapset"
2547             }
2548           ],
2549           "data_digest": "0x04cfa72f",
2550           "omap_digest": "0xffffffff",
2551           "size": 2048,
2552           "errors": [],
2553           "shard": 2,
2554           "osd": 0,
2555           "primary": false
2556         },
2557         {
2558           "osd": 1,
2559           "primary": true,
2560           "shard": 0,
2561           "errors": [],
2562           "size": 2048,
2563           "omap_digest": "0xffffffff",
2564           "data_digest": "0x04cfa72f",
2565           "attrs": [
2566             {
2567               "Base64": true,
2568               "value": "",
2569               "name": "_"
2570             },
2571             {
2572               "Base64": false,
2573               "value": "val1-EOBJ4",
2574               "name": "_key1-EOBJ4"
2575             },
2576             {
2577               "Base64": false,
2578               "value": "val2-EOBJ4",
2579               "name": "_key2-EOBJ4"
2580             },
2581             {
2582               "Base64": true,
2583               "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
2584               "name": "hinfo_key"
2585             },
2586             {
2587               "Base64": true,
2588               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
2589               "name": "snapset"
2590             }
2591           ]
2592         },
2593         {
2594           "osd": 2,
2595           "primary": false,
2596           "shard": 1,
2597           "errors": [],
2598           "size": 2048,
2599           "omap_digest": "0xffffffff",
2600           "data_digest": "0x04cfa72f",
2601           "attrs": [
2602             {
2603               "Base64": true,
2604               "value": "",
2605               "name": "_"
2606             },
2607             {
2608               "Base64": false,
2609               "value": "val1-EOBJ4",
2610               "name": "_key1-EOBJ4"
2611             },
2612             {
2613               "Base64": false,
2614               "value": "val2-EOBJ4",
2615               "name": "_key2-EOBJ4"
2616             },
2617             {
2618               "Base64": true,
2619               "value": "AQEYAAAAAAgAAAAAAAADAAAAL6fPBLB8dlsvp88E",
2620               "name": "hinfo_key"
2621             },
2622             {
2623               "Base64": true,
2624               "value": "AwIdAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
2625               "name": "snapset"
2626             }
2627           ]
2628         }
2629       ],
2630       "selected_object_info": "3:5e723e06:::EOBJ4:head(45'6 client.4289.0:1 dirty|data_digest|omap_digest s 7 uv 6 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
2631       "union_shard_errors": [],
2632       "errors": [
2633         "attr_value_mismatch",
2634         "attr_name_mismatch"
2635       ],
2636       "object": {
2637         "version": 6,
2638         "snap": "head",
2639         "locator": "",
2640         "nspace": "",
2641         "name": "EOBJ4"
2642       }
2643     },
2644     {
2645       "shards": [
2646         {
2647           "data_digest": "0x04cfa72f",
2648           "omap_digest": "0xffffffff",
2649           "size": 2048,
2650           "errors": [],
2651           "shard": 2,
2652           "osd": 0,
2653           "primary": false
2654         },
2655         {
2656           "size": 4096,
2657           "shard": 0,
2658           "errors": [
2659             "size_mismatch_oi",
2660             "ec_size_error",
2661             "obj_size_oi_mismatch"
2662           ],
2663           "osd": 1,
2664           "primary": true
2665         },
2666         {
2667           "data_digest": "0x04cfa72f",
2668           "omap_digest": "0xffffffff",
2669           "size": 2048,
2670           "shard": 1,
2671           "errors": [],
2672           "osd": 2,
2673           "primary": false
2674         }
2675       ],
2676       "selected_object_info": "3:8549dfb5:::EOBJ5:head(65'7 client.4441.0:1 dirty|data_digest|omap_digest s 7 uv 7 dd 2ddbf8f5 od ffffffff alloc_hint [0 0 0])",
2677       "union_shard_errors": [
2678         "size_mismatch_oi",
2679         "ec_size_error",
2680         "obj_size_oi_mismatch"
2681       ],
2682       "errors": [
2683         "size_mismatch"
2684       ],
2685       "object": {
2686         "version": 7,
2687         "snap": "head",
2688         "locator": "",
2689         "nspace": "",
2690         "name": "EOBJ5"
2691       }
2692     }
2693   ],
2694   "epoch": 0
2695 }
2696 EOF
2697
2698     fi
2699
2700     jq "$jqfilter" $dir/json | python -c "$sortkeys" | sed -e "$sedfilter" > $dir/csjson
2701     diff ${DIFFCOLOPTS} $dir/checkcsjson $dir/csjson || test $getjson = "yes" || return 1
2702     if test $getjson = "yes"
2703     then
2704       if [ "$allow_overwrites" = "true" ]
2705       then
2706         num=4
2707       else
2708         num=5
2709       fi
2710       jq '.' $dir/json > save${num}.json
2711     fi
2712
2713     if which jsonschema > /dev/null;
2714     then
2715       jsonschema -i $dir/json $CEPH_ROOT/doc/rados/command/list-inconsistent-obj.json || return 1
2716     fi
2717
2718     rados rmpool $poolname $poolname --yes-i-really-really-mean-it
2719     teardown $dir || return 1
2720 }
2721
2722 function TEST_corrupt_scrub_erasure_appends() {
2723     corrupt_scrub_erasure $1 false
2724 }
2725
2726 function TEST_corrupt_scrub_erasure_overwrites() {
2727     if [ "$use_ec_overwrite" = "true" ]; then
2728         corrupt_scrub_erasure $1 true
2729     fi
2730 }
2731
2732 #
2733 # Test to make sure that a periodic scrub won't cause deep-scrub info to be lost
2734 #
2735 function TEST_periodic_scrub_replicated() {
2736     local dir=$1
2737     local poolname=psr_pool
2738     local objname=POBJ
2739
2740     setup $dir || return 1
2741     run_mon $dir a --osd_pool_default_size=2 || return 1
2742     run_mgr $dir x || return 1
2743     local ceph_osd_args="--osd-scrub-interval-randomize-ratio=0 --osd-deep-scrub-randomize-ratio=0 "
2744     ceph_osd_args+="--osd_scrub_backoff_ratio=0"
2745     run_osd $dir 0 $ceph_osd_args || return 1
2746     run_osd $dir 1 $ceph_osd_args || return 1
2747     create_rbd_pool || return 1
2748     wait_for_clean || return 1
2749
2750     create_pool $poolname 1 1 || return 1
2751     wait_for_clean || return 1
2752
2753     local osd=0
2754     add_something $dir $poolname $objname scrub || return 1
2755     local primary=$(get_primary $poolname $objname)
2756     local pg=$(get_pg $poolname $objname)
2757
2758     # Add deep-scrub only error
2759     local payload=UVWXYZ
2760     echo $payload > $dir/CORRUPT
2761     # Uses $ceph_osd_args for osd restart
2762     objectstore_tool $dir $osd $objname set-bytes $dir/CORRUPT || return 1
2763
2764     # No scrub information available, so expect failure
2765     set -o pipefail
2766     !  rados list-inconsistent-obj $pg | jq '.' || return 1
2767     set +o pipefail
2768
2769     pg_deep_scrub $pg || return 1
2770
2771     # Make sure bad object found
2772     rados list-inconsistent-obj $pg | jq '.' | grep -q $objname || return 1
2773
2774     flush_pg_stats
2775     local last_scrub=$(get_last_scrub_stamp $pg)
2776     # Fake a schedule scrub
2777     CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.${primary}) \
2778              trigger_scrub $pg || return 1
2779     # Wait for schedule regular scrub
2780     wait_for_scrub $pg "$last_scrub"
2781
2782     # It needed to be upgraded
2783     grep -q "Deep scrub errors, upgrading scrub to deep-scrub" $dir/osd.${primary}.log || return 1
2784
2785     # Bad object still known
2786     rados list-inconsistent-obj $pg | jq '.' | grep -q $objname || return 1
2787
2788     # Can't upgrade with this set
2789     ceph osd set nodeep-scrub
2790     # Let map change propagate to OSDs
2791     flush pg_stats
2792     sleep 5
2793
2794     # Fake a schedule scrub
2795     CEPH_ARGS='' ceph --admin-daemon $(get_asok_path osd.${primary}) \
2796              trigger_scrub $pg || return 1
2797     # Wait for schedule regular scrub
2798     # to notice scrub and skip it
2799     local found=false
2800     for i in $(seq 14 -1 0)
2801     do
2802       sleep 1
2803       ! grep -q "Regular scrub skipped due to deep-scrub errors and nodeep-scrub set" $dir/osd.${primary}.log || { found=true ; break; }
2804       echo Time left: $i seconds
2805     done
2806     test $found = "true" || return 1
2807
2808     # Bad object still known
2809     rados list-inconsistent-obj $pg | jq '.' | grep -q $objname || return 1
2810
2811     flush_pg_stats
2812     # Request a regular scrub and it will be done
2813     pg_scrub $pg
2814     grep -q "Regular scrub request, deep-scrub details will be lost" $dir/osd.${primary}.log || return 1
2815
2816     # deep-scrub error is no longer present
2817     rados list-inconsistent-obj $pg | jq '.' | grep -qv $objname || return 1
2818 }
2819
2820
2821 main osd-scrub-repair "$@"
2822
2823 # Local Variables:
2824 # compile-command: "cd ../.. ; make -j4 && \
2825 #    test/osd/osd-scrub-repair.sh # TEST_corrupt_and_repair_replicated"
2826 # End: