[SCM] SAMBA-CTDB repository - branch v3-2-ctdb updated - build_3.2.11_ctdb.60-6-g2f66b4d

Michael Adam obnox at samba.org
Mon May 18 11:05:59 GMT 2009


The branch, v3-2-ctdb has been updated
       via  2f66b4d266b76125c25a5e5ff27db6c74cb76a6a (commit)
       via  38d01dadc5953eb340ce1234865a8d1067402163 (commit)
       via  94e01617e02be80980ce82ce548c712fa01dc569 (commit)
       via  85cd942697db131baa74cf97c27c34f3f02e01d1 (commit)
      from  7cefc534a5028123fb3c9f75b20fb34a2e0ab588 (commit)

http://gitweb.samba.org/?p=obnox/samba-ctdb.git;a=shortlog;h=v3-2-ctdb


- Log -----------------------------------------------------------------
commit 2f66b4d266b76125c25a5e5ff27db6c74cb76a6a
Author: Volker Lendecke <vl at samba.org>
Date:   Mon May 18 09:49:23 2009 +0200

    In aio_fork, we have to close all fd's, we might hold a gpfs share mode
    
    Keeping such an fd open prohibits another open of that same file.
    
    Signed-off-by: Michael Adam <obnox at samba.org>

commit 38d01dadc5953eb340ce1234865a8d1067402163
Author: Volker Lendecke <vl at samba.org>
Date:   Mon May 18 09:46:05 2009 +0200

    Add "file_walk_table" to do stuff with all open files
    
    Signed-off-by: Michael Adam <obnox at samba.org>

commit 94e01617e02be80980ce82ce548c712fa01dc569
Author: Volker Lendecke <vl at samba.org>
Date:   Mon May 18 09:36:16 2009 +0200

    Fix a race condition in vfs_aio_fork with gpfs share modes
    
    Signed-off-by: Michael Adam <obnox at samba.org>

commit 85cd942697db131baa74cf97c27c34f3f02e01d1
Author: Michael Adam <obnox at samba.org>
Date:   Fri May 15 01:48:55 2009 +0200

    s3:first cut at dbwrap_tool - a tdb tool that is CTDB-aware.
    
    This tool (in contrast to tdbtool) reads Samba's configuration
    and if clustering = yes, it talks to CTDB instead of accessing
    the TDB data bases directly. This is done by simply using
    the dbwrap mechanim, just like the Samba daemons.
    
    This first version can read and write int32 and uint32 values
    and delete records from a (c)tdb database.
    More operations will follow.
    
    This tool can already be useful in CTDB environments, e.g. when
    "net idmap restore" fails to set the USER and GROUP HWM keys,
    because the methods are deliberately not implemented in
    idmap_tdb2.c. You can manually set the high water marks
    with
    "dbwrap_tool store idmap_tdb2.tdb 'USER HWM' int32 12345"
    and
    "dbwrap_tool store idmap_tdb2.tdb 'GROUP HWM' int32 67890"
    
    Michael

-----------------------------------------------------------------------

Summary of changes:
 source/Makefile.in            |   18 +++-
 source/modules/vfs_aio_fork.c |   26 ++++-
 source/smbd/files.c           |   22 ++++
 source/utils/dbwrap_tool.c    |  247 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 310 insertions(+), 3 deletions(-)
 create mode 100644 source/utils/dbwrap_tool.c


Changeset truncated at 500 lines:

diff --git a/source/Makefile.in b/source/Makefile.in
index ce5a052..e24176c 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -202,7 +202,8 @@ BIN_PROGS = @EXTRA_BIN_PROGS@ \
 EVERYTHING_PROGS = bin/debug2html at EXEEXT@ bin/smbfilter at EXEEXT@ \
 	bin/talloctort at EXEEXT@ bin/replacetort at EXEEXT@ \
 	bin/log2pcap at EXEEXT@ bin/sharesec at EXEEXT@ bin/ndrdump at EXEEXT@ \
-	bin/vlp at EXEEXT@ bin/smbiconv at EXEEXT@
+	bin/vlp at EXEEXT@ bin/smbiconv at EXEEXT@ \
+	bin/dbwrap_tool at EXEEXT@
 
 PAM_MODULES = @PAM_MODULES@
 
