summaryrefslogtreecommitdiff
path: root/ovsdb
diff options
context:
space:
mode:
authorBen Pfaff <blp@ovn.org>2017-10-06 15:15:31 -0700
committerBen Pfaff <blp@ovn.org>2017-12-24 18:13:22 -0800
commit02f4f23137c1b67536f388813eefccce52ea2492 (patch)
tree4c4efeefcc229e60ef1d2c06ee96e4e7e5a131e2 /ovsdb
parent4cc9d1f03f83e9fac90a77ddaca0af662b2758b1 (diff)
downloadopenvswitch-02f4f23137c1b67536f388813eefccce52ea2492.tar.gz
log: Use absolute name of log file.
In ovsdb-server, the OVSDB log code is used to open the databases specified on the command line before ovsdb-server daemonizes itself. Afterward, it is occasionally necessary for ovsdb-server to reference those files by name again. When that happens, if daemonization changed the current directory to the root, any relative names are no longer valid and those references will fail. Until now, this was handled at a higher level in ovsdb-server, but in the future it will be convenient to handle it in the log code itself. This commit prepares for that by making the log code take the absolute name of log files itself. Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'ovsdb')
-rw-r--r--ovsdb/log.c95
1 files changed, 62 insertions, 33 deletions
diff --git a/ovsdb/log.c b/ovsdb/log.c
index 5c15e53db..0f8dafa30 100644
--- a/ovsdb/log.c
+++ b/ovsdb/log.c
@@ -72,7 +72,8 @@ struct ovsdb_log {
off_t prev_offset;
off_t offset;
- char *name;
+ char *name; /* Absolute name of file. */
+ char *display_name; /* For use in log messages, etc. */
char *magic;
struct lockfile *lockfile;
FILE *stream;
@@ -130,8 +131,22 @@ ovsdb_log_open(const char *name, const char *magic,
if (open_mode == OVSDB_LOG_CREATE_EXCL || open_mode == OVSDB_LOG_CREATE) {
ovs_assert(!strchr(magic, '|'));
}
+
*filep = NULL;
+ /* Get the absolute name of the file because we might need to access it by
+ * name again later after the process has changed directory (e.g. because
+ * daemonize() chdirs to "/").
+ *
+ * We save the user-provided name of the file for use in log messages, to
+ * reduce user confusion. */
+ char *abs_name = abs_file_name(NULL, name);
+ if (!abs_name) {
+ error = ovsdb_io_error(0, "could not determine current "
+ "working directory");
+ goto error;
+ }
+
ovs_assert(locking == -1 || locking == false || locking == true);
if (locking < 0) {
locking = open_mode != OVSDB_LOG_READ_ONLY;
@@ -246,7 +261,8 @@ ovsdb_log_open(const char *name, const char *magic,
struct ovsdb_log *file = xmalloc(sizeof *file);
file->state = OVSDB_LOG_READ;
file->error = NULL;
- file->name = xstrdup(name);
+ file->name = abs_name;
+ file->display_name = xstrdup(name);
file->magic = xstrdup(actual_magic);
file->lockfile = lockfile;
file->stream = stream;
@@ -261,6 +277,7 @@ error_fclose:
error_unlock:
lockfile_unlock(lockfile);
error:
+ free(abs_name);
return error;
}
@@ -292,6 +309,7 @@ ovsdb_log_close(struct ovsdb_log *file)
if (file) {
ovsdb_error_destroy(file->error);
free(file->name);
+ free(file->display_name);
free(file->magic);
if (file->stream) {
fclose(file->stream);
@@ -374,8 +392,9 @@ parse_body(struct ovsdb_log *file, off_t offset, unsigned long int length,
json_parser_abort(parser);
return ovsdb_io_error(ferror(file->stream) ? errno : EOF,
"%s: error reading %lu bytes "
- "starting at offset %lld", file->name,
- length, (long long int) offset);
+ "starting at offset %lld",
+ file->display_name, length,
+ (long long int) offset);
}
sha1_update(&ctx, input, chunk);
json_parser_feed(parser, input, chunk);
@@ -427,7 +446,7 @@ ovsdb_log_read(struct ovsdb_log *file, struct json **jsonp)
if (feof(file->stream)) {
return NULL;
}
- error = ovsdb_io_error(errno, "%s: read failed", file->name);
+ error = ovsdb_io_error(errno, "%s: read failed", file->display_name);
goto error;
}
off_t data_offset = file->offset + strlen(header);
@@ -437,7 +456,8 @@ ovsdb_log_read(struct ovsdb_log *file, struct json **jsonp)
|| strcmp(magic, file->magic)) {
error = ovsdb_syntax_error(NULL, NULL, "%s: parse error at offset "
"%lld in header line \"%.*s\"",
- file->name, (long long int) file->offset,
+ file->display_name,
+ (long long int) file->offset,
(int) strcspn(header, "\n"), header);
goto error;
}
@@ -451,7 +471,7 @@ ovsdb_log_read(struct ovsdb_log *file, struct json **jsonp)
error = ovsdb_syntax_error(NULL, NULL, "%s: %lu bytes starting at "
"offset %lld have SHA-1 hash "SHA1_FMT" "
"but should have hash "SHA1_FMT,
- file->name, data_length,
+ file->display_name, data_length,
(long long int) data_offset,
SHA1_ARGS(actual_sha1),
SHA1_ARGS(expected_sha1));
@@ -461,7 +481,7 @@ ovsdb_log_read(struct ovsdb_log *file, struct json **jsonp)
if (json->type == JSON_STRING) {
error = ovsdb_syntax_error(NULL, NULL, "%s: %lu bytes starting at "
"offset %lld are not valid JSON (%s)",
- file->name, data_length,
+ file->display_name, data_length,
(long long int) data_offset,
json->u.string);
goto error;
@@ -469,7 +489,7 @@ ovsdb_log_read(struct ovsdb_log *file, struct json **jsonp)
if (json->type != JSON_OBJECT) {
error = ovsdb_syntax_error(NULL, NULL, "%s: %lu bytes starting at "
"offset %lld are not a JSON object",
- file->name, data_length,
+ file->display_name, data_length,
(long long int) data_offset);
goto error;
}
@@ -502,10 +522,30 @@ ovsdb_log_unread(struct ovsdb_log *file)
file->offset = file->prev_offset;
}
+static struct ovsdb_error *
+ovsdb_log_truncate(struct ovsdb_log *file)
+{
+ file->state = OVSDB_LOG_WRITE;
+
+ struct ovsdb_error *error = NULL;
+ if (fseeko(file->stream, file->offset, SEEK_SET)) {
+ error = ovsdb_io_error(errno, "%s: cannot seek to offset %lld",
+ file->display_name,
+ (long long int) file->offset);
+ } else if (ftruncate(fileno(file->stream), file->offset)) {
+ error = ovsdb_io_error(errno, "%s: cannot truncate to length %lld",
+ file->display_name,
+ (long long int) file->offset);
+ }
+ return error;
+}
+
/* Composes a log record for 'json' by filling 'header' with a header line and
* 'data' with a data line (each ending with a new-line). To write the record
* to a file, write 'header' followed by 'data'.
*
+ * 'magic' is the magic to use in the header record, e.g. OVSDB_MAGIC.
+ *
* The caller must initialize 'header' and 'data' to empty strings. */
void
ovsdb_log_compose_record(const struct json *json,
@@ -538,8 +578,6 @@ ovsdb_log_compose_record(const struct json *json,
struct ovsdb_error *
ovsdb_log_write(struct ovsdb_log *file, const struct json *json)
{
- struct ovsdb_error *error;
-
switch (file->state) {
case OVSDB_LOG_WRITE:
break;
@@ -547,19 +585,13 @@ ovsdb_log_write(struct ovsdb_log *file, const struct json *json)
case OVSDB_LOG_READ:
case OVSDB_LOG_READ_ERROR:
case OVSDB_LOG_WRITE_ERROR:
- file->state = OVSDB_LOG_WRITE;
ovsdb_error_destroy(file->error);
- file->error = NULL;
- if (fseeko(file->stream, file->offset, SEEK_SET)) {
- error = ovsdb_io_error(errno, "%s: cannot seek to offset %lld",
- file->name, (long long int) file->offset);
- goto error;
- }
- if (ftruncate(fileno(file->stream), file->offset)) {
- error = ovsdb_io_error(errno, "%s: cannot truncate to length %lld",
- file->name, (long long int) file->offset);
- goto error;
+ file->error = ovsdb_log_truncate(file);
+ if (file->error) {
+ file->state = OVSDB_LOG_WRITE_ERROR;
+ return ovsdb_error_clone(file->error);
}
+ file->state = OVSDB_LOG_WRITE;
break;
case OVSDB_LOG_BROKEN:
@@ -567,8 +599,7 @@ ovsdb_log_write(struct ovsdb_log *file, const struct json *json)
}
if (json->type != JSON_OBJECT && json->type != JSON_ARRAY) {
- error = OVSDB_BUG("bad JSON type");
- goto error;
+ return OVSDB_BUG("bad JSON type");
}
struct ds header = DS_EMPTY_INITIALIZER;
@@ -583,33 +614,31 @@ ovsdb_log_write(struct ovsdb_log *file, const struct json *json)
ds_destroy(&header);
ds_destroy(&data);
if (!ok) {
- error = ovsdb_io_error(errno, "%s: write failed", file->name);
+ int error = errno;
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
VLOG_WARN_RL(&rl, "%s: write failed (%s)",
- file->name, ovs_strerror(errno));
+ file->name, ovs_strerror(error));
/* Remove any partially written data, ignoring errors since there is
* nothing further we can do. */
ignore(ftruncate(fileno(file->stream), file->offset));
- goto error;
+ file->error = ovsdb_io_error(error, "%s: write failed",
+ file->display_name);
+ file->state = OVSDB_LOG_WRITE_ERROR;
+ return ovsdb_error_clone(file->error);
}
file->offset += total_length;
return NULL;
-
-error:
- file->state = OVSDB_LOG_WRITE_ERROR;
- file->error = ovsdb_error_clone(error);
- return error;
}
struct ovsdb_error *
ovsdb_log_commit(struct ovsdb_log *file)
{
if (file->stream && fsync(fileno(file->stream))) {
- return ovsdb_io_error(errno, "%s: fsync failed", file->name);
+ return ovsdb_io_error(errno, "%s: fsync failed", file->display_name);
}
return NULL;
}