Skip to content

Commit

Permalink
fuse, meta: make fuse options adjustable via .meta [WIP]
Browse files Browse the repository at this point in the history
The .meta synthetic tree features the options entry
for each xlator, which lets us see the options with
which the translator was configured. Technically,
'options' exports the options dict with which the
given xlator has been configured. This approach
provides read-only access to the xlator options,
and only those options are visible which has been
set.

We implement an alternative options entry (referred
to as 'aadjustable options' in the sequel) that
exports the full option set of the xlator. We
extended the volume_options stucture wih 'fetch'
and 'update' methods, that facilitate access to
the realtime values of the xlator options. In
the adjustable options dict each option is readable
which has 'fetch' and if they have 'update' too,
then they shall be writable (this is properly
reflected in file modes since 2554080).

While the dict-based options is generic and provides
an export mechanism for xlator options without specific
support from the xlators, adjustable options will export
only those options for which the xlator implements
fetch/update.

We made this effort for the fuse xlator, which is positioned
in glusterfs client as the root of the xlator tree, and thus
can't be 'hot-swapped' like other xlators via graph switch.

All the fuse options obained 'fetch'; and the ones where
runtime update is possible also 'update' (ie. those which
control the internal behavior of the filesystem server, can
be updated; the ones which are mount options or init options
for the FUSE infrastucture, can't).

**
THIS IS A WIP implementation, misses one thing: adjustability
of fuse dumping, which will need more specific support code due
to the involvement of external resource
**

Change-Id: I72cb0f3c2f93712cd08147a4ae2e076354d8d9d8
Fixes: gluster#1785
Signed-off-by: Csaba Henk <csaba@redhat.com>
  • Loading branch information
csabahenk committed Oct 20, 2021
1 parent 51f4118 commit acea56d
Show file tree
Hide file tree
Showing 13 changed files with 945 additions and 257 deletions.
6 changes: 6 additions & 0 deletions libglusterfs/src/glusterfs/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@ typedef struct volume_options {

/* Flag to understand how this option is categorized */
gf_category_t category;

/* Method to get the actual value of the option */
char *(*fetch)(struct volume_options *opt, xlator_t *this);

/* Method to set the value of the option */
int (*update)(struct volume_options *opt, xlator_t *this, char *data);
} volume_option_t;

typedef struct vol_opt_list {
Expand Down
12 changes: 9 additions & 3 deletions xlators/meta/src/loglevel-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,21 @@ loglevel_file_fill(xlator_t *this, inode_t *file, strfd_t *strfd)
}

static int
loglevel_file_write(xlator_t *this, fd_t *fd, struct iovec *iov, int count)
loglevel_file_write_str(xlator_t *this, fd_t *fd, char *str)
{
long int level = -1;

level = strtol(iov[0].iov_base, NULL, 0);
level = strtol(str, NULL, 0);
if (level >= GF_LOG_NONE && level <= GF_LOG_TRACE)
gf_log_set_loglevel(this->ctx, level);

return iov_length(iov, count);
return strlen(str);
}

static int
loglevel_file_write(xlator_t *this, fd_t *fd, struct iovec *iov, int count)
{
return file_write_wrapper(this, fd, iov, count, loglevel_file_write_str);
}

static struct meta_ops loglevel_file_ops = {
Expand Down
12 changes: 9 additions & 3 deletions xlators/meta/src/measure-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,20 @@ measure_file_fill(xlator_t *this, inode_t *file, strfd_t *strfd)
}

static int
measure_file_write(xlator_t *this, fd_t *fd, struct iovec *iov, int count)
measure_file_write_str(xlator_t *this, fd_t *fd, char *str)
{
long int num = -1;

num = strtol(iov[0].iov_base, NULL, 0);
num = strtol(str, NULL, 0);
this->ctx->measure_latency = !!num;

return iov_length(iov, count);
return strlen(str);
}

static int
measure_file_write(xlator_t *this, fd_t *fd, struct iovec *iov, int count)
{
return file_write_wrapper(this, fd, iov, count, measure_file_write_str);
}

static struct meta_ops measure_file_ops = {
Expand Down
33 changes: 33 additions & 0 deletions xlators/meta/src/meta-helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,3 +331,36 @@ fixed_dirents_len(struct meta_dirent *dirents)

return i;
}

int
file_write_wrapper(xlator_t *this, fd_t *fd, struct iovec *iov, int count,
int (*file_write_str)(xlator_t *this, fd_t *fd, char *str))
{
int i = 0;
int j = 0;
size_t tlen = 0;
char *str = NULL;
char *p = NULL;
int ret = 0;

for (i = 0; i < count; i++) {
for (j = 0; j < iov[i].iov_len; j++) {
if (((char *)iov[i].iov_base)[j] == 0)
return -EINVAL;
}
tlen += iov[i].iov_len;
}
str = GF_MALLOC(tlen + 1, gf_meta_mt_writestr_t);
if (!str)
return -1;
p = str;
for (i = 0; i < count; i++) {
memcpy(p, iov[i].iov_base, iov[i].iov_len);
p += iov[i].iov_len;
}
str[tlen] = 0;
ret = file_write_str(this, fd, str);

GF_FREE(str);
return ret;
}
3 changes: 3 additions & 0 deletions xlators/meta/src/meta-hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ DECLARE_HOOK(type_file);
DECLARE_HOOK(version_file);
DECLARE_HOOK(options_dir);
DECLARE_HOOK(option_file);
DECLARE_HOOK(adjustable_options_dir);
DECLARE_HOOK(adjustable_option_file);
DECLARE_HOOK(adjustable_option_link);
DECLARE_HOOK(cmdline_file);
DECLARE_HOOK(name_file);
DECLARE_HOOK(private_file);
Expand Down
1 change: 1 addition & 0 deletions xlators/meta/src/meta-mem-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ enum gf_meta_mem_types_ {
gf_meta_mt_strfd_t,
gf_meta_mt_dirents_t,
gf_meta_mt_local_t,
gf_meta_mt_writestr_t,
gf_meta_mt_end
};
#endif
6 changes: 6 additions & 0 deletions xlators/meta/src/meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ struct meta_ops {
int (*file_fill)(xlator_t *this, inode_t *file, strfd_t *strfd);
int (*iatt_fill)(xlator_t *this, inode_t *inode, struct iatt *iatt);
int (*link_fill)(xlator_t *this, inode_t *inode, strfd_t *strfd);
int (*file_write_vec)(xlator_t *this, fd_t *fd, struct iovec *iov,
int count);
int (*file_write)(xlator_t *this, fd_t *fd, struct iovec *iov, int count);
struct xlator_fops fops;
struct xlator_cbks cbks;
Expand Down Expand Up @@ -137,4 +139,8 @@ meta_dir_fill(xlator_t *this, fd_t *fd);

int
fixed_dirents_len(struct meta_dirent *dirents);

int
file_write_wrapper(xlator_t *this, fd_t *fd, struct iovec *iov, int count,
int (*file_write_buf)(xlator_t *this, fd_t *fd, char *buf));
#endif /* __META_H__ */
151 changes: 151 additions & 0 deletions xlators/meta/src/option-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,154 @@ meta_option_file_hook(call_frame_t *frame, xlator_t *this, loc_t *loc,

return 0;
}

/* adjustable variant */

static volume_option_t *
find_volopt(xlator_t *xl, char *key)
{
volume_opt_list_t *vol_opt_list = NULL;
volume_option_t *vol_opt = NULL;
int i = 0;

list_for_each_entry(vol_opt_list, &xl->volume_options, list)
{
vol_opt = vol_opt_list->given_opt;
while (vol_opt->key[0]) {
if (vol_opt->fetch) {
for (i = 0; i < ZR_VOLUME_MAX_NUM_KEY; i++) {
if (vol_opt->key[i]) {
if (strcmp(vol_opt->key[i], key) == 0)
return vol_opt;
} else
break;
}
}
vol_opt++;
}
}

return NULL;
}

static int
adjustable_option_file_fill(xlator_t *this, inode_t *inode, strfd_t *strfd)
{
volume_option_t *vol_opt = NULL;
char *optval = NULL;
xlator_t *xl = NULL;
dentry_t *dentry = NULL;
dentry_t *trav = NULL;

xl = meta_ctx_get(inode, this);
list_for_each_entry(trav, &inode->dentry_list, inode_list)
{
dentry = trav;
break;
}
vol_opt = find_volopt(xl, dentry->name);
optval = vol_opt->fetch(vol_opt, xl);

strprintf(strfd, "%s\n", optval);
GF_FREE(optval);

return strfd->size;
}

static int
adjustable_option_file_write_str(xlator_t *this, fd_t *fd, char *str)
{
volume_option_t *vol_opt = NULL;
xlator_t *xl = NULL;
dentry_t *dentry = NULL;
dentry_t *trav = NULL;
int ret = 0;
size_t len = 0;

len = strlen(str);
if (len == 0)
return -EINVAL;
/* chomp str to avoid failing conversions due to trailing newline */
if (str[len - 1] == '\n')
str[len - 1] = 0;

xl = meta_ctx_get(fd->inode, this);
list_for_each_entry(trav, &fd->inode->dentry_list, inode_list)
{
dentry = trav;
break;
}
vol_opt = find_volopt(xl, dentry->name);
ret = vol_opt->update(vol_opt, xl, str);

return (ret == -1) ? -EINVAL : len;
}

static int
adjustable_option_file_write(xlator_t *this, fd_t *fd, struct iovec *iov,
int count)
{
return file_write_wrapper(this, fd, iov, count,
adjustable_option_file_write_str);
}

static struct meta_ops adjustable_option_file_ops = {
.file_fill = adjustable_option_file_fill};

static struct meta_ops adjustable_option_file_rw_ops = {
.file_fill = adjustable_option_file_fill,
.file_write = adjustable_option_file_write};

int
meta_adjustable_option_file_hook(call_frame_t *frame, xlator_t *this,
loc_t *loc, dict_t *xdata)
{
xlator_t *xl = NULL;
volume_option_t *vol_opt = NULL;

xl = meta_ctx_get(loc->parent, this);
meta_ctx_set(loc->inode, this, xl);

vol_opt = find_volopt(xl, (char *)loc->name);
meta_ops_set(loc->inode, this,
vol_opt->update ? &adjustable_option_file_rw_ops
: &adjustable_option_file_ops);

return 0;
}

static int
adjustable_option_link_fill(xlator_t *this, inode_t *inode, strfd_t *strfd)
{
volume_option_t *vol_opt = NULL;
;
xlator_t *xl = NULL;
dentry_t *dentry = NULL;
dentry_t *trav = NULL;

xl = meta_ctx_get(inode, this);
list_for_each_entry(trav, &inode->dentry_list, inode_list)
{
dentry = trav;
break;
}
vol_opt = find_volopt(xl, dentry->name);

strprintf(strfd, "%s", vol_opt->key[0]);

return 0;
}

static struct meta_ops adjustable_option_link_ops = {
.link_fill = adjustable_option_link_fill};

int
meta_adjustable_option_link_hook(call_frame_t *frame, xlator_t *this,
loc_t *loc, dict_t *xdata)
{
meta_ctx_set(loc->inode, this, meta_ctx_get(loc->parent, this));

meta_ops_set(loc->inode, this, &adjustable_option_link_ops);

return 0;
}
76 changes: 76 additions & 0 deletions xlators/meta/src/options-dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,72 @@ options_dir_fill(xlator_t *this, inode_t *inode, struct meta_dirent **dp)
return xl->options->count;
}

static int
adjustable_options_dir_fill(xlator_t *this, inode_t *inode,
struct meta_dirent **dp)
{
int count = 0;
int i = 0;
volume_opt_list_t *vol_opt_list = NULL;
volume_option_t *vol_opt = NULL;
struct meta_dirent *dirent = NULL;
struct meta_dirent *direntp = NULL;
xlator_t *xl = NULL;

xl = meta_ctx_get(inode, this);

list_for_each_entry(vol_opt_list, &xl->volume_options, list)
{
vol_opt = vol_opt_list->given_opt;
while (vol_opt->key[0]) {
if (vol_opt->fetch) {
for (i = 0; i < ZR_VOLUME_MAX_NUM_KEY; i++) {
if (vol_opt->key[i])
count++;
else
break;
}
}
vol_opt++;
}
}
dirent = GF_CALLOC(sizeof(*dirent), count, gf_meta_mt_dirents_t);
if (!dirent)
return -1;

direntp = dirent;

list_for_each_entry(vol_opt_list, &xl->volume_options, list)
{
vol_opt = vol_opt_list->given_opt;
while (vol_opt->key[0]) {
if (vol_opt->fetch) {
direntp->name = gf_strdup(vol_opt->key[0]);
direntp->type = IA_IFREG;
direntp->hook = meta_adjustable_option_file_hook;
direntp++;
for (i = 1; i < ZR_VOLUME_MAX_NUM_KEY; i++) {
if (vol_opt->key[i]) {
direntp->name = gf_strdup(vol_opt->key[i]);
direntp->type = IA_IFLNK;
direntp->hook = meta_adjustable_option_link_hook;
direntp++;
} else
break;
}
}
vol_opt++;
}
}

*dp = dirent;

return count;
}

static struct meta_ops options_dir_ops = {.dir_fill = options_dir_fill};
static struct meta_ops adjustable_options_dir_ops = {
.dir_fill = adjustable_options_dir_fill};

int
meta_options_dir_hook(call_frame_t *frame, xlator_t *this, loc_t *loc,
Expand All @@ -63,3 +128,14 @@ meta_options_dir_hook(call_frame_t *frame, xlator_t *this, loc_t *loc,

return 0;
}

int
meta_adjustable_options_dir_hook(call_frame_t *frame, xlator_t *this,
loc_t *loc, dict_t *xdata)
{
meta_ctx_set(loc->inode, this, meta_ctx_get(loc->parent, this));

meta_ops_set(loc->inode, this, &adjustable_options_dir_ops);

return 0;
}

0 comments on commit acea56d

Please sign in to comment.