[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Cluster-devel] [PATCH 3/7] gfs2l: Enable setting the type of a block



This adds an optional type specifier to the set statement so that when
you do

   set 12345 <type> { ... }

the block's meta header fields will be set to that of <type> where
<type> is a structure name e.g. gfs2_rgrp.

This is useful for setting unallocated blocks to a certain block type
as the type can't be inferred from an existing meta header.

Signed-off-by: Andrew Price <anprice redhat com>
---
 gfs2/libgfs2/lang.c    | 41 ++++++++++++++++++++++++++++++++++-------
 gfs2/libgfs2/lang.h    |  1 +
 gfs2/libgfs2/libgfs2.h |  1 +
 gfs2/libgfs2/meta.c    | 15 +++++++++++++++
 gfs2/libgfs2/parser.y  | 12 ++++++++++++
 5 files changed, 63 insertions(+), 7 deletions(-)

diff --git a/gfs2/libgfs2/lang.c b/gfs2/libgfs2/lang.c
index 069750f..28805b5 100644
--- a/gfs2/libgfs2/lang.c
+++ b/gfs2/libgfs2/lang.c
@@ -27,6 +27,7 @@ const char* ast_type_string[] = {
 	[AST_EX_BLOCKSPEC] = "BLOCKSPEC",
 	[AST_EX_STRUCTSPEC] = "STRUCTSPEC",
 	[AST_EX_FIELDSPEC] = "FIELDSPEC",
+	[AST_EX_TYPESPEC] = "TYPESPEC",
 
 	// Keywords
 	[AST_KW_STATE] = "STATE",
@@ -64,6 +65,7 @@ static int ast_expr_init(struct ast_node *expr, ast_node_t type, const char *str
 	case AST_EX_BLOCKSPEC:
 	case AST_EX_STRUCTSPEC:
 	case AST_EX_FIELDSPEC:
+	case AST_EX_TYPESPEC:
 	case AST_KW_STATE:
 		break;
 	default:
@@ -173,7 +175,6 @@ static uint64_t ast_lookup_path(char *path, struct gfs2_sbd *sbd)
 		segment = strtok_r(NULL, "/", &c);
 	}
 
-	perror("Path lookup");
 	return 0;
 }
 
@@ -263,6 +264,8 @@ static uint64_t ast_lookup_block_num(struct ast_node *ast, struct gfs2_sbd *sbd)
 		bn = ast_lookup_block_num(ast->ast_left, sbd) + ast->ast_num;
 		break;
 	case AST_EX_ADDRESS:
+		if (gfs2_check_range(sbd, ast->ast_num))
+			break;
 		bn = ast->ast_num;
 		break;
 	case AST_EX_PATH:
