Resolving Gluster GFIDs back to real files and directories (BASH)
When dealing with Gluster, you'll inevitably stumble across output which provides a Gluster File ID (GFID) rather than a real path - whether that's when dealing with a split-brain or when checking logs.
This script can be used to turn a GFID (such as 54fa66cc-ccdd-42f4-8eb2-6083e9121de5
) back into a more recognisable path (such as /brick1/gluster/foo/bar.jpg
), this can then be used to help resolve split-brain issues etc.
Details
- Language: BASH
- License: BSD-3-Clause
Snippet
#!/bin/bash
#
# Copyright (C) 2019 B Tasker
#
# resolve-gfid.sh
#
# Take a brick path and a GFID and work out the path it represents (i.e.
# where it points to if you were accessing via GlusterFS).
#
# Adaptation based on the logic in https://gist.github.com/louiszuckerman/4392640
# essentially fixes some bugs related to Gluster breakage, adds comments
# and tidies code formatting a bit
#
#
if [[ "$#" -lt "2" || "$#" -gt "3" ]]
then
cat << END
Glusterfs GFID resolver -- turns a GFID into a real file path
Usage: $0 <brick-path> <gfid> [-q]
<brick-path> : the path to your glusterfs brick (required)
<gfid> : the gfid you wish to resolve to a real path (required)
-q : quieter output (optional)
with this option only the actual resolved path is printed.
without this option $0 will print the GFID,
whether it identifies a file or directory, and the resolved
path to the real file or directory.
Theory:
The .glusterfs directory in the brick root has files named by GFIDs
If the GFID identifies a directory, then this file is a symlink to the
actual directory. If the GFID identifies a file then this file is a
hard link to the actual file.
END
exit
fi
# Get brick and GFID from the cmdline
BRICK="$1"
GFID="$2"
QUIET="$3"
# Directories are named based on the first chars of the gfid
# e.g. f6/b7/f6b763ec-a996-4f2a-adc9-89635b7e12dc
#
GP1=`cut -c 1-2 <<<"$GFID"`
GP2=`cut -c 3-4 <<<"$GFID"`
# Start building the path to the GFID symlink's parent directory
GFIDPRE="$BRICK"/.glusterfs/"$GP1"/"$GP2"
# Append the GFID
GFIDPATH="$GFIDPRE"/"$GFID"
if [ ! "$QUIET" == "-q" ]; then
echo -ne "$GFID\t==\t"
fi
# Does the path exist, and is it a symbolic link?
if [ -h "$GFIDPATH" ]; then
if [ ! "$QUIET" == "-q" ]; then
echo -ne "Directory:\t"
fi
DIRPATH="$GFIDPRE"/`readlink "$GFIDPATH"`
# Calculate the "real" pathname
#
# The script this is based on tried to cd and pwd it
# this resulted in the script failing with "Too many levels of symbolic links"
# whenever Gluster was having one of it's moments
#
echo $(readlink -f `dirname "$DIRPATH"`)/$(basename "$DIRPATH")
else
# Not a symlink - means it's a file and the path we're looking at
# will be a hardlink back to the file wherever on the brick it actually lives
if [ ! "$QUIET" == "-q" ]; then
echo -ne "File:\t"
fi
INUM=`ls -i "$GFIDPATH" | cut -f 1 -d \ `
if [ "$INUM" == "" ]
then
echo "Unable to get inode number for file. Do you lack appropriate permissions?"
exit 1
fi
find "$BRICK" -inum "$INUM" ! -path \*.glusterfs/\*
fi
Usage Example
./resolv-gfid.sh /brick1/gluster 54fa66cc-ccdd-42f4-8eb2-6083e9121de5
54fa66cc-ccdd-42f4-8eb2-6083e9121de5 == Directory: /brick1/gluster/sharedfile/jpgs/034