summaryrefslogtreecommitdiffstats
path: root/extras/glusterfs-defrag.in
blob: 982878bdbe93fb7ef21566dad1db61f842bd6fb9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#!/bin/bash

# Please leave 'added_bricks' as empty if you want 100% defrag.
# If you want to move data to newly added bricks, properly give
# brick info as "<hostname>:<export-dir>" form (which was given
# in 'gluster volume create' command)
# More than one brick can be given with space inbetween.

#
# (c) 2010 Gluster Inc <http://www.gluster.com/>
#

set -e;

added_bricks="node1:/gfs/export1"

CP="cp"
MV="mv"

scan_dir()
{
    path=$1;
    # run defrag on files first #
    find "$path" -maxdepth 1 -type f -perm +01000 -exec $0 '{}' \;

    for subdir in $(find "$path" -maxdepth 1 -type d | sed 1d); do
        $0 "$subdir";
    done
}

fix_xattr()
{
    path=$1;
    getfattr -n trusted.distribute.fix.layout "$path" 2>/dev/null;
}

rsync_filename()
{
    path=$1
    dir=$(dirname "$path");
    file=$(basename "$path");

    echo "$dir/.$file.zr$$";
}

relocate_file()
{
    path=$1;
    stat_info=$(stat -c '%a' "$path");
    if [ $stat_info -lt 1000 ] ; then
        return;
    fi

    flag=0;
    linknode=$(getfattr --only-values -n trusted.distribute.linkinfo $path 2>/dev/null);
    if [ -z $linknode ] ; then
        return;
    fi

    for bricks in ${added_bricks}; do
        current_brick=${linknode:0:${#bricks}};
        if [ "${bricks}" == "${current_brick}" ]; then
            flag=1;
        fi
    done

    if [ $flag -ne 1 ]; then
        return;
    fi

    tmp_path=$(rsync_filename "$path");

    pre_mtime=$(stat -c '%Y' "$path");
    $CP -a "$path" "$tmp_path";
    post_mtime=$(stat -c '%Y' "$path");

    if [ $pre_mtime = $post_mtime ]; then
	chmod -t "$tmp_path";
	$MV "$tmp_path" "$path";
	echo "file '$path' relocated"
    else
	echo "file '$path' modified during defrag. skipping"
	rm -f "$tmp_path";
    fi
}

defrag_usage()
{
    echo "Usage: $0 <directory>"
}

main()
{
    path="$1";

    if [ -z "$path" ]; then
        defrag_usage;
        return;
    fi

    if [ -d "$path" ]; then
        fix_xattr "$path";
	scan_dir "$path";
    else
	relocate_file "$@";
    fi
}

main "$1"