diff options
-rw-r--r-- | source3/smbd/server.c | 3 | ||||
-rw-r--r-- | source3/tdb/tdb.c | 58 | ||||
-rw-r--r-- | source3/tdb/tdb.h | 1 |
3 files changed, 52 insertions, 10 deletions
diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1dfff6cafa..27fd8e3015 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -309,6 +309,9 @@ max can be %d\n", done correctly in the process. */ reset_globals_after_fork(); + /* tdb needs special fork handling */ + tdb_reopen_all(); + return True; } /* The parent doesn't need this socket */ diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c index bb58950948..3a5b66bbc7 100644 --- a/source3/tdb/tdb.c +++ b/source3/tdb/tdb.c @@ -611,31 +611,24 @@ static int expand_file(TDB_CONTEXT *tdb, tdb_off size, tdb_off addition) #else char b = 0; -#ifdef HAVE_PWRITE - if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) { -#else if (lseek(tdb->fd, (size+addition) - 1, SEEK_SET) != (size+addition) - 1 || write(tdb->fd, &b, 1) != 1) { -#endif TDB_LOG((tdb, 0, "expand_file to %d failed (%s)\n", size+addition, strerror(errno))); return -1; } #endif - /* now fill the file with something. This ensures that the file isn't sparse, which would be - very bad if we ran out of disk. This must be done with write, not via mmap */ + /* now fill the file with something. This ensures that the + file isn't sparse, which would be very bad if we ran out of + disk. This must be done with write, not via mmap */ memset(buf, 0x42, sizeof(buf)); while (addition) { int n = addition>sizeof(buf)?sizeof(buf):addition; -#ifdef HAVE_PWRITE - int ret = pwrite(tdb->fd, buf, n, size); -#else int ret; if (lseek(tdb->fd, size, SEEK_SET) != size) return -1; ret = write(tdb->fd, buf, n); -#endif if (ret != n) { TDB_LOG((tdb, 0, "expand_file write of %d failed (%s)\n", n, strerror(errno))); @@ -1369,6 +1362,7 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags, tdb.map_ptr = NULL; tdb.lockedkeys = NULL; tdb.flags = tdb_flags; + tdb.open_flags = open_flags; if ((open_flags & O_ACCMODE) == O_WRONLY) goto fail; @@ -1605,3 +1599,47 @@ void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , cons { tdb->log_fn = fn; } + + +/* reopen a tdb - this is used after a fork to ensure that we have an independent + seek pointer from our parent and to re-establish locks */ +int tdb_reopen(TDB_CONTEXT *tdb) +{ + struct stat st; + + tdb_munmap(tdb); + close(tdb->fd); + tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); + if (tdb->fd == -1) { + TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno))); + goto fail; + } + fstat(tdb->fd, &st); + if (st.st_ino != tdb->inode || st.st_dev != tdb->device) { + TDB_LOG((tdb, 0, "tdb_reopen: file dev/inode has changed!\n")); + goto fail; + } + tdb_mmap(tdb); + if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1) { + TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n")); + goto fail; + } + + return 0; + +fail: + tdb_close(tdb); + return -1; +} + +/* reopen all tdb's */ +int tdb_reopen_all(void) +{ + TDB_CONTEXT *tdb; + + for (tdb=tdbs; tdb; tdb = tdb->next) { + if (tdb_reopen(tdb) != 0) return -1; + } + + return 0; +} diff --git a/source3/tdb/tdb.h b/source3/tdb/tdb.h index cc37825e78..4efe263ee8 100644 --- a/source3/tdb/tdb.h +++ b/source3/tdb/tdb.h @@ -95,6 +95,7 @@ typedef struct tdb_context { dev_t device; /* uniquely identifies this tdb */ ino_t inode; /* uniquely identifies this tdb */ void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...); /* logging function */ + int open_flags; /* flags used in the open - needed by reopen */ } TDB_CONTEXT; typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *); |