struct _virSecurityManagerMetadataLockState {
- size_t nfds;
+ size_t nfds; /* Captures size of both @fds and @paths */
int *fds;
+ const char **paths;
};
*
* Lock passed @paths for metadata change. The returned state
* should be passed to virSecurityManagerMetadataUnlock.
+ * Passed @paths must not be freed until the corresponding unlock call.
*
* NOTE: this function is not thread safe (because of usage of
* POSIX locks).
size_t i = 0;
size_t nfds = 0;
int *fds = NULL;
+ const char **locked_paths = NULL;
virSecurityManagerMetadataLockStatePtr ret = NULL;
- if (VIR_ALLOC_N(fds, npaths) < 0)
+ if (VIR_ALLOC_N(fds, npaths) < 0 ||
+ VIR_ALLOC_N(locked_paths, npaths) < 0)
return NULL;
/* Sort paths to lock in order to avoid deadlocks with other
break;
} while (1);
+ locked_paths[nfds] = p;
VIR_APPEND_ELEMENT_COPY_INPLACE(fds, nfds, fd);
}
if (VIR_ALLOC(ret) < 0)
goto cleanup;
+ ret->paths = g_steal_pointer(&locked_paths);
ret->fds = g_steal_pointer(&fds);
ret->nfds = nfds;
nfds = 0;
for (i = nfds; i > 0; i--)
VIR_FORCE_CLOSE(fds[i - 1]);
VIR_FREE(fds);
+ VIR_FREE(locked_paths);
return ret;
}
for (i = 0; i < (*state)->nfds; i++) {
char ebuf[1024];
+ const char *path = (*state)->paths[i];
int fd = (*state)->fds[i];
/* Technically, unlock is not needed because it will
* happen on VIR_CLOSE() anyway. But let's play it nice. */
if (virFileUnlock(fd, METADATA_OFFSET, METADATA_LEN) < 0) {
- VIR_WARN("Unable to unlock fd %d: %s",
- fd, virStrerror(errno, ebuf, sizeof(ebuf)));
+ VIR_WARN("Unable to unlock fd %d path %s: %s",
+ fd, path, virStrerror(errno, ebuf, sizeof(ebuf)));
}
if (VIR_CLOSE(fd) < 0) {
- VIR_WARN("Unable to close fd %d: %s",
- fd, virStrerror(errno, ebuf, sizeof(ebuf)));
+ VIR_WARN("Unable to close fd %d path %s: %s",
+ fd, path, virStrerror(errno, ebuf, sizeof(ebuf)));
}
}
VIR_FREE((*state)->fds);
+ VIR_FREE((*state)->paths);
VIR_FREE(*state);
}