@@ -1092,6 +1093,11 @@ VLP_OBJ = $(VLP_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) \
 	  $(PASSDB_OBJ) @LIBWBCLIENT_STATIC@ $(SMBLDAP_OBJ) $(GROUPDB_OBJ) $(LDB_OBJ) \
 	  $(DISPLAY_SEC_OBJ)
 
+DBWRAP_TOOL_OBJ = utils/dbwrap_tool.o \
+		  $(PARAM_OBJ) \
+		  $(LIB_NONSMBD_OBJ) \
+		  $(LIBSAMBA_OBJ)
+
 ######################################################################
 # now the rules...
 ######################################################################
@@ -2429,6 +2435,16 @@ bin/timelimit at EXEEXT@: script/tests/timelimit.o
 	@echo Linking $@
 	@$(CC) $(FLAGS) -o $@ $(DYNEXP) script/tests/timelimit.o
 
+bin/dbwrap_tool at EXEEXT@: $(DBWRAP_TOOL_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARED@
+	@echo "Linking $@"
+	@$(CC) -o $@ $(DBWRAP_TOOL_OBJ)\
+		$(LDFLAGS) $(DYNEEXP) $(LIBS) \
+		$(LDAP_LIBS) \
+		$(LIBTALLOC_LIBS) $(LIBTDB_LIBS)
+
+install-dbwrap_tool:: bin/dbwrap_tool at EXEEXT@
+	@$(SHELL) script/installbin.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(BINDIR) bin/dbwrap_tool at EXEEXT@
+
 install:: installservers installbin @INSTALL_CIFSMOUNT@ @INSTALL_CIFSUPCALL@ installman \
 		installscripts installdat installmodules @SWAT_INSTALL_TARGETS@ \
 		@INSTALL_PAM_MODULES@ installlibs
diff --git a/source/modules/vfs_aio_fork.c b/source/modules/vfs_aio_fork.c
index 28428f2..ca4ee60 100644
--- a/source/modules/vfs_aio_fork.c
+++ b/source/modules/vfs_aio_fork.c
@@ -359,6 +359,14 @@ static void aio_child_loop(int sockfd, struct mmap_area *map)
 			ret_struct.ret_errno = errno;
 		}
 
+		/*
+		 * Close the fd before telling our parent we're done. The
+		 * parent might close and re-open the file very quickly, and
+		 * with system-level share modes (GPFS) we would get an
+		 * unjustified SHARING_VIOLATION.
+		 */
+		close(fd);
+
 		ret = write_data(sockfd, (char *)&ret_struct,
 				 sizeof(ret_struct));
 		if (ret != sizeof(ret_struct)) {
@@ -366,8 +374,6 @@ static void aio_child_loop(int sockfd, struct mmap_area *map)
 				   strerror(errno)));
 			exit(2);
 		}
-
-		close(fd);
 	}
 }
 
@@ -420,6 +426,21 @@ static int aio_child_destructor(struct aio_child *child)
 	return 0;
 }
 
+/*
+ * We have to close all fd's in open files, we might incorrectly hold a system
+ * level share mode on a file.
+ */
+
+static struct files_struct *close_fsp_fd(struct files_struct *fsp,
+					 void *private_data)
+{
+	if ((fsp->fh != NULL) && (fsp->fh->fd != -1)) {
+		close(fsp->fh->fd);
+		fsp->fh->fd = -1;
+	}
+	return NULL;
+}
+
 static NTSTATUS create_aio_child(struct aio_child_list *children,
 				 size_t map_size,
 				 struct aio_child **presult)
@@ -459,6 +480,7 @@ static NTSTATUS create_aio_child(struct aio_child_list *children,
 	if (result->pid == 0) {
 		close(fdpair[0]);
 		result->sockfd = fdpair[1];
+		file_walk_table(close_fsp_fd, NULL);
 		aio_child_loop(result->sockfd, result->map);
 	}
 
diff --git a/source/smbd/files.c b/source/smbd/files.c
index 8ed8eaf..f643892 100644
--- a/source/smbd/files.c
+++ b/source/smbd/files.c
@@ -225,6 +225,28 @@ void file_close_user(int vuid)
 	}
 }
 
