diff options
author | Volker Lendecke <vl@samba.org> | 2013-02-21 16:34:32 +0100 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2014-05-22 21:05:15 +0200 |
commit | cbd73ba1635c061fa71ff0476cbce087b389d1ad (patch) | |
tree | 16e67ca6bad58a5c3ba4c58ad77c3683fa74eb4b /lib/tdb/common/open.c | |
parent | c29e64d97ee18e9d7946151052d1757084f861c6 (diff) | |
download | samba-cbd73ba1635c061fa71ff0476cbce087b389d1ad.tar.gz samba-cbd73ba1635c061fa71ff0476cbce087b389d1ad.tar.xz samba-cbd73ba1635c061fa71ff0476cbce087b389d1ad.zip |
tdb: introduce tdb->hdr_ofs
This makes it possible to have some extra headers before
the real tdb content starts in the file.
This will be used used e.g. to implement locking based on robust mutexes.
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
Pair-Programmed-With: Michael Adam <obnox@samba.org>
Signed-off-by: Volker Lendecke <vl@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Michael Adam <obnox@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'lib/tdb/common/open.c')
-rw-r--r-- | lib/tdb/common/open.c | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/lib/tdb/common/open.c b/lib/tdb/common/open.c index 17ab0b7c28..162f30d404 100644 --- a/lib/tdb/common/open.c +++ b/lib/tdb/common/open.c @@ -194,6 +194,7 @@ _PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int td unsigned v; const char *hash_alg; uint32_t magic1, magic2; + int ret; ZERO_STRUCT(header); @@ -340,7 +341,6 @@ _PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int td if ((tdb_flags & TDB_CLEAR_IF_FIRST) && (!tdb->read_only) && (locked = (tdb_nest_lock(tdb, ACTIVE_LOCK, F_WRLCK, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE) == 0))) { - int ret; ret = tdb_brlock(tdb, F_WRLCK, FREELIST_TOP, 0, TDB_LOCK_WAIT); if (ret == -1) { @@ -400,8 +400,18 @@ _PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int td tdb->flags |= TDB_CONVERT; tdb_convert(&header, sizeof(header)); } - if (fstat(tdb->fd, &st) == -1) + + /* + * We only use st.st_dev and st.st_ino from the raw fstat() + * call, everything else needs to use tdb_fstat() in order + * to skip tdb->hdr_ofs! + */ + if (fstat(tdb->fd, &st) == -1) { goto fail; + } + tdb->device = st.st_dev; + tdb->inode = st.st_ino; + ZERO_STRUCT(st); if (header.rwlocks != 0 && header.rwlocks != TDB_FEATURE_FLAG_MAGIC && @@ -446,28 +456,27 @@ _PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int td } /* Is it already in the open list? If so, fail. */ - if (tdb_already_open(st.st_dev, st.st_ino)) { + if (tdb_already_open(tdb->device, tdb->inode)) { TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " "%s (%d,%d) is already open in this process\n", - name, (int)st.st_dev, (int)st.st_ino)); + name, (int)tdb->device, (int)tdb->inode)); errno = EBUSY; goto fail; } - /* Beware truncation! */ - tdb->map_size = st.st_size; - if (tdb->map_size != st.st_size) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " - "len %llu too large!\n", (long long)st.st_size)); + /* + * We had tdb_mmap(tdb) here before, + * but we need to use tdb_fstat(), + * which is triggered from tdb_oob() before calling tdb_mmap(). + * As this skips tdb->hdr_ofs. + */ + tdb->map_size = 0; + ret = tdb->methods->tdb_oob(tdb, 0, 1, 0); + if (ret == -1) { errno = EIO; goto fail; } - tdb->device = st.st_dev; - tdb->inode = st.st_ino; - tdb_mmap(tdb); if (locked) { if (tdb_nest_unlock(tdb, ACTIVE_LOCK, F_WRLCK, false) == -1) { TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " @@ -649,6 +658,11 @@ static int tdb_reopen_internal(struct tdb_context *tdb, bool active_lock) TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno))); goto fail; } + /* + * We only use st.st_dev and st.st_ino from the raw fstat() + * call, everything else needs to use tdb_fstat() in order + * to skip tdb->hdr_ofs! + */ if (fstat(tdb->fd, &st) != 0) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); goto fail; @@ -657,7 +671,16 @@ static int tdb_reopen_internal(struct tdb_context *tdb, bool active_lock) TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: file dev/inode has changed!\n")); goto fail; } - if (tdb_mmap(tdb) != 0) { + ZERO_STRUCT(st); + + /* + * We had tdb_mmap(tdb) here before, + * but we need to use tdb_fstat(), + * which is triggered from tdb_oob() before calling tdb_mmap(). + * As this skips tdb->hdr_ofs. + */ + tdb->map_size = 0; + if (tdb->methods->tdb_oob(tdb, 0, 1, 0) != 0) { goto fail; } #endif /* fake pread or pwrite */ |