#!/bin/sh # (C) 2006, 2007, 2008 Gluster Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public # License along with this program; if not, write to the Free # Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301 USA _init () { # log level definitions LOG_NONE=NONE; LOG_CRITICAL=CRITICAL; LOG_ERROR=ERROR; LOG_WARNING=WARNING; LOG_INFO=INFO LOG_DEBUG=DEBUG; LOG_TRACE=TRACE; HOST_NAME_MAX=64; prefix="@prefix@"; exec_prefix=@exec_prefix@; cmd_line=$(echo "@sbindir@/glusterfs"); case `uname -s` in NetBSD) getinode="stat -f %i" getdev="stat -f %d" lgetinode="${getinode} -L" lgetdev="${getdev} -L" mounttab=/proc/mounts ;; Linux) getinode="stat -c %i $i" getdev="stat -c %d $d" lgetinode="${getinode} -L" lgetdev="${getdev} -L" mounttab=/etc/mtab ;; esac UPDATEDBCONF=/etc/updatedb.conf } parse_backup_volfile_servers () { local server_list=$1 local servers="" local new_servers="" servers=$(echo ${server_list} | sed 's/\:/ /g') for server in ${servers}; do length=$(echo $server | wc -c) if [ ${length} -gt ${HOST_NAME_MAX} ]; then echo "Hostname:${server} provided is too long.. skipping" continue fi new_servers=$(echo "$new_servers $server") done echo ${new_servers} } parse_backupvolfile_server () { local server=$1 length=$(echo $server | wc -c) if [ ${length} -gt ${HOST_NAME_MAX} ]; then echo "Hostname:${server} provided is too long.. exiting" exit 1 fi echo ${server} } start_glusterfs () { # lets the comparsion be case insensitive for all strings if [ -n "$log_level_str" ]; then case "$( echo $log_level_str | tr '[a-z]' '[A-Z]')" in "ERROR") log_level=$LOG_ERROR; ;; "INFO") log_level=$LOG_INFO ;; "DEBUG") log_level=$LOG_DEBUG; ;; "CRITICAL") log_level=$LOG_CRITICAL; ;; "WARNING") log_level=$LOG_WARNING; ;; "TRACE") log_level=$LOG_TRACE; ;; "NONE") log_level=$LOG_NONE; ;; *) echo "invalid log level $log_level_str, using INFO"; log_level=$LOG_INFO; ;; esac fi #options without values start here if [ -n "$read_only" ]; then cmd_line=$(echo "$cmd_line --read-only"); fi if [ -n "$acl" ]; then cmd_line=$(echo "$cmd_line --acl"); fi if [ -n "$selinux" ]; then cmd_line=$(echo "$cmd_line --selinux"); fi if [ -n "$enable_ino32" ]; then cmd_line=$(echo "$cmd_line --enable-ino32"); fi if [ -n "$worm" ]; then cmd_line=$(echo "$cmd_line --worm"); fi if [ -n "$fopen_keep_cache" ]; then cmd_line=$(echo "$cmd_line --fopen-keep-cache"); fi if [ -n "$volfile_check" ]; then cmd_line=$(echo "$cmd_line --volfile-check"); fi if [ -n "$mem_accounting" ]; then cmd_line=$(echo "$cmd_line --mem-accounting"); fi if [ -n "$aux_gfid_mount" ]; then cmd_line=$(echo "$cmd_line --aux-gfid-mount"); fi #options with values start here if [ -n "$log_level" ]; then cmd_line=$(echo "$cmd_line --log-level=$log_level"); fi if [ -n "$log_file" ]; then cmd_line=$(echo "$cmd_line --log-file=$log_file"); fi if [ -n "$direct_io_mode" ]; then cmd_line=$(echo "$cmd_line --direct-io-mode=$direct_io_mode"); fi if [ -n "$use_readdirp" ]; then cmd_line=$(echo "$cmd_line --use-readdirp=$use_readdirp"); fi if [ -n "$volume_name" ]; then cmd_line=$(echo "$cmd_line --volume-name=$volume_name"); fi if [ -n "$attribute_timeout" ]; then cmd_line=$(echo "$cmd_line --attribute-timeout=$attribute_timeout"); fi if [ -n "$entry_timeout" ]; then cmd_line=$(echo "$cmd_line --entry-timeout=$entry_timeout"); fi if [ -n "$negative_timeout" ]; then cmd_line=$(echo "$cmd_line --negative-timeout=$negative_timeout"); fi if [ -n "$gid_timeout" ]; then cmd_line=$(echo "$cmd_line --gid-timeout=$gid_timeout"); fi if [ -n "$bg_qlen" ]; then cmd_line=$(echo "$cmd_line --background-qlen=$bg_qlen"); fi if [ -n "$cong_threshold" ]; then cmd_line=$(echo "$cmd_line --congestion-threshold=$cong_threshold"); fi if [ -n "$fuse_mountopts" ]; then cmd_line=$(echo "$cmd_line --fuse-mountopts=$fuse_mountopts"); fi if [ -n "$xlator_option" ]; then xlator_option=$(echo $xlator_option | sed s/"xlator-option="/"--xlator-option "/g) cmd_line=$(echo "$cmd_line $xlator_option"); fi # for rdma volume, we have to fetch volfile with '.rdma' added # to volume name, so that it fetches the right client vol file volume_id_rdma=""; if [ -z "$volfile_loc" ]; then if [ -n "$server_ip" ]; then cmd_line=$(echo "$cmd_line --volfile-server=$server_ip"); if [ -n "$backupvolfile_server" ]; then if [ -z "$backup_volfile_servers" ]; then server=$(parse_backupvolfile_server ${backupvolfile_server}) cmd_line=$(echo "$cmd_line --volfile-server=$server"); fi fi if [ -n "$backup_volfile_servers" ]; then servers=$(parse_backup_volfile_servers ${backup_volfile_servers}) for i in $(echo ${servers}); do cmd_line=$(echo "$cmd_line --volfile-server=$i"); done fi if [ -n "$volfile_max_fetch_attempts" ]; then cmd_line=$(echo "$cmd_line --volfile-max-fetch-attempts=$volfile_max_fetch_attempts"); fi if [ -n "$server_port" ]; then cmd_line=$(echo "$cmd_line --volfile-server-port=$server_port"); fi if [ -n "$transport" ]; then cmd_line=$(echo "$cmd_line --volfile-server-transport=$transport"); if [ "$transport" = "rdma" ]; then volume_id_rdma=".rdma"; fi fi if [ -n "$volume_id" ]; then if [ -n "$volume_id_rdma" ]; then volume_id="$volume_id$volume_id_rdma"; fi cmd_line=$(echo "$cmd_line --volfile-id=$volume_id"); fi fi else cmd_line=$(echo "$cmd_line --volfile=$volfile_loc"); fi if [ -n "$fuse_mountopts" ]; then cmd_line=$(echo "$cmd_line --fuse-mountopts=$fuse_mountopts"); fi cmd_line=$(echo "$cmd_line $mount_point"); err=0; $cmd_line; if [ $? -ne 0 ]; then echo "Mount failed. Please check the log file for more details." exit 1; fi inode=$( ${getinode} $mount_point 2>/dev/null); # this is required if the stat returns error if [ -z "$inode" ]; then inode="0"; fi if [ $inode -ne 1 ]; then err=1; fi if [ $err -eq "1" ]; then echo "Mount failed. Please check the log file for more details." umount $mount_point > /dev/null 2>&1; exit 1; fi } usage () { echo "Usage: mount.glusterfs : -o Options: man 8 mount.glusterfs To display the version number of the mount helper: mount.glusterfs --version" } # check for recursive mounts. i.e, mounting over an existing brick check_recursive_mount () { if [ $1 = "/" ]; then echo Cannot mount over root; exit 2; fi # GFID check first # remove trailing / from mount point mnt_dir=${1%/}; export PATH; # check whether getfattr exists which getfattr > /dev/null 2>&1; if [ $? -ne 0 ]; then return; fi getfattr -n trusted.gfid $mnt_dir 2>/dev/null | grep -iq "trusted.gfid="; if [ $? -eq 0 ]; then echo "ERROR: $mnt_dir is in use as a brick of a gluster volume"; exit 2; fi # check if the mount point is a brick's parent directory GLUSTERD_WORKDIR="/var/lib/glusterd"; ls -L "$GLUSTERD_WORKDIR"/vols/*/bricks/* > /dev/null 2>&1; if [ $? -ne 0 ]; then return; fi brick_path=`grep ^path "$GLUSTERD_WORKDIR"/vols/*/bricks/* | cut -d "=" -f 2`; root_inode=`${lgetinode} /`; root_dev=`${lgetdev} /`; mnt_inode=`${lgetinode} $mnt_dir`; mnt_dev=`${lgetdev} $mnt_dir`; for brick in "$brick_path"; do # evaluate brick path to see if this is local, if non-local, skip iteration ls $brick > /dev/null 2>&1; if [ $? -ne 0 ]; then continue; fi getfattr -n trusted.gfid "$brick" 2>/dev/null | grep -iq "trusted.gfid="; if [ $? -ne 0 ]; then continue; else # brick is local while [ 1 ]; do tmp_brick="$brick"; brick="$brick"/..; brick_dev=`${lgetdev} $brick`; brick_inode=`${lgetinode} $brick`; if [ "$mnt_inode" -eq "$brick_inode" -a "$mnt_dev" -eq "$brick_dev" ]; then echo ERROR: $mnt_dir is a parent of the brick $tmp_brick; exit 2; fi [ "$root_inode" -ne "$brick_inode" -o "$root_dev" -ne "$brick_dev" ] || break; done; fi done; } main () { helper=$(echo "$@" | sed -n 's/.*\--[ ]*\([^ ]*\).*/\1/p'); in_opt="no" pos_args=0 for opt in "$@"; do if [ "$in_opt" = "yes" ]; then for pair in $(echo "$opt" | tr "," " "); do # Handle options without values. case "$pair" in "ro") read_only=1 ;; "acl") acl=1 ;; "selinux") selinux=1 ;; "worm") worm=1 ;; "fopen-keep-cache") fopen_keep_cache=1 ;; "enable-ino32") enable_ino32=1 ;; "mem-accounting") mem_accounting=1;; "aux-gfid-mount") if [ `uname -s` = "Linux" ]; then aux_gfid_mount=1 fi ;; # "mount -t glusterfs" sends this, but it's useless. "rw") ;; # these ones are interpreted during system initialization "noauto") ;; "_netdev") ;; *) key=$(echo "$pair" | cut -f1 -d'='); value=$(echo "$pair" | cut -f2- -d'='); # Handle options with values. case "$key" in "log-level") log_level_str=$value ;; "log-file") log_file=$value ;; "transport") transport=$value ;; "direct-io-mode") direct_io_mode=$value ;; "volume-name") volume_name=$value ;; "volume-id") volume_id=$value ;; "volfile-check") volfile_check=$value ;; "server-port") server_port=$value ;; "attribute-timeout") attribute_timeout=$value ;; "entry-timeout") entry_timeout=$value ;; "negative-timeout") negative_timeout=$value ;; "gid-timeout") gid_timeout=$value ;; "background-qlen") bg_qlen=$value ;; "backup-volfile-servers") backup_volfile_servers=$value ;; ## Place-holder backward compatibility "backupvolfile-server") backupvolfile_server=$value ;; "fetch-attempts") volfile_max_fetch_attempts=$value ;; ## End backward compatibility "congestion-threshold") cong_threshold=$value ;; "xlator-option") xlator_option=$xlator_option" "$pair ;; "fuse-mountopts") fuse_mountopts=$value ;; "use-readdirp") use_readdirp=$value ;; *) # Passthru [ -z "$fuse_mountopts" ] || fuse_mountopts="$fuse_mountopts," fuse_mountopts="$fuse_mountopts$pair" ;; esac esac done in_opt="no" elif [ "$opt" = "-o" ]; then in_opt="yes" else case $pos_args in 0) volfile_loc=$opt ;; 1) mount_point=$opt ;; *) echo "extra arguments at end (ignored)" ;; esac pos_args=$((pos_args+1)) fi done if [ $in_opt = "yes" -o $pos_args -lt 2 ]; then usage exit 1 fi [ -r "$volfile_loc" ] || { server_ip=$(echo "$volfile_loc" | sed -n 's/\([a-zA-Z0-9:.\-]*\):.*/\1/p'); test_str=$(echo "$volfile_loc" | sed -n 's/.*:\([^ ]*\).*/\1/p'); [ -n "$test_str" ] && { volume_id="$test_str"; } volfile_loc=""; } # [ -n "$helper" ] && { cmd_line=$(echo "$cmd_line --$helper"); exec $cmd_line; exit 0; } # No need to do a ! -d test, it is taken care while initializing the # variable mount_point [ -z "$mount_point" -o ! -d "$mount_point" ] && { echo "ERROR: Mount point does not exist." usage; exit 0; } # Simple check to avoid multiple identical mounts if grep -q "[[:space:]+]${mount_point}[[:space:]+]fuse" $mounttab; then echo -n "$0: according to mtab, GlusterFS is already mounted on " echo "$mount_point" exit 0; fi check_recursive_mount "$mount_point"; # Append fuse.glusterfs to PRUNEFS variable in updatedb.conf(5). updatedb(8) # should not index files under GlusterFS, indexing will slow down GlusteFS # if the filesystem is several TB in size. test -f $UPDATEDBCONF && { if ! grep -q 'glusterfs' $UPDATEDBCONF; then sed 's/\(PRUNEFS.*\)"/\1 fuse.glusterfs"/' $UPDATEDBCONF \ > ${UPDATEDBCONF}.bak mv -f ${UPDATEDBCONF}.bak $UPDATEDBCONF fi } start_glusterfs; } _init "$@" && main "$@";