glusterfs

Форк
0
247 строк · 5.5 Кб
1
/*
2
  Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
3
  This file is part of GlusterFS.
4

5
  This file is licensed to you under your choice of the GNU Lesser
6
  General Public License, version 3 or any later version (LGPLv3 or
7
  later), or the GNU General Public License, version 2 (GPLv2), in all
8
  cases as published by the Free Software Foundation.
9
*/
10

11
#ifndef _CONFIG_H
12
#define _CONFIG_H
13
#include "config.h"
14
#endif
15

16
#include <stdlib.h>
17
#include <stdio.h>
18
#include <unistd.h>
19
#include <errno.h>
20
#include <dirent.h>
21
#include <limits.h>
22
#include <sys/types.h>
23
#include <sys/stat.h>
24
#include <sys/mount.h>
25

26
#include "glusterfs/globals.h"
27
#include "glusterfs/glusterfs.h"
28
#include "glusterfs/logging.h"
29
#include "glusterfs/syscall.h"
30
#include "glusterfs/mem-types.h"
31

32
static void
33
usage(void)
34
{
35
    fprintf(stderr, "Usage: umountd [-d dev] [-t timeout] [-r] path\n");
36
    exit(EXIT_FAILURE);
37
}
38

39
static int
40
sanity_check(char *path, dev_t *devp)
41
{
42
    struct stat st;
43
    struct stat parent_st;
44
    int ret;
45
    char pathtmp[PATH_MAX];
46
    char *parent;
47

48
    if (path == NULL)
49
        usage();
50

51
    if ((ret = stat(path, &st)) != 0) {
52
        switch (errno) {
53
            case ENOTCONN:
54
                /* volume is stopped */
55
                break;
56
            default:
57
                gf_log("umountd", GF_LOG_ERROR, "Cannot access %s: %s\n", path,
58
                       strerror(errno));
59
                goto out;
60
        }
61
    }
62

63
    /* If dev was not specified, get it from path */
64
    if (*devp == -1 && ret == 0)
65
        *devp = st.st_dev;
66

67
    snprintf(pathtmp, PATH_MAX, "%s", path);
68
    parent = dirname(pathtmp);
69

70
    if (stat(parent, &parent_st) != 0) {
71
        gf_log("umountd", GF_LOG_ERROR, "Cannot access %s: %s\n", parent,
72
               strerror(errno));
73
        goto out;
74
    }
75

76
    if (st.st_dev == parent_st.st_dev) {
77
        gf_log("umountd", GF_LOG_ERROR, "No filesystem mounted on %s\n", path);
78
        goto out;
79
    }
80

81
    ret = 0;
82

83
out:
84
    return ret;
85
}
86

87
static void
88
log_rotate(int signum)
89
{
90
    gf_log_logrotate(1);
91

92
    if (signal(SIGHUP, *log_rotate) == SIG_ERR) {
93
        gf_log("umountd", GF_LOG_ERROR, "signal () failed");
94
        exit(EXIT_FAILURE);
95
    }
96

97
    return;
98
}
99

100
static int
101
logging_init(void)
102
{
103
    glusterfs_ctx_t *ctx;
104
    char log_file[PATH_MAX];
105
    int ret = -1;
106

107
    ctx = glusterfs_ctx_new();
108
    if (!ctx) {
109
        fprintf(stderr, "glusterfs_ctx_new failed\n");
110
        goto out;
111
    }
112

113
    ret = glusterfs_globals_init(ctx);
114
    if (ret) {
115
        fprintf(stderr, "glusterfs_globals_init failed\n");
116
        goto out;
117
    }
118

119
    THIS->ctx = ctx;
120
    xlator_mem_acct_init(THIS, gf_common_mt_end);
121

122
    snprintf(log_file, PATH_MAX, "%s/umountd.log", DEFAULT_LOG_FILE_DIRECTORY);
123

124
    ret = gf_log_init(ctx, log_file, "umountd");
125
    if (ret) {
126
        fprintf(stderr, "gf_log_init failed\n");
127
        goto out;
128
    }
129

130
    if (signal(SIGHUP, *log_rotate) == SIG_ERR) {
131
        gf_log("umountd", GF_LOG_ERROR, "signal () failed");
132
        goto out;
133
    }
134

135
    ret = 0;
136
out:
137
    return ret;
138
}
139

140
static int
141
umountd_async(char *path, dev_t dev, int frmdir, int timeout)
142
{
143
    int ret = -1;
144
    struct stat stbuf = {
145
        0,
146
    };
147
    int unmount_ret = 0;
148

149
    do {
150
        unmount_ret = unmount(path, 0);
151
        if (unmount_ret == 0)
152
            gf_log("umountd", GF_LOG_INFO, "Unmounted %s", path);
153

154
        if (unmount_ret != 0 && errno != EBUSY) {
155
            gf_log("umountd", GF_LOG_WARNING, "umount %s failed: %s", path,
156
                   strerror(errno));
157
        }
158

159
        ret = sys_lstat(path, &stbuf);
160
        if (ret != 0) {
161
            gf_log("umountd", GF_LOG_WARNING, "Cannot stat device from %s",
162
                   path, strerror(errno));
163
            break;
164
        }
165

166
        if (stbuf.st_dev != dev) {
167
            if (unmount_ret != 0)
168
                gf_log("umountd", GF_LOG_INFO,
169
                       "device mismatch "
170
                       "(expect %lld, found %lld), "
171
                       "someone else unmounted %s",
172
                       dev, stbuf.st_dev, path);
173
            ret = 0;
174
            break;
175
        }
176

177
        sleep(timeout);
178
    } while (1 /*CONSTCOND*/);
179

180
    if (ret) {
181
        gf_log("umountd", GF_LOG_ERROR, "Asynchronous unmount of %s failed: %s",
182
               path, strerror(errno));
183
    } else {
184
        if (frmdir) {
185
            ret = rmdir(path);
186
            if (ret)
187
                gf_log("umountd", GF_LOG_WARNING, "rmdir %s failed: %s", path,
188
                       strerror(errno));
189
            else
190
                gf_log("umountd", GF_LOG_INFO, "Removed %s", path);
191
        }
192
    }
193

194
    return ret;
195
}
196

197
int
198
main(int argc, char **argv)
199
{
200
    char *path = NULL;
201
    dev_t dev = -1;
202
    int frmdir = 0;
203
    int timeout = 30;
204
    int f;
205

206
    while ((f = getopt(argc, argv, "d:rt:")) != -1) {
207
        switch (f) {
208
            case 'p':
209
                path = optarg;
210
                break;
211
            case 'd':
212
                dev = strtoll(optarg, NULL, 10);
213
                break;
214
            case 't':
215
                timeout = atoi(optarg);
216
                break;
217
            case 'r':
218
                frmdir = 1;
219
                break;
220
            default:
221
                usage();
222
                break;
223
        }
224
    }
225

226
    argc -= optind;
227
    argv += optind;
228

229
    if (argc != 1)
230
        usage();
231

232
    path = argv[0];
233

234
    if (logging_init() != 0)
235
        exit(EXIT_FAILURE);
236

237
    if (sanity_check(path, &dev) != 0)
238
        exit(EXIT_FAILURE);
239

240
    if (daemon(0, 0) != 0)
241
        exit(EXIT_FAILURE);
242

243
    if (umountd_async(path, dev, frmdir, timeout) != 0)
244
        exit(EXIT_FAILURE);
245

246
    return EXIT_SUCCESS;
247
}
248

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.