+/*
+ * Walk the files table until "fn" returns non-NULL
+ */
+
+struct files_struct *file_walk_table(
+	struct files_struct *(*fn)(struct files_struct *fsp,
+				   void *private_data),
+	void *private_data)
+{
+	struct files_struct *fsp, *next;
+
+	for (fsp = Files; fsp; fsp = next) {
+		struct files_struct *ret;
+		next = fsp->next;
+		ret = fn(fsp, private_data);
+		if (ret != NULL) {
+			return ret;
+		}
+	}
+	return NULL;
+}
+
 /****************************************************************************
  Debug to enumerate all open files in the smbd.
 ****************************************************************************/
diff --git a/source/utils/dbwrap_tool.c b/source/utils/dbwrap_tool.c
new file mode 100644
index 0000000..877d38a
--- /dev/null
+++ b/source/utils/dbwrap_tool.c
@@ -0,0 +1,247 @@
+/*
+   Samba Unix/Linux CIFS implementation
+
+   low level TDB/CTDB tool using the dbwrap interface
+
+   Copyright (C) 2009 Michael Adam <obnox at samba.org>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+
+extern bool AllowDebugChange;
+
+typedef enum { OP_FETCH, OP_STORE, OP_DELETE } dbwrap_op;
+
+typedef enum { TYPE_INT32, TYPE_UINT32 } dbwrap_type;
+
+static int dbwrap_tool_fetch_int32(struct db_context *db,
+				   const char *keyname,
+				   void *data)
+{
+	int32_t value;
+
+	value = dbwrap_fetch_int32(db, keyname);
+	d_printf("%d\n", value);
+
+	return 0;
+}
+
+static int dbwrap_tool_fetch_uint32(struct db_context *db,
+				    const char *keyname,
+				    void *data)
+{
+	uint32_t value;
+	bool ret;
+
+	ret = dbwrap_fetch_uint32(db, keyname, &value);
+	if (ret) {
+		d_printf("%u\n", value);
+		return 0;
+	} else {
+		d_fprintf(stderr, "ERROR: could not fetch uint32 key '%s'\n",
+			  keyname);
+		return -1;
+	}
+}
+
+static int dbwrap_tool_store_int32(struct db_context *db,
+				   const char *keyname,
+				   void *data)
+{
+	NTSTATUS status;
+	int32_t value = *((int32_t *)data);
+
+	status = dbwrap_trans_store_int32(db, keyname, value);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		d_fprintf(stderr, "ERROR: could not store int32 key '%s': %s\n",
+			  keyname, nt_errstr(status));
+		return -1;
+	}
+
+	return 0;
+}
+
+static int dbwrap_tool_store_uint32(struct db_context *db,
+				    const char *keyname,
+				    void *data)
+{
+	NTSTATUS status;
+	uint32_t value = *((uint32_t *)data);
+
+	status = dbwrap_trans_store_uint32(db, keyname, value);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		d_fprintf(stderr,
+			  "ERROR: could not store uint32 key '%s': %s\n",
+			  keyname, nt_errstr(status));
+		return -1;
+	}
+
+	return 0;
+}
+
+static int dbwrap_tool_delete(struct db_context *db,
+			      const char *keyname,
+			      void *data)
+{
+	NTSTATUS status;
+
+	status = dbwrap_trans_delete_bystring(db, keyname);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		d_fprintf(stderr, "ERROR deleting record %s : %s\n",
+			  keyname, nt_errstr(status));
+		return -1;
+	}
+
+	return 0;
+}
+
+struct dbwrap_op_dispatch_table {
+	dbwrap_op op;
+	dbwrap_type type;
+	int (*cmd)(struct db_context *db,
+		   const char *keyname,
+		   void *data);
+};
+
+struct dbwrap_op_dispatch_table dispatch_table[] = {
+	{ OP_FETCH,  TYPE_INT32,  dbwrap_tool_fetch_int32 },
+	{ OP_FETCH,  TYPE_UINT32, dbwrap_tool_fetch_uint32 },
+	{ OP_STORE,  TYPE_INT32,  dbwrap_tool_store_int32 },
+	{ OP_STORE,  TYPE_UINT32, dbwrap_tool_store_uint32 },
+	{ OP_DELETE, TYPE_INT32,  dbwrap_tool_delete },
+	{ OP_DELETE, TYPE_UINT32, dbwrap_tool_delete },
+	{ 0, 0, NULL },
+};
+
+int main(int argc, const char **argv)
+{
+	struct event_context *evt_ctx;
+	struct messaging_context *msg_ctx;
+	struct db_context *db;
+
+	uint16_t count;
+
+	const char *dbname;
+	const char *opname;
+	dbwrap_op op;
+	const char *keyname;
+	const char *keytype = "int32";
+	dbwrap_type type;
+	const char *valuestr = "0";
+	int32_t value = 0;
+
+	TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+	int ret = 1;
+
+	load_case_tables();
+	DEBUGLEVEL_CLASS[DBGC_ALL] = 0;
+	dbf = x_stderr;
+	AllowDebugChange = false;
+	lp_load(get_dyn_CONFIGFILE(), true, false, false, true);
+
+	if ((argc != 4) && (argc != 5) && (argc != 6)) {
+		d_fprintf(stderr,
+			  "USAGE: %s <database> <op> <key> [<type> [<value>]]\n"
+			  "       ops: fetch, store, delete\n"
+			  "       types: int32, uint32\n",
+			 argv[0]);
+		goto done;
+	}
+
+	dbname = argv[1];
+	opname = argv[2];
+	keyname = argv[3];
+
+	if (strcmp(opname, "store") == 0) {
+		if (argc != 6) {
+			d_fprintf(stderr, "ERROR: operation 'store' requires "
+				  "value argument\n");
+			goto done;
+		}
+		valuestr = argv[5];
+		keytype = argv[4];
+		op = OP_STORE;
+	} else if (strcmp(opname, "fetch") == 0) {
+		if (argc != 5) {
+			d_fprintf(stderr, "ERROR: operation 'fetch' requires "
+				  "type but not value argument\n");
+			goto done;
+		}
+		op = OP_FETCH;
+		keytype = argv[4];
+	} else if (strcmp(opname, "delete") == 0) {
+		if (argc != 4) {
+			d_fprintf(stderr, "ERROR: operation 'delete' does "
+				  "not allow type nor value argument\n");
+			goto done;
+		}
+		op = OP_DELETE;
+	} else {
+		d_fprintf(stderr,
+			  "ERROR: invalid op '%s' specified\n"
+			  "       supported ops: fetch, store, delete\n",
+			  opname);
+		goto done;
+	}
+
+	if (strcmp(keytype, "int32") == 0) {
+		type = TYPE_INT32;
+		value = (int32_t)strtol(valuestr, NULL, 10);
+	} else if (strcmp(keytype, "uint32") == 0) {
+		type = TYPE_UINT32;
+		value = (int32_t)strtoul(valuestr, NULL, 10);
+	} else {
+		d_fprintf(stderr, "ERROR: invalid type '%s' specified.\n"
+				  "       supported types: int32, uint32\n",
+				  keytype);
+		goto done;
+	}
+
+	evt_ctx = event_context_init(mem_ctx);
+	if (evt_ctx == NULL) {
+		d_fprintf(stderr, "ERROR: could not init event context\n");
+		goto done;
+	}
+
+	msg_ctx = messaging_init(mem_ctx, server_id_self(), evt_ctx);
+	if (msg_ctx == NULL) {
+		d_fprintf(stderr, "ERROR: could not init messaging context\n");
+		goto done;
+	}
+
+	db = db_open(mem_ctx, dbname, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
+	if (db == NULL) {
+		d_fprintf(stderr, "ERROR: could not open dbname\n");
+		goto done;
+	}
+
+	for (count = 0; dispatch_table[count].cmd != NULL; count++) {
+		if ((op == dispatch_table[count].op) &&
+		    (type == dispatch_table[count].type))
+		{
+			ret = dispatch_table[count].cmd(db, keyname, &value);
+			break;
+		}
+	}
+
+done:
+	TALLOC_FREE(mem_ctx);
+	return ret;
+}


-- 
SAMBA-CTDB repository


More information about the samba-cvs mailing list