@@ -284,6 +287,7 @@ static struct gfs2_buffer_head *ast_lookup_block(struct ast_node *node, struct g
 {
 	uint64_t bn = ast_lookup_block_num(node, sbd);
 	if (bn == 0) {
+		fprintf(stderr, "Block not found: %s\n", node->ast_text);
 		return NULL;
 	}
 
@@ -526,6 +530,23 @@ static int ast_field_set(struct gfs2_buffer_head *bh, const struct lgfs2_metafie
 	return AST_INTERP_INVAL;
 }
 
+static const struct lgfs2_metadata *lang_find_mtype(struct ast_node *node, struct gfs2_buffer_head *bh, unsigned ver)
+{
+	const struct lgfs2_metadata *mtype = NULL;
+
+	if (node->ast_type == AST_EX_TYPESPEC) {
+		mtype = lgfs2_find_mtype_name(node->ast_str, ver);
+		if (mtype == NULL)
+			fprintf(stderr, "Invalid block type: %s\n", node->ast_text);
+	} else {
+		mtype = lgfs2_find_mtype(lgfs2_get_block_type(bh), ver);
+		if (mtype == NULL)
+			fprintf(stderr, "Unrecognised block at: %s\n", node->ast_text);
+	}
+
+	return mtype;
+}
+
 /**
  * Interpret an assignment (set)
  */
@@ -536,9 +557,9 @@ static struct lgfs2_lang_result *ast_interp_set(struct lgfs2_lang_state *state,
 	struct ast_node *fieldspec;
 	struct ast_node *fieldname;
 	struct ast_node *fieldval;
-	uint32_t mh_type = 0;
 	int i = 0;
 	int ret = 0;
+	unsigned ver = sbd->gfs1 ? LGFS2_MD_GFS1 : LGFS2_MD_GFS2;
 
 	struct lgfs2_lang_result *result = calloc(1, sizeof(struct lgfs2_lang_result));
 	if (result == NULL) {
@@ -551,14 +572,20 @@ static struct lgfs2_lang_result *ast_interp_set(struct lgfs2_lang_state *state,
 		goto out_err;
 	}
 
-	mh_type = lgfs2_get_block_type(result->lr_bh);
-	if (mh_type == 0) {
+	result->lr_mtype = lang_find_mtype(lookup->ast_right, result->lr_bh, ver);
+	if (result->lr_mtype == NULL) {
+		fprintf(stderr, "Unrecognised block at: %s\n", lookup->ast_str);
 		goto out_err;
 	}
 
-	result->lr_mtype = lgfs2_find_mtype(mh_type, sbd->gfs1 ? LGFS2_MD_GFS1 : LGFS2_MD_GFS2);
-	if (result->lr_mtype == NULL) {
-		goto out_err;
+	if (lookup->ast_right->ast_type == AST_EX_TYPESPEC) {
+		struct gfs2_meta_header mh = {
+			.mh_magic = GFS2_MAGIC,
+			.mh_type = result->lr_mtype->mh_type,
+			.mh_format = result->lr_mtype->mh_format,
+		};
+		gfs2_meta_header_out(&mh, result->lr_bh->iov.iov_base);
+		lookup = lookup->ast_right;
 	}
 
 	for (fieldspec = lookup->ast_right;
diff --git a/gfs2/libgfs2/lang.h b/gfs2/libgfs2/lang.h
index 955e52e..7d9a6e9 100644
--- a/gfs2/libgfs2/lang.h
+++ b/gfs2/libgfs2/lang.h
@@ -30,6 +30,7 @@ typedef enum {
 	AST_EX_BLOCKSPEC,
 	AST_EX_STRUCTSPEC,
 	AST_EX_FIELDSPEC,
+	AST_EX_TYPESPEC,
 
 	// Keywords
 	AST_KW_STATE,
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 997e23f..55847c8 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -356,6 +356,7 @@ extern const struct lgfs2_symbolic lgfs2_ld1_types[];
 extern const unsigned lgfs2_ld1_type_size;
 extern int lgfs2_selfcheck(void);
 extern const struct lgfs2_metadata *lgfs2_find_mtype(uint32_t mh_type, const unsigned versions);
+extern const struct lgfs2_metadata *lgfs2_find_mtype_name(const char *name, const unsigned versions);
 
 /* bitmap.c */
 struct gfs2_bmap {
diff --git a/gfs2/libgfs2/meta.c b/gfs2/libgfs2/meta.c
index dc22e9a..94be823 100644
--- a/gfs2/libgfs2/meta.c
+++ b/gfs2/libgfs2/meta.c
@@ -1,4 +1,5 @@
 #include <stdint.h>
+#include <string.h>
 #include "libgfs2.h"
 
 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
@@ -821,3 +822,17 @@ const struct lgfs2_metadata *lgfs2_find_mtype(uint32_t mh_type, const unsigned v
 
 	return NULL;
 }
+
+const struct lgfs2_metadata *lgfs2_find_mtype_name(const char *name, const unsigned versions)
+{
+	const struct lgfs2_metadata *m = lgfs2_metadata;
+	unsigned n = 0;
+
+	do {
+		if ((m[n].versions & versions) && !strcmp(m[n].name, name))
+			return &m[n];
+		n++;
+	} while (n < lgfs2_metadata_size);
+
+	return NULL;
+}
diff --git a/gfs2/libgfs2/parser.y b/gfs2/libgfs2/parser.y
index 0321d74..d60c1af 100644
--- a/gfs2/libgfs2/parser.y
+++ b/gfs2/libgfs2/parser.y
@@ -65,6 +65,12 @@ set_stmt:	TOK_SET blockspec structspec {
 			$2->ast_right = $3;
 			$$ = $1;
 		}
+		| TOK_SET blockspec typespec structspec {
+			$1->ast_right = $2;
+			$2->ast_right = $3;
+			$3->ast_right = $4;
+			$$ = $1;
+		}
 ;
 get_stmt:	TOK_GET blockspec { $1->ast_right = $2; $$ = $1; }
 		| TOK_GET blockspec TOK_STATE {
@@ -84,6 +90,11 @@ offset:		blockspec TOK_OFFSET {
 			$$ = $2;
 		}
 ;
+typespec:	identifier {
+			$1->ast_type = AST_EX_TYPESPEC;
+			$$ = $1;
+		}
+;
 block_literal:	identifier		{ $$ = $1; }
 ;
 subscript:	block_literal TOK_LBRACKET index TOK_RBRACKET {
@@ -107,6 +118,7 @@ path:		string			{
 		}
 ;
 structspec:	TOK_LBRACE fieldspecs TOK_RBRACE { $$ = $2; }
+structspec:	TOK_LBRACE TOK_RBRACE            { $$ = NULL; }
 ;
 fieldspecs:	fieldspecs TOK_COMMA fieldspec	{ $1->ast_left = $3; $$ = $1; }
 		| fieldspec			{ $$ = $1; }
-- 
1.8.1.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]