# Filters for btrfs command output . ./common/filter # Some, but not all, commands emit "Btrfs " _filter_btrfs_version() { sed -e "s/^[Bb]trfs.*//g" } _filter_devid() { sed -e "s/\(devid\)\s\+[0-9]\+/\1 /g" } # If passed a number as first arg, filter that number of devices # If passed a UUID as second arg, filter that exact UUID _filter_btrfs_filesystem_show() { if [ ! -z $1 ]; then NUMDEVS=$1 NUM_SUBST="" else NUMDEVS="[0-9]\+" NUM_SUBST="" fi UUID="" if [ ! -z $2 ]; then UUID=$2 fi # the uniq collapses all device lines into 1 _filter_uuid $UUID | _filter_scratch | _filter_scratch_pool | \ _filter_size | _filter_btrfs_version | _filter_devid | \ _filter_zero_size | \ sed -e "s/\(Total devices\) $NUMDEVS/\1 $NUM_SUBST/g" | \ uniq > $tmp.btrfs_filesystem_show # The first two lines are Label/UUID and total devices head -n 2 $tmp.btrfs_filesystem_show # The remaining is the device list, first filter out the detailed # missing device to the generic one. # Then sort and uniq the result tail -n +3 $tmp.btrfs_filesystem_show | \ sed -e "s/devid size 0 used 0 path MISSING/*** Some devices missing/" | \ sort -r | uniq rm -f $tmp.btrfs_filesystem_show } # This eliminates all numbers, and shows only unique lines, # to accomodate a varying nr. of devices. # If given an argument, make sure we saw that many devices # in total. _filter_btrfs_device_stats() { if [ ! -z $1 ]; then NUMDEVS=$1 UNIQ_OPT="-c" else NUMDEVS="thiswillnotmatch" UNIQ_OPT="" fi _filter_scratch | _filter_scratch_pool | \ sed -e "s/[0-9]\+$//g" | sort | uniq $UNIQ_OPT | \ sed -e "s/ *$NUMDEVS / /g" } _filter_transaction_commit() { sed -e "/Transaction commit: none (default)/d" \ -e "s/Delete subvolume [0-9]\+ (.*commit):/Delete subvolume/g" \ -e "s/Delete subvolume (.*commit):/Delete subvolume/g" } _filter_btrfs_subvol_delete() { _filter_scratch | _filter_transaction_commit } _filter_btrfs_compress_property() { sed -e "s/compression=\(lzo\|zlib\|zstd\)/COMPRESSION=XXX/g" } # filter error messages from btrfs prop, optionally verify against $1 # recognized message(s): # "object is not compatible with property: label" # "invalid value for property:{, value}" # "failed to {get,set} compression for $PATH[.:]: Invalid argument" _filter_btrfs_prop_error() { if ! [ -z "$1" ]; then sed -e "s#\(compatible with property\): $1#\1#" \ -e "s#^\(.*failed to [sg]et compression for $1\)[:.] \(.*\)#\1: \2#" else sed -e "s#^\(.*compatible with property\).*#\1#" \ -e "s#^\(.*invalid value for property\)[:.].*#\1#" fi } # filter warning messages caused by "btrfs quota assign/remove" command. # Since qgroup relationship change could cause qgroup inconsistency, it would # either trigger a qgroup rescan, or warning message. _filter_btrfs_qgroup_assign_warnings() { sed -e "/Quota data changed, rescan scheduled/d" \ -e "/quotas may be inconsistent, rescan needed/d" } # Long ago we found that attempting to clone inline extents resulted in hitting # a BUG_ON() and then decided to not support such use cases by returning errno # -EOPNOTSUPP to user space. Later on, clone/reflink became a VFS API too, since # other filesystems (such as XFS) implemented this feature. After that we found # one scenario of data corruption due to allowing cloning an EOF block into the # middle of a file, and started to reject such scenario by returning the errno # -EINVAL to user space (this affected both Btrfs and XFS). Such scenario often # overlaps the detection of attempts to clone inline extents, since it is done # early on based only on the arguments passed to the clone system call (and # btrfs' specific ioctl) before processing the source file extents. # So replace error messages related to errno -EOPNOTSUPP to be the same as the # one we get from a -EINVAL errno. _filter_btrfs_cloner_error() { sed -e "s/\(clone failed:\) Operation not supported/\1 Invalid argument/g" } # filter output of "btrfs inspect-internal dump-tree -t raid-stripe" _filter_stripe_tree() { _filter_trailing_whitespace | _filter_btrfs_version |\ sed -E -e "s/leaf [0-9]+ items [0-9]+ free space [0-9]+ generation [0-9]+ owner RAID_STRIPE_TREE/leaf XXXXXXXXX items X free space XXXXX generation X owner RAID_STRIPE_TREE/" \ -e "s/leaf [0-9]+ flags 0x1\(WRITTEN\) backref revision 1/leaf XXXXXXXXX flags 0x1\(WRITTEN\) backref revision 1/" \ -e "s/checksum stored [0-9a-f]+/checksum stored /" \ -e "s/checksum calced [0-9a-f]+/checksum calced /" \ -e "s/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}//" \ -e "s/item ([0-9]+) key \([0-9]+ RAID_STRIPE ([0-9]+)\) itemoff [0-9]+ itemsize ([0-9]+)/item \1 key \(XXXXXX RAID_STRIPE \2\) itemoff XXXXX itemsize \3/" \ -e "s/stripe ([0-9]+) devid ([0-9]+) physical [0-9]+/stripe \1 devid \2 physical XXXXXXXXX/" \ -e "s/total bytes [0-9]+/total bytes XXXXXXXX/" \ -e "s/bytes used [0-9]+/bytes used XXXXXX/" } # filter output of "btrfs balance start -[smd] convert _filter_balance_convert() { _filter_scratch | \ sed -e "s/relocate [0-9]\+ out of [0-9]\+ chunks/relocate X out of X chunks/g" } # filter output of "btrfs device add" _filter_device_add() { _filter_scratch | _filter_scratch_pool | \ sed -e "/Resetting device zones SCRATCH_DEV ([0-9]\+/d" } # make sure this script returns success /bin/true