[Ocfs2-tools-devel] [PATCH 4/6] O2info: Add running codes for '--fs-features'.
Sunil Mushran
sunil.mushran at oracle.com
Fri Apr 23 15:34:53 PDT 2010
Tristan Ye wrote:
> Task of dumping fs features will also be capable of two approaches,
> including libocfs2 and ioctl methods.
>
> Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
> ---
> o2info/o2info.c | 16 +++++
> o2info/operations.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++
> o2info/utils.c | 66 ++++++++++++++++++++
> o2info/utils.h | 4 +
> 4 files changed, 252 insertions(+), 0 deletions(-)
>
> diff --git a/o2info/o2info.c b/o2info/o2info.c
> index 28601dd..1e281d9 100644
> --- a/o2info/o2info.c
> +++ b/o2info/o2info.c
> @@ -34,6 +34,8 @@
>
> #include "utils.h"
>
> +extern struct o2info_operation fs_features_op;
> +
> static LIST_HEAD(o2info_op_task_list);
> static int o2info_op_task_count;
> int cluster_coherent;
> @@ -98,10 +100,24 @@ static struct o2info_option coherency_option = {
> .opt_private = NULL,
> };
>
> +static struct o2info_option fs_features_option = {
> + .opt_option = {
> + .name = "fs-features",
> + .val = CHAR_MAX,
> + .has_arg = 0,
> + .flag = NULL,
> + },
> + .opt_help = " --fs-features",
> + .opt_handler = NULL,
> + .opt_op = &fs_features_op,
> + .opt_private = NULL,
> +};
> +
> static struct o2info_option *options[] = {
> &help_option,
> &version_option,
> &coherency_option,
> + &fs_features_option,
> NULL,
> };
>
> diff --git a/o2info/operations.c b/o2info/operations.c
> index ad719a4..d2a190c 100644
> --- a/o2info/operations.c
> +++ b/o2info/operations.c
> @@ -59,3 +59,169 @@ static void o2i_error(struct o2info_operation *op, const char *fmt, ...)
>
> return;
> }
> +
> +struct o2info_fs_features {
> + uint32_t compat;
> + uint32_t incompat;
> + uint32_t rocompat;
> +};
> +
> +static int get_fs_features_ioctl(struct o2info_operation *op,
> + int fd,
> + struct o2info_fs_features *ofs)
> +{
> + int rc = 0, flags = 0;
> + struct ocfs2_info_fs_features oif;
> +
> + memset(ofs, 0, sizeof(*ofs));
> + flags |= cluster_coherent;
> +
> + o2info_fill_request((struct ocfs2_info_request *)&oif, sizeof(oif),
> + OCFS2_INFO_FS_FEATURES, flags);
> +
> + uint64_t reqs[1] = {(unsigned long)&oif};
>
Plain C please. Keep the declarations at the top of the function.
> +
> + struct ocfs2_info info = {
> + .oi_requests = (uint64_t)reqs,
> + .oi_count = 1,
> + };
> +
> + rc = ioctl(fd, OCFS2_IOC_INFO, &info);
> + if (rc) {
> + rc = errno;
> + o2i_error(op, "ioctl failed: %s\n", strerror(rc));
> + goto out;
> + }
> +
> + if (oif.if_req.ir_flags & OCFS2_INFO_FL_FILLED) {
> + ofs->compat = oif.if_compat_features;
> + ofs->incompat = oif.if_incompat_features;
> + ofs->rocompat = oif.if_ro_compat_features;
> + }
> +
> +out:
> + return rc;
> +}
>
What happens if rc == 0 and flags is not FILLED. Best if
we ensure that cannot happen. As in, kernel should return
an error if it is not filled.
> +
> +static int get_fs_features_libocfs2(struct o2info_operation *op,
> + ocfs2_filesys *fs,
> + struct o2info_fs_features *ofs)
> +{
> + int rc = 0;
> + struct ocfs2_super_block *sb = NULL;
> +
> + memset(ofs, 0, sizeof(*ofs));
> +
> + sb = OCFS2_RAW_SB(fs->fs_super);
> + ofs->compat = sb->s_feature_compat;
> + ofs->incompat = sb->s_feature_incompat;
> + ofs->rocompat = sb->s_feature_ro_compat;
> +
> + return rc;
> +}
> +
> +static void o2info_print_line(char const *title, char *content, char splitter)
> +{
> + char *ptr = NULL, *token = NULL, *tmp = NULL;
> + uint32_t max_len = 80, len = 0;
> +
> + tmp = malloc(max_len);
> + ptr = content;
> +
> + snprintf(tmp, max_len, "%s", title);
> + fprintf(stdout, "%s", tmp);
> + len += strlen(tmp);
> +
> + while (ptr) {
> +
> + token = ptr;
> + ptr = strchr(ptr, splitter);
> +
> + if (ptr)
> + *ptr = 0;
> +
> + if (strcmp(token, "") != 0) {
> + snprintf(tmp, max_len, " %s", token);
> + len += strlen(tmp);
> + if (len > max_len) {
> + fprintf(stdout, "\n");
> + len = 0;
> + snprintf(tmp, max_len, "%s", title);
> + fprintf(stdout, "%s", tmp);
> + len += strlen(tmp);
> + snprintf(tmp, max_len, " %s", token);
> + fprintf(stdout, "%s", tmp);
> + len += strlen(tmp);
> + } else
> + fprintf(stdout, "%s", tmp);
> + }
> +
> + if (!ptr)
> + break;
> +
> + ptr++;
> + }
> +
> + fprintf(stdout, "\n");
> +
> + if (tmp)
> + ocfs2_free(&tmp);
> +}
> +
> +static int fs_features_run(struct o2info_operation *op,
> + struct o2info_method *om,
> + void *arg)
> +{
> + int rc = 0;
> + static struct o2info_fs_features ofs;
> +
> + char *compat = NULL;
> + char *incompat = NULL;
> + char *rocompat = NULL;
> + char *features = NULL;
> +
> + if (om->om_method == O2INFO_USE_IOCTL)
> + rc = get_fs_features_ioctl(op, om->om_fd, &ofs);
> + else
> + rc = get_fs_features_libocfs2(op, om->om_fs, &ofs);
> + if (rc)
> + goto out;
> +
> + rc = o2info_get_compat_flag(ofs.compat, &compat);
> + if (rc)
> + goto out;
> +
> + rc = o2info_get_incompat_flag(ofs.incompat, &incompat);
> + if (rc)
> + goto out;
> +
> + rc = o2info_get_rocompat_flag(ofs.rocompat, &rocompat);
> + if (rc)
> + goto out;
> +
> + features = malloc(strlen(compat) + strlen(incompat) +
> + strlen(rocompat) + 3);
> +
> + sprintf(features, "%s %s %s", compat, incompat, rocompat);
> +
> + o2info_print_line("Features:", features, ' ');
> +
> +out:
> + if (compat)
> + ocfs2_free(&compat);
> +
> + if (incompat)
> + ocfs2_free(&incompat);
> +
> + if (rocompat)
> + ocfs2_free(&rocompat);
> +
> + if (features)
> + ocfs2_free(&features);
> +
> + return rc;
> +}
> +
> +DEFINE_O2INFO_OP(fs_features,
> + fs_features_run,
> + NULL);
> diff --git a/o2info/utils.c b/o2info/utils.c
> index 0911c50..85b2fdf 100644
> --- a/o2info/utils.c
> +++ b/o2info/utils.c
> @@ -31,6 +31,72 @@
>
> #include "utils.h"
>
> +int o2info_get_compat_flag(uint32_t flag, char **compat)
> +{
> + errcode_t err;
> + char buf[PATH_MAX];
> + ocfs2_fs_options flags = {
> + .opt_compat = flag,
> + };
> +
> + *buf = '\0';
> + err = ocfs2_snprint_feature_flags(buf, PATH_MAX, &flags);
> + if (!err) {
> + *compat = strdup(buf);
> + if (!*compat) {
> + errorf("No memory for allocation\n");
> + err = -1;
> + }
> + } else
> + tcom_err(err, "while processing feature flags");
>
see note below
> +
> + return err;
> +}
> +
> +int o2info_get_incompat_flag(uint32_t flag, char **incompat)
> +{
> + errcode_t err;
> + char buf[PATH_MAX];
> + ocfs2_fs_options flags = {
> + .opt_incompat = flag,
> + };
> +
> + *buf = '\0';
> + err = ocfs2_snprint_feature_flags(buf, PATH_MAX, &flags);
> + if (!err) {
> + *incompat = strdup(buf);
> + if (!*incompat) {
> + errorf("No memory for allocation\n");
> + err = -1;
> + }
> + } else
> + tcom_err(err, "while processing feature flags");
>
see note below
> +
> + return err;
> +}
> +
> +int o2info_get_rocompat_flag(uint32_t flag, char **rocompat)
> +{
> + errcode_t err;
> + char buf[PATH_MAX];
> + ocfs2_fs_options flags = {
> + .opt_ro_compat = flag,
> + };
> +
> + *buf = '\0';
> + err = ocfs2_snprint_feature_flags(buf, PATH_MAX, &flags);
> + if (!err) {
> + *rocompat = strdup(buf);
> + if (!*rocompat) {
> + errorf("No memory for allocation\n");
> + err = -1;
> + }
> + } else
> + tcom_err(err, "while processing feature flags");
>
A better flow is:
+ err = ocfs2_snprint_feature_flags(buf, PATH_MAX, &flags);
+ if (err) {
+ tcom_err(err, "while processing feature flags");
+ goto bail;
+ }
+
+ *rocompat = strdup(buf);
+ if (!*rocompat) {
+ errorf("No memory for allocation");
+ err = -1;
+ }
+bail:
The idea is to minimize the levels of indentation.
> +
> + return err;
> +}
> +
> errcode_t o2info_open(struct o2info_method *om, int flags)
> {
> errcode_t err = 0;
> diff --git a/o2info/utils.h b/o2info/utils.h
> index 6d55d39..69446c2 100644
> --- a/o2info/utils.h
> +++ b/o2info/utils.h
> @@ -22,6 +22,10 @@
>
> #include "o2info.h"
>
> +int o2info_get_compat_flag(uint32_t flag, char **compat);
> +int o2info_get_incompat_flag(uint32_t flag, char **incompat);
> +int o2info_get_rocompat_flag(uint32_t flag, char **rocompat);
> +
> int o2info_method(const char *path);
>
> errcode_t o2info_open(struct o2info_method *om, int flags);
>
More information about the Ocfs2-tools-devel
mailing list