[libvirt] [PATCH] virfile: Report useful error fork approach to create NFS mount point fails
Ján Tomko
jtomko at redhat.com
Mon Jun 15 11:06:42 UTC 2015
On Thu, Jun 11, 2015 at 11:15:17AM +0200, Erik Skultety wrote:
> Commit 92d9114e tweaked the way we handle child errors when using fork
> approach to set specific permissions. The same logic should be used to
> create directories with specified permissions as well, otherwise the parent
> process doesn't report any useful error "unknown cause" while still returning
> negative errcode.
>
> https://bugzilla.redhat.com/show_bug.cgi?id=1230137
> ---
> src/util/virfile.c | 48 +++++++++++++++++++++++++++++++++++++++---------
> 1 file changed, 39 insertions(+), 9 deletions(-)
>
> diff --git a/src/util/virfile.c b/src/util/virfile.c
> index 5ff4668..7675eeb 100644
> --- a/src/util/virfile.c
> +++ b/src/util/virfile.c
> @@ -2376,6 +2376,7 @@ virDirCreate(const char *path,
> if (pid) { /* parent */
> /* wait for child to complete, and retrieve its exit code */
> VIR_FREE(groups);
> +
> while ((waitret = waitpid(pid, &status, 0)) == -1 && errno == EINTR);
> if (waitret == -1) {
> ret = -errno;
> @@ -2384,11 +2385,33 @@ virDirCreate(const char *path,
> path);
> goto parenterror;
> }
> - if (!WIFEXITED(status) || (ret = -WEXITSTATUS(status)) == -EACCES) {
The old condition was wrong:
child would call _exit(-EACCESS) and we would the compare -(-EACCESS) to -EACCESS
> - /* fall back to the simpler method, which works better in
> - * some cases */
> - return virDirCreateNoFork(path, mode, uid, gid, flags);
> +
> + /*
> + * If waitpid succeeded, but if the child exited abnormally or
> + * reported non-zero status, report failure, except for EACCES where
> + * we try to fall back to non-fork method as in the original logic.
> + */
What is the original logic referenced here?
> + if (!WIFEXITED(status) || (WEXITSTATUS(status)) != 0) {
> + if (WEXITSTATUS(status) == EACCES)
> + return virDirCreateNoFork(path, mode, uid, gid, flags);
> + char *msg = virProcessTranslateStatus(status);
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("child failed to create '%s': %s"),
> + path, msg);
> + VIR_FREE(msg);
> + /* Use child exit status if possible; otherwise,
> + * just use -EACCES, since by our original failure in
> + * the non fork+setuid path would have been EACCES or
> + * EPERM by definition (see qemuOpenFileAs after the
> + * first virFileOpenAs failure), but EACCES is close enough.
This comment references irrelevant functions and seems redundant.
> + * Besides -EPERM is like returning fd == -1.
> + */
> + if (WIFEXITED(status))
> + ret = -WEXITSTATUS(status);
> + else
> + ret = -EACCES;
> }
> +
> parenterror:
> return ret;
> }
> @@ -2400,15 +2423,14 @@ virDirCreate(const char *path,
> ret = -errno;
> goto childerror;
> }
> +
> if (mkdir(path, mode) < 0) {
> ret = -errno;
> - if (ret != -EACCES) {
> - /* in case of EACCES, the parent will retry */
> - virReportSystemError(errno, _("child failed to create directory '%s'"),
> - path);
> - }
> + virReportSystemError(errno, _("child failed to create directory '%s'"),
> + path);
Do we really need this hunk?
If we fail with EACCES, parent should call the NoFork function which
should return success / report error.
> goto childerror;
> }
> +
The space ajdustments would be better in a separate patch.
> /* check if group was set properly by creating after
> * setgid. If not, try doing it with chown */
> if (stat(path, &st) == -1) {
> @@ -2417,6 +2439,7 @@ virDirCreate(const char *path,
> _("stat of '%s' failed"), path);
> goto childerror;
> }
> +
> if ((st.st_gid != gid) && (chown(path, (uid_t) -1, gid) < 0)) {
> ret = -errno;
> virReportSystemError(errno,
> @@ -2424,13 +2447,20 @@ virDirCreate(const char *path,
> path, (unsigned int) gid);
> goto childerror;
> }
> +
> if (mode != (mode_t) -1 && chmod(path, mode) < 0) {
> virReportSystemError(errno,
> _("cannot set mode of '%s' to %04o"),
> path, mode);
> goto childerror;
> }
> +
> childerror:
> + ret = -ret;
> + if ((ret & 0xff) != ret) {
> + VIR_WARN("unable to pass desired return value %d", ret);
> + ret = 0xff;
> + }
And flipping the return value to unsigned should be separate from adding
the new error message in the parent.
Jan
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20150615/fa2c4f07/attachment-0001.sig>
More information about the libvir-list
mailing list