For nmount(), allow a text string error message to be propagated back

to user-space if a parameter named "errmsg" is passed into the iovec.
Used in conjunction with vfs_mount_error(), more useful error messages
than errno can be passed back to userspace when mounting a filesystem
fails.

Discussed with:		phk, pjd
This commit is contained in:
Craig Rodrigues 2005-11-09 02:26:38 +00:00
parent 90e0829525
commit 4560dfb5b1

View File

@ -390,6 +390,18 @@ nmount(td, uap)
iov++;
}
error = vfs_donmount(td, uap->flags, auio);
/* copyout the errmsg */
for (i = 0; (error != 0) && (i < iovcnt); i += 2) {
const char *name = (const char *)auio->uio_iov[i].iov_base;
if (!strcmp(name, "errmsg")) {
copyout(auio->uio_iov[i+1].iov_base,
uap->iovp[i+1].iov_base, uap->iovp[i+1].iov_len);
break;
}
}
free(auio, M_IOV);
return (error);
}
@ -464,8 +476,15 @@ static int
vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions)
{
struct vfsoptlist *optlist;
struct iovec *iov_errmsg = NULL;
char *fstype, *fspath;
int error, fstypelen, fspathlen;
int i;
for (i = 0; i < fsoptions->uio_iovcnt; i += 2) {
if (!strcmp((char *)fsoptions->uio_iov[i].iov_base, "errmsg"))
iov_errmsg = &fsoptions->uio_iov[i+1];
}
error = vfs_buildopts(fsoptions, &optlist);
if (error)
@ -480,12 +499,18 @@ vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions)
error = vfs_getopt(optlist, "fstype", (void **)&fstype, &fstypelen);
if (error || fstype[fstypelen - 1] != '\0') {
error = EINVAL;
if (iov_errmsg)
strncpy((char *)iov_errmsg->iov_base, "Invalid fstype",
iov_errmsg->iov_len);
goto bail;
}
fspathlen = 0;
error = vfs_getopt(optlist, "fspath", (void **)&fspath, &fspathlen);
if (error || fspath[fspathlen - 1] != '\0') {
error = EINVAL;
if (iov_errmsg != NULL)
strncpy((char *)iov_errmsg->iov_base, "Invalid fspath",
iov_errmsg->iov_len);
goto bail;
}
@ -503,6 +528,17 @@ vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions)
error = vfs_domount(td, fstype, fspath, fsflags, optlist);
mtx_unlock(&Giant);
bail:
if (error && iov_errmsg != NULL) {
/* save the errmsg */
char *errmsg;
int len, ret;
ret = vfs_getopt(optlist, "errmsg", (void **)&errmsg, &len);
if(ret == 0 && len > 0)
strncpy((char *)iov_errmsg->iov_base, errmsg,
iov_errmsg->iov_len);
}
if (error)
vfs_freeopts(optlist);
return (error);
@ -1195,9 +1231,8 @@ vfs_mount_error(struct mount *mp, const char *fmt, ...)
char *errmsg;
error = vfs_getopt(moptlist, "errmsg", (void **)&errmsg, &len);
if (error || errmsg == NULL || len <= 0) {
if (error || errmsg == NULL || len <= 0)
return;
}
va_start(ap, fmt);
vsnprintf(errmsg, (size_t)len, fmt, ap);