14
#include <glusterfs/globals.h>
15
#include <glusterfs/glusterfs.h>
16
#include <glusterfs/compat.h>
17
#include <glusterfs/dict.h>
18
#include <glusterfs/list.h>
19
#include <glusterfs/logging.h>
20
#include <glusterfs/syscall.h>
21
#include <glusterfs/compat.h>
22
#include <glusterfs/compat-errno.h>
23
#include <glusterfs/run.h>
24
#include "glusterd-mem-types.h"
25
#include "glusterd-utils.h"
26
#include <glusterfs/common-utils.h>
27
#include "glusterd-mountbroker.h"
28
#include "glusterd-op-sm.h"
29
#include "glusterd-messages.h"
32
seq_dict_foreach(dict_t *dict, int (*fn)(char *str, void *data), void *data)
34
char index[] = "4294967296";
40
snprintf(index, sizeof(index), "%d", i);
41
ret = dict_get_str(dict, index, &val);
43
return ret == -ENOENT ? 0 : ret;
51
parse_mount_pattern_desc(gf_mount_spec_t *mspec, char *pdesc)
58
gf_mount_pattern_t *pat = NULL;
74
for (curs = pdesc; *curs; curs++) {
79
mspec->patterns = GF_CALLOC(mspec->len, sizeof(*mspec->patterns),
80
gf_gld_mt_mount_pattern);
81
if (!mspec->patterns) {
82
gf_smsg("glusterd", GF_LOG_ERROR, errno, GD_MSG_NO_MEMORY, NULL);
87
pat = mspec->patterns;
95
pat->negative = _gf_true;
102
c2 = nwstrtail(curs, "SUB(");
104
pat->condition = SET_SUB;
107
c2 = nwstrtail(curs, "SUP(");
109
pat->condition = SET_SUPER;
110
lastsup = pat - mspec->patterns;
113
c2 = nwstrtail(curs, "EQL(");
115
pat->condition = SET_EQUAL;
118
c2 = nwstrtail(curs, "MEET(");
120
pat->condition = SET_INTERSECT;
123
c2 = nwstrtail(curs, "SUB+(");
125
pat->condition = SET_SUB;
137
pnum = *curs == ')' ? 0 : 1;
138
for (c2 = curs; *c2 != ')';) {
139
if (strchr("&|", *c2)) {
143
while (!strchr("|&)", *c2) && !isspace(*c2))
163
for (pcc = mspec->patterns[incl].components; *pcc; pcc++)
167
pat->components = GF_CALLOC(pnum + 1, sizeof(*pat->components),
168
gf_gld_mt_mount_comp_container);
169
if (!pat->components) {
174
cc = pat->components;
177
memcpy(pat->components, mspec->patterns[incl].components,
178
pnc * sizeof(*pat->components));
185
while (!isspace(*c2) && *c2 != ')')
190
*cc = gf_strdup(curs);
214
if (ret == SYNTAX_ERR) {
215
gf_msg("glusterd", GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
216
"cannot parse mount patterns %s", pdesc);
226
const char *georep_mnt_desc_template =
230
"volfile-server=localhost "
235
"log-file=%s/" GEOREP
245
make_georep_mountspec(gf_mount_spec_t *mspec, const char *volnames, char *user,
248
char *georep_mnt_desc = NULL;
249
char *meetspec = NULL;
253
char *savetok = NULL;
262
vols = gf_strdup((char *)volnames);
264
gf_smsg(THIS->name, GF_LOG_ERROR, errno, GD_MSG_STRDUP_FAILED,
265
"Volume name=%s", volnames, NULL);
269
for (vc = 1, p = vols; *p; p++) {
273
siz = strlen(volnames) + vc * SLEN("volfile-id=");
274
meetspec = GF_CALLOC(1, siz + 1, gf_gld_mt_georep_meet_spec);
276
gf_smsg(THIS->name, GF_LOG_ERROR, errno, GD_MSG_NO_MEMORY, NULL);
281
vol = strtok_r(p, ",", &savetok);
287
strcat(meetspec, "volfile-id=");
288
strcat(meetspec, vol);
290
strcat(meetspec, " ");
293
ret = gf_asprintf(&georep_mnt_desc, georep_mnt_desc_template,
294
GF_CLIENT_PID_GSYNCD, user, logdir, meetspec);
296
georep_mnt_desc = NULL;
300
ret = parse_mount_pattern_desc(mspec, georep_mnt_desc);
305
fa[2] = georep_mnt_desc;
307
for (i = 0; i < 3; i++) {
318
match_comp(char *str, char *patcomp)
335
return fnmatch(c1, c2, 0) == 0 ? _gf_true : _gf_false;
338
struct gf_set_descriptor {
339
gf_boolean_t priv[2];
344
_gf_set_dict_iter1(char *val, void *data)
347
struct gf_set_descriptor *sd = dataa[0];
348
char **curs = dataa[1];
349
gf_boolean_t priv = _gf_true;
352
if (match_comp(val, *curs)) {
354
sd->common = _gf_true;
360
sd->priv[0] = _gf_true;
366
_gf_set_dict_iter2(char *val, void *data)
369
gf_boolean_t *boo = dataa[0];
370
char *comp = dataa[1];
372
if (match_comp(val, comp))
379
relate_sets(struct gf_set_descriptor *sd, dict_t *argdict, char **complist)
381
void *dataa[] = {NULL, NULL};
382
gf_boolean_t boo = _gf_false;
384
memset(sd, 0, sizeof(*sd));
388
seq_dict_foreach(argdict, _gf_set_dict_iter1, dataa);
393
dataa[1] = *complist;
394
seq_dict_foreach(argdict, _gf_set_dict_iter2, dataa);
397
sd->common = _gf_true;
399
sd->priv[1] = _gf_true;
406
_arg_parse_uid(char *val, void *data)
408
char *user = strtail(val, "user-map-root=");
409
struct passwd *pw = NULL;
417
if (*(int *)data >= 0)
421
*(int *)data = pw->pw_uid;
426
evaluate_mount_request(xlator_t *this, gf_mount_spec_t *mspec, dict_t *argdict)
428
struct gf_set_descriptor sd = {
436
gf_boolean_t match = _gf_false;
438
for (i = 0; i < mspec->len; i++) {
439
relate_sets(&sd, argdict, mspec->patterns[i].components);
440
switch (mspec->patterns[i].condition) {
448
match = (!sd.priv[0] && !sd.priv[1]);
454
GF_ASSERT(!"unreached");
456
if (mspec->patterns[i].negative)
460
gf_msg(this->name, GF_LOG_ERROR, EPERM,
461
GD_MSG_MNTBROKER_SPEC_MISMATCH,
462
"Mountbroker spec mismatch!!! SET: %d "
463
"COMPONENT: %d. Review the mount args passed",
464
mspec->patterns[i].condition, i);
469
ret = seq_dict_foreach(argdict, _arg_parse_uid, &uid);
477
_volname_get(char *val, void *data)
479
char **volname = data;
481
*volname = strtail(val, "volfile-id=");
483
return *volname ? 1 : 0;
487
_runner_add(char *val, void *data)
489
runner_t *runner = data;
491
runner_argprintf(runner, "--%s", val);
497
glusterd_do_mount(char *label, dict_t *argdict, char **path, int *op_errno)
499
glusterd_conf_t *priv = NULL;
500
char *mountbroker_root = NULL;
501
gf_mount_spec_t *mspec = NULL;
503
char *volname = NULL;
504
glusterd_volinfo_t *vol = NULL;
505
char *mtptemp = NULL;
506
char *mntlink = NULL;
507
char *cookieswitch = NULL;
517
xlator_t *this = THIS;
518
mode_t orig_umask = 0;
519
gf_boolean_t found_label = _gf_false;
521
priv = this->private;
527
if (dict_get_str(this->options, "mountbroker-root", &mountbroker_root) !=
530
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
531
"'option mountbroker-root' "
532
"missing in glusterd vol file");
539
gf_msg(this->name, GF_LOG_ERROR, *op_errno, GD_MSG_MNTBROKER_LABEL_NULL,
540
"label is NULL (%s)", strerror(*op_errno));
545
cds_list_for_each_entry(mspec, &priv->mount_specs, speclist)
547
if (strcmp(mspec->label, label) != 0)
550
found_label = _gf_true;
551
uid = evaluate_mount_request(this, mspec, argdict);
557
gf_msg(this->name, GF_LOG_ERROR, *op_errno,
558
GD_MSG_MNTBROKER_LABEL_MISS,
559
"Missing mspec: Check the corresponding option "
560
"in glusterd vol file for mountbroker user: %s",
567
seq_dict_foreach(argdict, _volname_get, &volname);
570
gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_DICT_GET_FAILED,
571
"Dict get failed for the key 'volname'");
574
if (glusterd_volinfo_find(volname, &vol) != 0 ||
575
!glusterd_is_volume_started(vol)) {
577
gf_msg(this->name, GF_LOG_ERROR, *op_errno, GD_MSG_MOUNT_REQ_FAIL,
578
"Either volume is not started or volinfo not found");
588
ret = gf_asprintf(&mtptemp, "%s/user%d/mtpt-%s-XXXXXX/cookie",
589
mountbroker_root, uid, label);
596
cookieswitch = strrchr(mtptemp, '/');
597
*cookieswitch = '\0';
599
sla = strrchr(mtptemp, '/');
601
ret = sys_mkdir(mtptemp, 0700);
603
ret = sys_chown(mtptemp, uid, 0);
604
else if (errno == EEXIST)
608
gf_msg(this->name, GF_LOG_ERROR, *op_errno, GD_MSG_SYSCALL_FAIL,
609
"Mountbroker User directory creation failed");
612
ret = sys_lstat(mtptemp, &st);
615
gf_msg(this->name, GF_LOG_ERROR, *op_errno, GD_MSG_SYSCALL_FAIL,
616
"stat on mountbroker user directory failed");
619
if (!(S_ISDIR(st.st_mode) && (st.st_mode & ~S_IFMT) == 0700 &&
620
st.st_uid == uid && st.st_gid == 0)) {
622
gf_msg(this->name, GF_LOG_ERROR, *op_errno, GD_MSG_MOUNT_REQ_FAIL,
623
"Incorrect mountbroker user directory attributes");
628
if (!mkdtemp(mtptemp)) {
630
gf_msg(this->name, GF_LOG_ERROR, *op_errno, GD_MSG_SYSCALL_FAIL,
631
"Mountbroker mount directory creation failed");
638
ret = gf_asprintf(&cookie, "%s/" MB_HIVE "/mntXXXXXX", mountbroker_root);
644
orig_umask = umask(S_IRWXG | S_IRWXO);
645
ret = mkstemp(cookie);
649
gf_msg(this->name, GF_LOG_ERROR, *op_errno, GD_MSG_SYSCALL_FAIL,
650
"Mountbroker cookie file creation failed");
656
sla = strchr(sla - 1, '/');
658
ret = gf_asprintf(&mntlink, "../user%d%s", uid, sla);
667
ret = sys_symlink(mntlink, mtptemp);
669
ret = sys_rename(mtptemp, cookie);
670
*cookieswitch = '\0';
673
gf_msg(this->name, GF_LOG_ERROR, *op_errno, GD_MSG_SYSCALL_FAIL,
674
"symlink or rename failed");
681
runner_add_arg(&runner, SBIN_DIR "/glusterfs");
682
seq_dict_foreach(argdict, _runner_add, &runner);
683
runner_add_arg(&runner, mtptemp);
684
ret = runner_run_reuse(&runner);
687
runner_log(&runner, "", GF_LOG_ERROR, "command failed");
695
gf_msg(this->name, GF_LOG_WARNING, *op_errno, GD_MSG_MOUNT_REQ_FAIL,
696
"unsuccessful mount request");
700
*cookieswitch = '\0';