Mount updates:
- allow mounting with "none" block device - allow unmounting by mountpoint - make VFS aware of file system process labels - allow m3_ca1 to use the full available message size - use *printf in u/mount(1), as mount(2) uses it already - fix reference leaks for some mount error cases in VFS
This commit is contained in:
parent
483160f3d4
commit
b31119abf5
21 changed files with 331 additions and 202 deletions
|
@ -21,14 +21,13 @@
|
||||||
_PROTOTYPE(int main, (int argc, char **argv));
|
_PROTOTYPE(int main, (int argc, char **argv));
|
||||||
_PROTOTYPE(void list, (void));
|
_PROTOTYPE(void list, (void));
|
||||||
_PROTOTYPE(void usage, (void));
|
_PROTOTYPE(void usage, (void));
|
||||||
_PROTOTYPE(void tell, (char *this));
|
|
||||||
|
|
||||||
int main(argc, argv)
|
int main(argc, argv)
|
||||||
int argc;
|
int argc;
|
||||||
char *argv[];
|
char *argv[];
|
||||||
{
|
{
|
||||||
int i, n, v, mountflags;
|
int i, n, v, mountflags;
|
||||||
char **ap, *vs, *opt, *err, *type, *args;
|
char **ap, *vs, *opt, *err, *type, *args, *device;
|
||||||
char special[PATH_MAX+1], mounted_on[PATH_MAX+1], version[10], rw_flag[10];
|
char special[PATH_MAX+1], mounted_on[PATH_MAX+1], version[10], rw_flag[10];
|
||||||
|
|
||||||
if (argc == 1) list(); /* just list /etc/mtab */
|
if (argc == 1) list(); /* just list /etc/mtab */
|
||||||
|
@ -57,25 +56,21 @@ char *argv[];
|
||||||
*ap = NULL;
|
*ap = NULL;
|
||||||
argc = (ap - argv);
|
argc = (ap - argv);
|
||||||
|
|
||||||
if (argc != 3) usage();
|
if (argc != 3 || *argv[1] == 0) usage();
|
||||||
if (mount(argv[1], argv[2], mountflags, type, args) < 0) {
|
|
||||||
|
device = argv[1];
|
||||||
|
if (!strcmp(device, "none")) device = NULL;
|
||||||
|
|
||||||
|
if (mount(device, argv[2], mountflags, type, args) < 0) {
|
||||||
err = strerror(errno);
|
err = strerror(errno);
|
||||||
std_err("mount: Can't mount ");
|
fprintf(stderr, "mount: Can't mount %s on %s: %s\n",
|
||||||
std_err(argv[1]);
|
argv[1], argv[2], err);
|
||||||
std_err(" on ");
|
|
||||||
std_err(argv[2]);
|
|
||||||
std_err(": ");
|
|
||||||
std_err(err);
|
|
||||||
std_err("\n");
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The mount has completed successfully. Tell the user. */
|
/* The mount has completed successfully. Tell the user. */
|
||||||
tell(argv[1]);
|
printf("%s is read-%s mounted on %s\n",
|
||||||
tell(" is read-");
|
argv[1], mountflags & MS_RDONLY ? "only" : "write", argv[2]);
|
||||||
tell(mountflags & MS_RDONLY ? "only" : "write");
|
|
||||||
tell(" mounted on ");
|
|
||||||
tell(argv[2]);
|
|
||||||
tell("\n");
|
|
||||||
|
|
||||||
/* Update /etc/mtab. */
|
/* Update /etc/mtab. */
|
||||||
n = load_mtab("mount");
|
n = load_mtab("mount");
|
||||||
|
@ -133,12 +128,9 @@ void list()
|
||||||
while (1) {
|
while (1) {
|
||||||
n = get_mtab_entry(special, mounted_on, version, rw_flag);
|
n = get_mtab_entry(special, mounted_on, version, rw_flag);
|
||||||
if (n < 0) break;
|
if (n < 0) break;
|
||||||
write(1, special, strlen(special));
|
printf("%s is read-%s mounted on %s (type %s)\n",
|
||||||
tell(" is read-");
|
special, strcmp(rw_flag, "rw") == 0 ? "write" : "only",
|
||||||
tell(strcmp(rw_flag, "rw") == 0 ? "write" : "only");
|
mounted_on, version);
|
||||||
tell(" mounted on ");
|
|
||||||
tell(mounted_on);
|
|
||||||
tell("\n");
|
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
@ -149,10 +141,3 @@ void usage()
|
||||||
std_err("Usage: mount [-r] [-t type] [-o options] special name\n");
|
std_err("Usage: mount [-r] [-t type] [-o options] special name\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void tell(this)
|
|
||||||
char *this;
|
|
||||||
{
|
|
||||||
write(1, this, strlen(this));
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include <minix/type.h>
|
#include <minix/type.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/svrctl.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
@ -17,55 +17,85 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
_PROTOTYPE(int main, (int argc, char **argv));
|
_PROTOTYPE(int main, (int argc, char **argv));
|
||||||
_PROTOTYPE(void update_mtab, (char *devname));
|
_PROTOTYPE(int find_mtab_entry, (char *name));
|
||||||
|
_PROTOTYPE(void update_mtab, (void));
|
||||||
_PROTOTYPE(void usage, (void));
|
_PROTOTYPE(void usage, (void));
|
||||||
_PROTOTYPE(void tell, (char *this));
|
|
||||||
|
|
||||||
static char mountpoint[PATH_MAX+1];
|
static char device[PATH_MAX+1], mountpoint[PATH_MAX+1], vs[10], rw[10];
|
||||||
|
|
||||||
int main(argc, argv)
|
int main(argc, argv)
|
||||||
int argc;
|
int argc;
|
||||||
char *argv[];
|
char *argv[];
|
||||||
{
|
{
|
||||||
|
int found;
|
||||||
|
|
||||||
if (argc != 2) usage();
|
if (argc != 2) usage();
|
||||||
|
found = find_mtab_entry(argv[1]);
|
||||||
if (umount(argv[1]) < 0) {
|
if (umount(argv[1]) < 0) {
|
||||||
if (errno == EINVAL)
|
if (errno == EINVAL)
|
||||||
std_err("Device not mounted\n");
|
std_err("umount: Device not mounted\n");
|
||||||
|
else if (errno == ENOTBLK)
|
||||||
|
std_err("unount: Not a mountpoint\n");
|
||||||
else
|
else
|
||||||
perror("umount");
|
perror("umount");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
update_mtab(argv[1]);
|
if (found) {
|
||||||
tell(argv[1]);
|
printf("%s unmounted from %s\n", device, mountpoint);
|
||||||
tell(" unmounted");
|
update_mtab();
|
||||||
if (*mountpoint != '\0') {
|
|
||||||
tell(" from ");
|
|
||||||
tell(mountpoint);
|
|
||||||
}
|
}
|
||||||
tell("\n");
|
else printf("%s unmounted (mtab not updated)\n", argv[1]);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_mtab(devname)
|
int find_mtab_entry(name)
|
||||||
char *devname;
|
char *name;
|
||||||
{
|
{
|
||||||
/* Remove an entry from /etc/mtab. */
|
/* Find a matching mtab entry for 'name' which may be a special or a path,
|
||||||
int n;
|
* and generate a new mtab file without this entry on the fly. Do not write
|
||||||
|
* out the result yet. Return whether we found a matching entry.
|
||||||
|
*/
|
||||||
char special[PATH_MAX+1], mounted_on[PATH_MAX+1], version[10], rw_flag[10];
|
char special[PATH_MAX+1], mounted_on[PATH_MAX+1], version[10], rw_flag[10];
|
||||||
|
struct stat nstat, mstat;
|
||||||
|
int n, found;
|
||||||
|
|
||||||
if (load_mtab("umount") < 0) {
|
if (load_mtab("umount") < 0) return 0;
|
||||||
std_err("/etc/mtab not updated.\n");
|
|
||||||
exit(1);
|
if (stat(name, &nstat) != 0) return 0;
|
||||||
}
|
|
||||||
|
found = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
n = get_mtab_entry(special, mounted_on, version, rw_flag);
|
n = get_mtab_entry(special, mounted_on, version, rw_flag);
|
||||||
if (n < 0) break;
|
if (n < 0) break;
|
||||||
if (strcmp(devname, special) == 0) {
|
if (strcmp(name, special) == 0 || (stat(mounted_on, &mstat) == 0 &&
|
||||||
|
mstat.st_dev == nstat.st_dev && mstat.st_ino == nstat.st_ino))
|
||||||
|
{
|
||||||
|
/* If we found an earlier match, keep that one. Mountpoints
|
||||||
|
* may be stacked on top of each other, and unmounting should
|
||||||
|
* take place in the reverse order of mounting.
|
||||||
|
*/
|
||||||
|
if (found) {
|
||||||
|
(void) put_mtab_entry(device, mountpoint, vs, rw);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(device, special);
|
||||||
strcpy(mountpoint, mounted_on);
|
strcpy(mountpoint, mounted_on);
|
||||||
|
strcpy(vs, version);
|
||||||
|
strcpy(rw, rw_flag);
|
||||||
|
found = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
(void) put_mtab_entry(special, mounted_on, version, rw_flag);
|
(void) put_mtab_entry(special, mounted_on, version, rw_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_mtab()
|
||||||
|
{
|
||||||
|
/* Write out the new mtab file. */
|
||||||
|
int n;
|
||||||
|
|
||||||
n = rewrite_mtab("umount");
|
n = rewrite_mtab("umount");
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
std_err("/etc/mtab not updated.\n");
|
std_err("/etc/mtab not updated.\n");
|
||||||
|
@ -75,12 +105,6 @@ char *devname;
|
||||||
|
|
||||||
void usage()
|
void usage()
|
||||||
{
|
{
|
||||||
std_err("Usage: umount special\n");
|
std_err("Usage: umount name\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tell(this)
|
|
||||||
char *this;
|
|
||||||
{
|
|
||||||
write(1, this, strlen(this));
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,7 +11,11 @@ enum dev_style { STYLE_DEV, STYLE_NDEV, STYLE_TTY, STYLE_CLONE };
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
||||||
/* Total number of different devices. */
|
/* Total number of different devices. */
|
||||||
#define NR_DEVICES 32 /* number of (major) devices */
|
#define NR_DEVICES 32 /* number of (major) devices */
|
||||||
|
|
||||||
|
#define NONE_MAJOR 0 /* pseudo device for mounting file
|
||||||
|
* systems without a real block device
|
||||||
|
*/
|
||||||
|
|
||||||
/* Major and minor device numbers for MEMORY driver. */
|
/* Major and minor device numbers for MEMORY driver. */
|
||||||
#define MEMORY_MAJOR 1 /* major device for memory devices */
|
#define MEMORY_MAJOR 1 /* major device for memory devices */
|
||||||
|
|
|
@ -10,12 +10,13 @@
|
||||||
#define M1 1
|
#define M1 1
|
||||||
#define M3 3
|
#define M3 3
|
||||||
#define M4 4
|
#define M4 4
|
||||||
#define M3_STRING 14
|
#define M3_STRING 14 /* legacy m3_ca1 size (must not be changed) */
|
||||||
|
#define M3_LONG_STRING 16 /* current m3_ca1 size (may be increased) */
|
||||||
|
|
||||||
typedef struct {int m1i1, m1i2, m1i3; char *m1p1, *m1p2, *m1p3;} mess_1;
|
typedef struct {int m1i1, m1i2, m1i3; char *m1p1, *m1p2, *m1p3;} mess_1;
|
||||||
typedef struct {int m2i1, m2i2, m2i3; long m2l1, m2l2; char *m2p1;
|
typedef struct {int m2i1, m2i2, m2i3; long m2l1, m2l2; char *m2p1;
|
||||||
short m2s1;} mess_2;
|
short m2s1;} mess_2;
|
||||||
typedef struct {int m3i1, m3i2; char *m3p1; char m3ca1[M3_STRING];} mess_3;
|
typedef struct {int m3i1, m3i2; char *m3p1; char m3ca1[M3_LONG_STRING];} mess_3;
|
||||||
typedef struct {long m4l1, m4l2, m4l3, m4l4, m4l5;} mess_4;
|
typedef struct {long m4l1, m4l2, m4l3, m4l4, m4l5;} mess_4;
|
||||||
typedef struct {short m5c1, m5c2; int m5i1, m5i2; long m5l1, m5l2, m5l3;}mess_5;
|
typedef struct {short m5c1, m5c2; int m5i1, m5i2; long m5l1, m5l2, m5l3;}mess_5;
|
||||||
typedef struct {long m6l1, m6l2, m6l3; short m6s1, m6s2, m6s3; char m6c1, m6c2;
|
typedef struct {long m6l1, m6l2, m6l3; short m6s1, m6s2, m6s3; char m6c1, m6c2;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#define MS_RDONLY 0x001 /* Mount device read only */
|
#define MS_RDONLY 0x001 /* Mount device read only */
|
||||||
#define MS_REUSE 0x002 /* Tell RS to try reusing binary from memory */
|
#define MS_REUSE 0x002 /* Tell RS to try reusing binary from memory */
|
||||||
|
#define MS_LABEL16 0x004 /* Mount message points to 16-byte label */
|
||||||
|
|
||||||
|
|
||||||
/* Function Prototypes. */
|
/* Function Prototypes. */
|
||||||
|
|
|
@ -25,40 +25,17 @@ PRIVATE int rs_down(char *label)
|
||||||
return system(cmd);
|
return system(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIVATE char *makelabel(_CONST char *special)
|
|
||||||
{
|
|
||||||
static char label[40];
|
|
||||||
_CONST char *dev;
|
|
||||||
|
|
||||||
/* Make label name. */
|
|
||||||
dev = strrchr(special, '/');
|
|
||||||
if(dev) dev++;
|
|
||||||
else dev = special;
|
|
||||||
if(strchr(dev, '\'') != NULL) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if(strlen(dev)+4 >= sizeof(label)) {
|
|
||||||
errno = E2BIG;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
sprintf(label, "fs_%s", dev);
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
PUBLIC int mount(special, name, mountflags, type, args)
|
PUBLIC int mount(special, name, mountflags, type, args)
|
||||||
char *name, *special, *type, *args;
|
char *name, *special, *type, *args;
|
||||||
int mountflags;
|
int mountflags;
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
message m;
|
message m;
|
||||||
struct rs_start rs_start;
|
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
char *label;
|
char label[16];
|
||||||
char path[60];
|
char path[60];
|
||||||
char cmd[200];
|
char cmd[200];
|
||||||
FILE *pipe;
|
char *p;
|
||||||
int ep;
|
|
||||||
int reuse;
|
int reuse;
|
||||||
|
|
||||||
/* Default values. */
|
/* Default values. */
|
||||||
|
@ -68,15 +45,33 @@ int mountflags;
|
||||||
|
|
||||||
/* Check mount flags */
|
/* Check mount flags */
|
||||||
if(mountflags & MS_REUSE) {
|
if(mountflags & MS_REUSE) {
|
||||||
reuse = 1;
|
reuse = 1;
|
||||||
mountflags &= ~MS_REUSE; /* Temporary: turn off to not confuse VFS */
|
mountflags &= ~MS_REUSE; /* Temporary: turn off to not confuse VFS */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make FS process label for RS from special name. */
|
/* Make a label for the file system process. This label must be unique and
|
||||||
if(!(label=makelabel(special))) {
|
* may currently not exceed 16 characters including terminating null. For
|
||||||
return -1;
|
* requests with an associated block device, we use the last path component
|
||||||
|
* name of the block special file (truncated to 12 characters, which is
|
||||||
|
* hopefully enough). For requests with no associated block device, we use
|
||||||
|
* the device number and inode of the mount point, in hexadecimal form.
|
||||||
|
*/
|
||||||
|
if (special) {
|
||||||
|
p = strrchr(special, '/');
|
||||||
|
p = p ? p + 1 : special;
|
||||||
|
if (strchr(p, '\'')) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sprintf(label, "fs_%.12s", p);
|
||||||
|
} else {
|
||||||
|
if (stat(name, &statbuf) < 0) return -1;
|
||||||
|
sprintf(label, "fs_%04x%x", statbuf.st_dev, statbuf.st_ino);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Tell VFS that we are passing in a 16-byte label. */
|
||||||
|
mountflags |= MS_LABEL16;
|
||||||
|
|
||||||
/* See if the given type is even remotely valid. */
|
/* See if the given type is even remotely valid. */
|
||||||
if(strlen(FSPATH)+strlen(type) >= sizeof(path)) {
|
if(strlen(FSPATH)+strlen(type) >= sizeof(path)) {
|
||||||
errno = E2BIG;
|
errno = E2BIG;
|
||||||
|
@ -102,32 +97,23 @@ int mountflags;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sprintf(cmd, _PATH_SERVICE " %sup %s -label '%s' -config " _PATH_SYSTEM_CONF
|
sprintf(cmd, _PATH_SERVICE " %sup %s -label '%s' -config " _PATH_SYSTEM_CONF
|
||||||
" -args '%s%s' -printep yes",
|
" -args '%s%s'",
|
||||||
reuse ? "-r ": "", path, label, args[0] ? "-o " : "", args);
|
reuse ? "-r ": "", path, label, args[0] ? "-o " : "", args);
|
||||||
|
|
||||||
if(!(pipe = popen(cmd, "r"))) {
|
if((r = system(cmd)) != 0) {
|
||||||
fprintf(stderr, "mount: couldn't run %s\n", cmd);
|
fprintf(stderr, "mount: couldn't run %s\n", cmd);
|
||||||
|
errno = r;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fscanf(pipe, "%d", &ep) != 1 || ep <= 0) {
|
|
||||||
fprintf(stderr, "mount: couldn't parse endpoint from %s\n", cmd);
|
|
||||||
errno = EINVAL;
|
|
||||||
pclose(pipe);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pclose(pipe);
|
|
||||||
|
|
||||||
/* Now perform mount(). */
|
/* Now perform mount(). */
|
||||||
m.m1_i1 = strlen(special) + 1;
|
m.m1_i1 = special ? strlen(special) + 1 : 0;
|
||||||
m.m1_i2 = strlen(name) + 1;
|
m.m1_i2 = strlen(name) + 1;
|
||||||
m.m1_i3 = mountflags;
|
m.m1_i3 = mountflags;
|
||||||
m.m1_p1 = special;
|
m.m1_p1 = special;
|
||||||
m.m1_p2 = name;
|
m.m1_p2 = name;
|
||||||
m.m1_p3 = (char*) ep;
|
m.m1_p3 = label;
|
||||||
r = _syscall(FS, MOUNT, &m);
|
r = _syscall(FS, MOUNT, &m);
|
||||||
|
|
||||||
if(r != OK) {
|
if(r != OK) {
|
||||||
|
@ -144,19 +130,16 @@ PUBLIC int umount(name)
|
||||||
_CONST char *name;
|
_CONST char *name;
|
||||||
{
|
{
|
||||||
message m;
|
message m;
|
||||||
char *label;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* Make MFS process label for RS from special name. */
|
|
||||||
if(!(label=makelabel(name))) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
_loadname(name, &m);
|
_loadname(name, &m);
|
||||||
r = _syscall(FS, UMOUNT, &m);
|
r = _syscall(FS, UMOUNT, &m);
|
||||||
|
|
||||||
if(r == OK) {
|
if(r == OK) {
|
||||||
rs_down(label);
|
/* VFS returns the label of the unmounted file system in the reply.
|
||||||
|
* As of writing, the size of the m3_ca1 field is 16 bytes.
|
||||||
|
*/
|
||||||
|
rs_down(m.m3_ca1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -15,5 +15,5 @@ message *msgptr;
|
||||||
k = strlen(name) + 1;
|
k = strlen(name) + 1;
|
||||||
msgptr->m3_i1 = k;
|
msgptr->m3_i1 = k;
|
||||||
msgptr->m3_p1 = (char *) name;
|
msgptr->m3_p1 = (char *) name;
|
||||||
if (k <= sizeof msgptr->m3_ca1) strcpy(msgptr->m3_ca1, name);
|
if (k <= M3_STRING) strcpy(msgptr->m3_ca1, name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,13 @@ mount \- mount a file system
|
||||||
.FL "\-o" "Options passed to FS server"
|
.FL "\-o" "Options passed to FS server"
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
.EX "mount /dev/fd1 /user" "Mount diskette 1 on \fI/user\fP"
|
.EX "mount /dev/fd1 /user" "Mount diskette 1 on \fI/user\fP"
|
||||||
|
.EX "mount -t procfs none /proc" "Mount proc file system on \fI/proc\fP"
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.PP
|
.PP
|
||||||
The file system contained on the special file is mounted on \fIfile\fP.
|
The file system contained on the special file \fIspecial\fP is mounted on
|
||||||
In the example above, the root directory of the file system in drive 1
|
\fIfile\fP. If the value of "\fBnone\fP" is given for \fIspecial\fP,
|
||||||
|
the file system is mounted without a block special device underneath it.
|
||||||
|
In the first example above, the root directory of the file system in drive 1
|
||||||
can be accessed as
|
can be accessed as
|
||||||
.B /user
|
.B /user
|
||||||
after the mount.
|
after the mount.
|
||||||
|
@ -37,6 +40,10 @@ The
|
||||||
.B \-o
|
.B \-o
|
||||||
flag may be used to pass options to the file system server.
|
flag may be used to pass options to the file system server.
|
||||||
The interpretation of these options is up to the server.
|
The interpretation of these options is up to the server.
|
||||||
|
.PP
|
||||||
|
If \fBmount\fP is invoked without any parameters, it will print the list of
|
||||||
|
currently mounted file systems according to
|
||||||
|
.BR mtab (5).
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.BR df (1),
|
.BR df (1),
|
||||||
.BR mkfs (1),
|
.BR mkfs (1),
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
.SH NAME
|
.SH NAME
|
||||||
umount \- unmount a mounted file system
|
umount \- unmount a mounted file system
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
\fBumount \fIspecial\fR
|
\fBumount \fIname\fR
|
||||||
.br
|
.br
|
||||||
.de FL
|
.de FL
|
||||||
.TP
|
.TP
|
||||||
|
@ -16,8 +16,13 @@ umount \- unmount a mounted file system
|
||||||
..
|
..
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
.EX "umount /dev/fd1" "Unmount diskette 1"
|
.EX "umount /dev/fd1" "Unmount diskette 1"
|
||||||
|
.EX "umount /mnt" "Unmount the file system mounted on /mnt"
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.PP
|
.PP
|
||||||
|
This command unmounts a file system identified by
|
||||||
|
.IR name .
|
||||||
|
This name may be either a block special file, or the path name of a mount
|
||||||
|
point.
|
||||||
A mounted file system is unmounted after the cache has been flushed to disk.
|
A mounted file system is unmounted after the cache has been flushed to disk.
|
||||||
A diskette should never be removed while it is mounted.
|
A diskette should never be removed while it is mounted.
|
||||||
If this happens, and is discovered before another diskette is inserted, the
|
If this happens, and is discovered before another diskette is inserted, the
|
||||||
|
|
|
@ -27,12 +27,18 @@ is a directory, then
|
||||||
.I name
|
.I name
|
||||||
must also be a directory.
|
must also be a directory.
|
||||||
.I Special
|
.I Special
|
||||||
must be a block special file, except for loopback mounts. For loopback
|
must be a block special file, or a NULL pointer.
|
||||||
mounts a normal file or directory is used for
|
If a NULL pointer is passed, the file system is
|
||||||
.IR special ,
|
mounted without a block device.
|
||||||
which must be seen as the root of a virtual device.
|
.I Mountflags
|
||||||
.I Flag
|
may be a bitwise combination of the following flags:
|
||||||
is 0 for a read-write mount, 1 for read-only.
|
.TP 2
|
||||||
|
.B MS_RDONLY
|
||||||
|
Mount file system read-only, rather than read-write.
|
||||||
|
.TP
|
||||||
|
.B MS_REUSE
|
||||||
|
Reuse the file system server image if possible.
|
||||||
|
.PP
|
||||||
.I Type
|
.I Type
|
||||||
is the type of the file system (e.g. "mfs"), used to pick a file system server.
|
is the type of the file system (e.g. "mfs"), used to pick a file system server.
|
||||||
If this parameter is NULL, the default type is used.
|
If this parameter is NULL, the default type is used.
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#define NR_MNTS 8 /* # slots in mount table */
|
#define NR_MNTS 8 /* # slots in mount table */
|
||||||
#define NR_VNODES 512 /* # slots in vnode table */
|
#define NR_VNODES 512 /* # slots in vnode table */
|
||||||
|
|
||||||
|
#define NR_NONEDEVS NR_MNTS /* # slots in nonedev bitmap */
|
||||||
|
|
||||||
/* Miscellaneous constants */
|
/* Miscellaneous constants */
|
||||||
#define SU_UID ((uid_t) 0) /* super_user's uid_t */
|
#define SU_UID ((uid_t) 0) /* super_user's uid_t */
|
||||||
#define SERVERS_UID ((uid_t) 11) /* who may do FSSIGNON */
|
#define SERVERS_UID ((uid_t) 11) /* who may do FSSIGNON */
|
||||||
|
@ -33,6 +35,11 @@
|
||||||
|
|
||||||
#define ROOT_INODE 1 /* inode number for root directory */
|
#define ROOT_INODE 1 /* inode number for root directory */
|
||||||
|
|
||||||
|
#define LABEL_MAX 16 /* maximum label size (including '\0'). Should
|
||||||
|
* not be smaller than 16 or bigger than
|
||||||
|
* M3_LONG_STRING.
|
||||||
|
*/
|
||||||
|
|
||||||
/* Args to dev_io */
|
/* Args to dev_io */
|
||||||
#define VFS_DEV_READ 2001
|
#define VFS_DEV_READ 2001
|
||||||
#define VFS_DEV_WRITE 2002
|
#define VFS_DEV_WRITE 2002
|
||||||
|
|
|
@ -65,7 +65,7 @@ PUBLIC int do_mapdriver()
|
||||||
unsigned long tasknr;
|
unsigned long tasknr;
|
||||||
vir_bytes label_vir;
|
vir_bytes label_vir;
|
||||||
size_t label_len;
|
size_t label_len;
|
||||||
char label[16];
|
char label[LABEL_MAX];
|
||||||
|
|
||||||
if (!super_user)
|
if (!super_user)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,7 +20,7 @@ extern struct dmap {
|
||||||
int _PROTOTYPE ((*dmap_io), (int, message *) );
|
int _PROTOTYPE ((*dmap_io), (int, message *) );
|
||||||
endpoint_t dmap_driver;
|
endpoint_t dmap_driver;
|
||||||
int dmap_flags;
|
int dmap_flags;
|
||||||
char dmap_label[16];
|
char dmap_label[LABEL_MAX];
|
||||||
int dmap_async_driver;
|
int dmap_async_driver;
|
||||||
struct filp *dmap_sel_filp;
|
struct filp *dmap_sel_filp;
|
||||||
} dmap[];
|
} dmap[];
|
||||||
|
|
|
@ -24,7 +24,6 @@ PRIVATE struct {
|
||||||
int g_who_p; /* slot number of caller process */
|
int g_who_p; /* slot number of caller process */
|
||||||
int g_call_nr; /* call number */
|
int g_call_nr; /* call number */
|
||||||
int g_super_user; /* is the caller root? */
|
int g_super_user; /* is the caller root? */
|
||||||
short g_cum_path_processed; /* how many path chars processed? */
|
|
||||||
char g_user_fullpath[PATH_MAX+1]; /* path to look up */
|
char g_user_fullpath[PATH_MAX+1]; /* path to look up */
|
||||||
} globals[MAX_DEPTH];
|
} globals[MAX_DEPTH];
|
||||||
|
|
||||||
|
@ -56,7 +55,6 @@ PRIVATE int push_globals()
|
||||||
globals[depth].g_who_p = who_p;
|
globals[depth].g_who_p = who_p;
|
||||||
globals[depth].g_call_nr = call_nr;
|
globals[depth].g_call_nr = call_nr;
|
||||||
globals[depth].g_super_user = super_user;
|
globals[depth].g_super_user = super_user;
|
||||||
globals[depth].g_cum_path_processed = cum_path_processed;
|
|
||||||
|
|
||||||
/* XXX is it safe to strcpy this? */
|
/* XXX is it safe to strcpy this? */
|
||||||
assert(sizeof(globals[0].g_user_fullpath) == sizeof(user_fullpath));
|
assert(sizeof(globals[0].g_user_fullpath) == sizeof(user_fullpath));
|
||||||
|
@ -89,7 +87,6 @@ PRIVATE void pop_globals()
|
||||||
who_p = globals[depth].g_who_p;
|
who_p = globals[depth].g_who_p;
|
||||||
call_nr = globals[depth].g_call_nr;
|
call_nr = globals[depth].g_call_nr;
|
||||||
super_user = globals[depth].g_super_user;
|
super_user = globals[depth].g_super_user;
|
||||||
cum_path_processed = globals[depth].g_cum_path_processed;
|
|
||||||
|
|
||||||
memcpy(user_fullpath, globals[depth].g_user_fullpath, sizeof(user_fullpath));
|
memcpy(user_fullpath, globals[depth].g_user_fullpath, sizeof(user_fullpath));
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,12 @@ EXTERN message m_in; /* the input message itself */
|
||||||
EXTERN message m_out; /* the output message used for reply */
|
EXTERN message m_out; /* the output message used for reply */
|
||||||
EXTERN int who_p, who_e; /* caller's proc number, endpoint */
|
EXTERN int who_p, who_e; /* caller's proc number, endpoint */
|
||||||
EXTERN int call_nr; /* system call number */
|
EXTERN int call_nr; /* system call number */
|
||||||
EXTERN message mount_m_in; /* the input message itself */
|
|
||||||
|
EXTERN message mount_m_in; /* the input message for a mount request */
|
||||||
|
EXTERN endpoint_t mount_fs_e; /* endpoint of file system to mount */
|
||||||
|
EXTERN char mount_label[LABEL_MAX]; /* label of file system to mount */
|
||||||
|
|
||||||
EXTERN char user_fullpath[PATH_MAX+1]; /* storage for user path name */
|
EXTERN char user_fullpath[PATH_MAX+1]; /* storage for user path name */
|
||||||
EXTERN short cum_path_processed; /* number of characters processed */
|
|
||||||
|
|
||||||
/* The following variables are used for returning results to the caller. */
|
/* The following variables are used for returning results to the caller. */
|
||||||
EXTERN int err_code; /* temporary storage for error number */
|
EXTERN int err_code; /* temporary storage for error number */
|
||||||
|
|
|
@ -517,6 +517,7 @@ PRIVATE void init_root()
|
||||||
/* Root directory is not mounted on a vnode. */
|
/* Root directory is not mounted on a vnode. */
|
||||||
vmp->m_mounted_on = NULL;
|
vmp->m_mounted_on = NULL;
|
||||||
vmp->m_root_node = root_node;
|
vmp->m_root_node = root_node;
|
||||||
|
strcpy(vmp->m_label, "fs_imgrd"); /* FIXME: obtain this from RS */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
|
|
@ -293,7 +293,7 @@ PRIVATE void unmount_all(void)
|
||||||
/* Unmount at least one. */
|
/* Unmount at least one. */
|
||||||
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
|
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
|
||||||
if (vmp->m_dev != NO_DEV)
|
if (vmp->m_dev != NO_DEV)
|
||||||
unmount(vmp->m_dev);
|
unmount(vmp->m_dev, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
/* This file performs the MOUNT and UMOUNT system calls.
|
/* This file performs the MOUNT and UMOUNT system calls.
|
||||||
*
|
*
|
||||||
* The entry points into this file are
|
* The entry points into this file are
|
||||||
* do_mount: perform the MOUNT system call
|
* do_fslogin: perform the FSLOGIN system call
|
||||||
* do_umount: perform the UMOUNT system call
|
* do_mount: perform the MOUNT system call
|
||||||
|
* do_umount: perform the UMOUNT system call
|
||||||
|
* unmount: unmount a file system
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
@ -14,8 +16,11 @@
|
||||||
#include <minix/const.h>
|
#include <minix/const.h>
|
||||||
#include <minix/endpoint.h>
|
#include <minix/endpoint.h>
|
||||||
#include <minix/syslib.h>
|
#include <minix/syslib.h>
|
||||||
|
#include <minix/bitmap.h>
|
||||||
|
#include <minix/ds.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "fproc.h"
|
#include "fproc.h"
|
||||||
|
@ -27,9 +32,16 @@
|
||||||
/* Allow the root to be replaced before the first 'real' mount. */
|
/* Allow the root to be replaced before the first 'real' mount. */
|
||||||
PRIVATE int allow_newroot = 1;
|
PRIVATE int allow_newroot = 1;
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( dev_t name_to_dev, (void) );
|
/* Bitmap of in-use "none" pseudo devices. */
|
||||||
FORWARD _PROTOTYPE( int mount_fs, (endpoint_t fs_e) );
|
PRIVATE bitchunk_t nonedev[BITMAP_CHUNKS(NR_NONEDEVS)] = { 0 };
|
||||||
|
|
||||||
|
#define alloc_nonedev(dev) SET_BIT(nonedev, minor(dev) - 1)
|
||||||
|
#define free_nonedev(dev) UNSET_BIT(nonedev, minor(dev) - 1)
|
||||||
|
|
||||||
|
FORWARD _PROTOTYPE( dev_t name_to_dev, (int allow_mountpt) );
|
||||||
|
FORWARD _PROTOTYPE( int mount_fs, (endpoint_t fs_e) );
|
||||||
|
FORWARD _PROTOTYPE( int is_nonedev, (Dev_t dev) );
|
||||||
|
FORWARD _PROTOTYPE( dev_t find_free_nonedev, (void) );
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_fslogin *
|
* do_fslogin *
|
||||||
|
@ -39,7 +51,7 @@ PUBLIC int do_fslogin()
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* Login before mount request */
|
/* Login before mount request */
|
||||||
if ((unsigned long)mount_m_in.m1_p3 != who_e) {
|
if (mount_fs_e != who_e) {
|
||||||
last_login_fs_e = who_e;
|
last_login_fs_e = who_e;
|
||||||
r = SUSPEND;
|
r = SUSPEND;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +70,7 @@ PUBLIC int do_fslogin()
|
||||||
fp = &fproc[who_p]; /* pointer to proc table struct */
|
fp = &fproc[who_p]; /* pointer to proc table struct */
|
||||||
super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE); /* su? */
|
super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE); /* su? */
|
||||||
|
|
||||||
r = do_mount();
|
r = mount_fs(mount_fs_e);
|
||||||
}
|
}
|
||||||
return(r);
|
return(r);
|
||||||
}
|
}
|
||||||
|
@ -69,13 +81,30 @@ PUBLIC int do_fslogin()
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int do_mount()
|
PUBLIC int do_mount()
|
||||||
{
|
{
|
||||||
endpoint_t fs_e;
|
u32_t fs_e;
|
||||||
|
int r, proc_nr;
|
||||||
|
|
||||||
/* Only the super-user may do MOUNT. */
|
/* Only the super-user may do MOUNT. */
|
||||||
if (!super_user) return(EPERM);
|
if (!super_user) return(EPERM);
|
||||||
|
|
||||||
/* FS process' endpoint number */
|
/* FS process' endpoint number */
|
||||||
fs_e = (unsigned long) m_in.fs_endpt;
|
if (m_in.mount_flags & MS_LABEL16) {
|
||||||
|
/* Get the label from the caller, and ask DS for the endpoint. */
|
||||||
|
r = sys_datacopy(who_e, (vir_bytes) m_in.fs_label, SELF,
|
||||||
|
(vir_bytes) mount_label, (phys_bytes) sizeof(mount_label));
|
||||||
|
if (r != OK) return(r);
|
||||||
|
|
||||||
|
mount_label[sizeof(mount_label)-1] = 0;
|
||||||
|
|
||||||
|
r = ds_retrieve_u32(mount_label, &fs_e);
|
||||||
|
if (r != OK) return(r);
|
||||||
|
|
||||||
|
if (isokendpt(fs_e, &proc_nr) != OK) return(EINVAL);
|
||||||
|
} else {
|
||||||
|
/* Legacy support: get the endpoint from the request itself. */
|
||||||
|
fs_e = (unsigned long) m_in.fs_label;
|
||||||
|
mount_label[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Sanity check on process number. */
|
/* Sanity check on process number. */
|
||||||
if(fs_e <= 0) {
|
if(fs_e <= 0) {
|
||||||
|
@ -93,9 +122,9 @@ PUBLIC int do_mount()
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE int mount_fs(endpoint_t fs_e)
|
PRIVATE int mount_fs(endpoint_t fs_e)
|
||||||
{
|
{
|
||||||
/* Perform the mount(name, mfile, rd_only) system call. */
|
/* Perform the mount(name, mfile, mount_flags) system call. */
|
||||||
int rdir, mdir; /* TRUE iff {root|mount} file is dir */
|
int rdir, mdir; /* TRUE iff {root|mount} file is dir */
|
||||||
int i, r, found, isroot, replace_root;
|
int i, r, found, rdonly, nodev, isroot, replace_root;
|
||||||
struct fproc *tfp;
|
struct fproc *tfp;
|
||||||
struct dmap *dp;
|
struct dmap *dp;
|
||||||
dev_t dev;
|
dev_t dev;
|
||||||
|
@ -110,19 +139,37 @@ PRIVATE int mount_fs(endpoint_t fs_e)
|
||||||
|
|
||||||
/* If FS not yet logged in, save message and suspend mount */
|
/* If FS not yet logged in, save message and suspend mount */
|
||||||
if (last_login_fs_e != fs_e) {
|
if (last_login_fs_e != fs_e) {
|
||||||
mount_m_in = m_in;
|
mount_m_in = m_in;
|
||||||
|
mount_fs_e = fs_e;
|
||||||
|
/* mount_label is already saved */
|
||||||
return(SUSPEND);
|
return(SUSPEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mount request got after FS login or FS login arrived after a suspended mount */
|
/* Mount request got after FS login or FS login arrived after a suspended
|
||||||
|
* mount.
|
||||||
|
*/
|
||||||
last_login_fs_e = NONE;
|
last_login_fs_e = NONE;
|
||||||
|
|
||||||
/* Clear endpoint field */
|
/* Clear endpoint field */
|
||||||
mount_m_in.fs_endpt = (char *) NONE;
|
mount_fs_e = NONE;
|
||||||
|
|
||||||
/* If 'name' is not for a block special file, return error. */
|
/* Should the file system be mounted read-only? */
|
||||||
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
|
rdonly = (m_in.mount_flags & MS_RDONLY);
|
||||||
if ((dev = name_to_dev()) == NO_DEV) return(err_code);
|
|
||||||
|
/* A null string for block special device means don't use a device at all. */
|
||||||
|
nodev = (m_in.name1_length == 0);
|
||||||
|
|
||||||
|
if (!nodev) {
|
||||||
|
/* If 'name' is not for a block special file, return error. */
|
||||||
|
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK)
|
||||||
|
return(err_code);
|
||||||
|
if ((dev = name_to_dev(FALSE /*allow_mountpt*/)) == NO_DEV)
|
||||||
|
return(err_code);
|
||||||
|
} else {
|
||||||
|
/* Find a free pseudo-device as substitute for an actual device. */
|
||||||
|
if ((dev = find_free_nonedev()) == NO_DEV)
|
||||||
|
return(err_code);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check whether there is a block special file open which uses the
|
/* Check whether there is a block special file open which uses the
|
||||||
* same device (partition) */
|
* same device (partition) */
|
||||||
|
@ -158,24 +205,13 @@ PRIVATE int mount_fs(endpoint_t fs_e)
|
||||||
/* Partition was/is already mounted */
|
/* Partition was/is already mounted */
|
||||||
if (found) {
|
if (found) {
|
||||||
/* It is possible that we have an old root lying around that
|
/* It is possible that we have an old root lying around that
|
||||||
* needs to be remounted. */
|
* needs to be remounted. This could for example be a boot
|
||||||
if(vmp->m_mounted_on || vmp->m_mounted_on == fproc[FS_PROC_NR].fp_rd) {
|
* ramdisk that has already been replaced by the real root.
|
||||||
/* Normally, m_mounted_on refers to the mount point. For a
|
*/
|
||||||
* root filesystem, m_mounted_on is equal to the root vnode.
|
if(vmp->m_mounted_on || root_dev == vmp->m_dev) {
|
||||||
* We assume that the root of FS is always the real root. If
|
return(EBUSY); /* not a root or still mounted */
|
||||||
* the two vnodes are different or if the root of FS is equal
|
|
||||||
* to the root of the filesystem we found, we found a
|
|
||||||
* filesystem that is in use.
|
|
||||||
*/
|
|
||||||
return(EBUSY); /* already mounted */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(vmp->m_mounted_on)
|
|
||||||
panic("vfs", "root unexpectedly mounted somewhere", NO_NUM);
|
|
||||||
|
|
||||||
if (root_dev == vmp->m_dev)
|
|
||||||
panic("vfs", "inconsistency remounting old root", NO_NUM);
|
|
||||||
|
|
||||||
/* Now get the inode of the file to be mounted on. */
|
/* Now get the inode of the file to be mounted on. */
|
||||||
if (fetch_name(m_in.name2, m_in.name2_length, M1)!=OK) return(err_code);
|
if (fetch_name(m_in.name2, m_in.name2_length, M1)!=OK) return(err_code);
|
||||||
if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
|
if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
|
||||||
|
@ -201,8 +237,10 @@ PRIVATE int mount_fs(endpoint_t fs_e)
|
||||||
|
|
||||||
/* Nothing else can go wrong. Perform the mount. */
|
/* Nothing else can go wrong. Perform the mount. */
|
||||||
vmp->m_mounted_on = vp;
|
vmp->m_mounted_on = vp;
|
||||||
vmp->m_flags = m_in.rd_only;
|
vmp->m_flags = rdonly;
|
||||||
allow_newroot = 0; /* The root is now fixed */
|
strcpy(vmp->m_label, mount_label);
|
||||||
|
allow_newroot = 0; /* The root is now fixed */
|
||||||
|
if (nodev) alloc_nonedev(dev); /* Make the allocation final */
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
@ -224,21 +262,29 @@ PRIVATE int mount_fs(endpoint_t fs_e)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We'll need a vnode for the root inode, check whether there is one */
|
/* We'll need a vnode for the root inode, check whether there is one */
|
||||||
if ((root_node = get_free_vnode()) == NIL_VNODE) return(ENFILE);
|
if ((root_node = get_free_vnode()) == NIL_VNODE) {
|
||||||
|
if (vp != NIL_VNODE) put_vnode(vp);
|
||||||
/* Get driver process' endpoint */
|
return(ENFILE);
|
||||||
dp = &dmap[(dev >> MAJOR) & BYTE];
|
|
||||||
if (dp->dmap_driver == NONE) {
|
|
||||||
printf("VFS: no driver for dev %x\n", dev);
|
|
||||||
return(EINVAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
label = dp->dmap_label;
|
label = "";
|
||||||
if (strlen(label) == 0)
|
if (!nodev) {
|
||||||
panic(__FILE__, "VFS mount_fs: no label for major", dev >> MAJOR);
|
/* Get driver process' endpoint */
|
||||||
|
dp = &dmap[(dev >> MAJOR) & BYTE];
|
||||||
|
if (dp->dmap_driver == NONE) {
|
||||||
|
printf("VFS: no driver for dev %x\n", dev);
|
||||||
|
if (vp != NIL_VNODE) put_vnode(vp);
|
||||||
|
return(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
label = dp->dmap_label;
|
||||||
|
if (strlen(label) == 0)
|
||||||
|
panic(__FILE__, "VFS mount_fs: no label for major",
|
||||||
|
dev >> MAJOR);
|
||||||
|
}
|
||||||
|
|
||||||
/* Tell FS which device to mount */
|
/* Tell FS which device to mount */
|
||||||
if ((r = req_readsuper(fs_e, label, dev, m_in.rd_only, isroot, &res)) != OK){
|
if ((r = req_readsuper(fs_e, label, dev, rdonly, isroot, &res)) != OK) {
|
||||||
if (vp != NIL_VNODE) put_vnode(vp);
|
if (vp != NIL_VNODE) put_vnode(vp);
|
||||||
return(r);
|
return(r);
|
||||||
}
|
}
|
||||||
|
@ -257,7 +303,7 @@ PRIVATE int mount_fs(endpoint_t fs_e)
|
||||||
/* Fill in max file size and blocksize for the vmnt */
|
/* Fill in max file size and blocksize for the vmnt */
|
||||||
vmp->m_fs_e = res.fs_e;
|
vmp->m_fs_e = res.fs_e;
|
||||||
vmp->m_dev = dev;
|
vmp->m_dev = dev;
|
||||||
vmp->m_flags = m_in.rd_only;
|
vmp->m_flags = rdonly;
|
||||||
|
|
||||||
/* Root node is indeed on the partition */
|
/* Root node is indeed on the partition */
|
||||||
root_node->v_vmnt = vmp;
|
root_node->v_vmnt = vmp;
|
||||||
|
@ -268,6 +314,8 @@ PRIVATE int mount_fs(endpoint_t fs_e)
|
||||||
* Nothing else can go wrong. Perform the mount. */
|
* Nothing else can go wrong. Perform the mount. */
|
||||||
vmp->m_root_node = root_node;
|
vmp->m_root_node = root_node;
|
||||||
vmp->m_mounted_on = NULL;
|
vmp->m_mounted_on = NULL;
|
||||||
|
strcpy(vmp->m_label, mount_label);
|
||||||
|
if (nodev) alloc_nonedev(dev);
|
||||||
|
|
||||||
root_dev = dev;
|
root_dev = dev;
|
||||||
ROOT_FS_E = fs_e;
|
ROOT_FS_E = fs_e;
|
||||||
|
@ -291,11 +339,9 @@ PRIVATE int mount_fs(endpoint_t fs_e)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* File types may not conflict. */
|
/* File types may not conflict. */
|
||||||
if (r == OK) {
|
mdir = ((vp->v_mode & I_TYPE) == I_DIRECTORY); /*TRUE iff dir*/
|
||||||
mdir = ((vp->v_mode & I_TYPE) == I_DIRECTORY); /*TRUE iff dir*/
|
rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY);
|
||||||
rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY);
|
if (!mdir && rdir) r = EISDIR;
|
||||||
if (!mdir && rdir) r = EISDIR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If error, return the super block and both inodes; release the vmnt. */
|
/* If error, return the super block and both inodes; release the vmnt. */
|
||||||
if (r != OK) {
|
if (r != OK) {
|
||||||
|
@ -308,9 +354,13 @@ PRIVATE int mount_fs(endpoint_t fs_e)
|
||||||
/* Nothing else can go wrong. Perform the mount. */
|
/* Nothing else can go wrong. Perform the mount. */
|
||||||
vmp->m_mounted_on = vp;
|
vmp->m_mounted_on = vp;
|
||||||
vmp->m_root_node = root_node;
|
vmp->m_root_node = root_node;
|
||||||
|
strcpy(vmp->m_label, mount_label);
|
||||||
|
|
||||||
/* The root is now fixed */
|
/* The root is now fixed */
|
||||||
allow_newroot = 0;
|
allow_newroot = 0;
|
||||||
|
|
||||||
|
/* Allocate the pseudo device that was found, if not using a real device. */
|
||||||
|
if (nodev) alloc_nonedev(dev);
|
||||||
|
|
||||||
/* There was a block spec file open, and it should be handled by the
|
/* There was a block spec file open, and it should be handled by the
|
||||||
* new FS proc now */
|
* new FS proc now */
|
||||||
|
@ -326,23 +376,35 @@ PRIVATE int mount_fs(endpoint_t fs_e)
|
||||||
PUBLIC int do_umount()
|
PUBLIC int do_umount()
|
||||||
{
|
{
|
||||||
/* Perform the umount(name) system call. */
|
/* Perform the umount(name) system call. */
|
||||||
|
char label[LABEL_MAX];
|
||||||
dev_t dev;
|
dev_t dev;
|
||||||
|
int r;
|
||||||
|
|
||||||
/* Only the super-user may do umount. */
|
/* Only the super-user may do umount. */
|
||||||
if (!super_user) return(EPERM);
|
if (!super_user) return(EPERM);
|
||||||
|
|
||||||
/* If 'name' is not for a block special file, return error. */
|
/* If 'name' is not for a block special file or mountpoint, return error. */
|
||||||
if(fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
|
if(fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
|
||||||
if((dev = name_to_dev()) == NO_DEV) return(err_code);
|
if((dev = name_to_dev(TRUE /*allow_mountpt*/)) == NO_DEV) return(err_code);
|
||||||
return unmount(dev);
|
|
||||||
|
if((r = unmount(dev, label)) != OK) return(r);
|
||||||
|
|
||||||
|
/* Return the label of the mounted file system, so that the caller
|
||||||
|
* can shut down the corresponding server process.
|
||||||
|
*/
|
||||||
|
if (strlen(label) >= M3_LONG_STRING) /* should never evaluate to true */
|
||||||
|
label[M3_LONG_STRING-1] = 0;
|
||||||
|
strcpy(m_out.umount_label, label);
|
||||||
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* unmount *
|
* unmount *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int unmount(dev)
|
PUBLIC int unmount(dev, label)
|
||||||
Dev_t dev;
|
Dev_t dev; /* block-special device */
|
||||||
|
char *label; /* buffer to retrieve label, or NULL */
|
||||||
{
|
{
|
||||||
struct vnode *vp, *vi;
|
struct vnode *vp, *vi;
|
||||||
struct vmnt *vmp_i = NULL, *vmp = NULL;
|
struct vmnt *vmp_i = NULL, *vmp = NULL;
|
||||||
|
@ -371,19 +433,25 @@ Dev_t dev;
|
||||||
|
|
||||||
/* Tell FS to drop all inode references for root inode except 1. */
|
/* Tell FS to drop all inode references for root inode except 1. */
|
||||||
vnode_clean_refs(vmp->m_root_node);
|
vnode_clean_refs(vmp->m_root_node);
|
||||||
|
|
||||||
if (vmp->m_mounted_on) {
|
if (vmp->m_mounted_on) {
|
||||||
put_vnode(vmp->m_mounted_on);
|
put_vnode(vmp->m_mounted_on);
|
||||||
vmp->m_mounted_on = NIL_VNODE;
|
vmp->m_mounted_on = NIL_VNODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tell FS to unmount */
|
/* Tell FS to unmount */
|
||||||
if(vmp->m_fs_e <= 0 || vmp->m_fs_e == NONE)
|
if(vmp->m_fs_e <= 0 || vmp->m_fs_e == NONE)
|
||||||
panic(__FILE__, "unmount: strange fs endpoint", vmp->m_fs_e);
|
panic(__FILE__, "unmount: strange fs endpoint", vmp->m_fs_e);
|
||||||
|
|
||||||
if ((r = req_unmount(vmp->m_fs_e)) != OK) /* Not recoverable. */
|
if ((r = req_unmount(vmp->m_fs_e)) != OK) /* Not recoverable. */
|
||||||
printf("VFS: ignoring failed umount attempt (%d)\n", r);
|
printf("VFS: ignoring failed umount attempt (%d)\n", r);
|
||||||
|
|
||||||
|
if (is_nonedev(vmp->m_dev))
|
||||||
|
free_nonedev(vmp->m_dev);
|
||||||
|
|
||||||
|
if (label != NULL)
|
||||||
|
strcpy(label, vmp->m_label);
|
||||||
|
|
||||||
vmp->m_root_node->v_ref_count = 0;
|
vmp->m_root_node->v_ref_count = 0;
|
||||||
vmp->m_root_node->v_fs_count = 0;
|
vmp->m_root_node->v_fs_count = 0;
|
||||||
vmp->m_root_node->v_sdev = NO_DEV;
|
vmp->m_root_node->v_sdev = NO_DEV;
|
||||||
|
@ -421,27 +489,63 @@ Dev_t dev;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* name_to_dev *
|
* name_to_dev *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE dev_t name_to_dev()
|
PRIVATE dev_t name_to_dev(allow_mountpt)
|
||||||
|
int allow_mountpt;
|
||||||
{
|
{
|
||||||
/* Convert the block special file 'path' to a device number. If 'path'
|
/* Convert the block special file in 'user_fullpath' to a device number.
|
||||||
* is not a block special file, return error code in 'err_code'. */
|
* If the given path is not a block special file, but 'allow_mountpt' is set
|
||||||
|
* and the path is the root node of a mounted file system, return that device
|
||||||
|
* number. In all other cases, return NO_DEV and an error code in 'err_code'.
|
||||||
|
*/
|
||||||
int r;
|
int r;
|
||||||
dev_t dev;
|
dev_t dev;
|
||||||
struct vnode *vp;
|
struct vnode *vp;
|
||||||
|
|
||||||
/* Request lookup */
|
/* Request lookup */
|
||||||
if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) {
|
if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) {
|
||||||
printf("VFS: name_to_dev: lookup of '%s' failed\n", user_fullpath);
|
|
||||||
return(NO_DEV);
|
return(NO_DEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) {
|
if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL) {
|
||||||
|
dev = vp->v_sdev;
|
||||||
|
} else if (allow_mountpt && vp->v_vmnt->m_root_node == vp) {
|
||||||
|
dev = vp->v_dev;
|
||||||
|
} else {
|
||||||
err_code = ENOTBLK;
|
err_code = ENOTBLK;
|
||||||
dev = NO_DEV;
|
dev = NO_DEV;
|
||||||
} else
|
}
|
||||||
dev = vp->v_sdev;
|
|
||||||
|
|
||||||
put_vnode(vp);
|
put_vnode(vp);
|
||||||
return(dev);
|
return(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* is_nonedev *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE int is_nonedev(dev)
|
||||||
|
{
|
||||||
|
/* Return whether the given device is a "none" pseudo device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return (major(dev) == NONE_MAJOR &&
|
||||||
|
minor(dev) > 0 && minor(dev) <= NR_NONEDEVS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* find_free_nonedev *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE dev_t find_free_nonedev()
|
||||||
|
{
|
||||||
|
/* Find a free "none" pseudo device. Do not allocate it yet.
|
||||||
|
*/
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < NR_NONEDEVS; i++)
|
||||||
|
if (!GET_BIT(nonedev, i))
|
||||||
|
return makedev(NONE_MAJOR, i + 1);
|
||||||
|
|
||||||
|
err_code = EMFILE;
|
||||||
|
return NO_DEV;
|
||||||
|
}
|
||||||
|
|
|
@ -31,11 +31,12 @@
|
||||||
#define dev_nr m4_l3
|
#define dev_nr m4_l3
|
||||||
#define dev_style m4_l4
|
#define dev_style m4_l4
|
||||||
#define m_force m4_l5
|
#define m_force m4_l5
|
||||||
#define rd_only m1_i3
|
#define mount_flags m1_i3
|
||||||
#define request m1_i2
|
#define request m1_i2
|
||||||
#define sig m1_i2
|
#define sig m1_i2
|
||||||
#define endpt1 m1_i1
|
#define endpt1 m1_i1
|
||||||
#define fs_endpt m1_p3
|
#define fs_label m1_p3
|
||||||
|
#define umount_label m3_ca1
|
||||||
#define tp m2_l1
|
#define tp m2_l1
|
||||||
#define utime_actime m2_l1
|
#define utime_actime m2_l1
|
||||||
#define utime_modtime m2_l2
|
#define utime_modtime m2_l2
|
||||||
|
|
|
@ -94,7 +94,7 @@ _PROTOTYPE( int do_vm_mmap, (void) );
|
||||||
_PROTOTYPE( int do_fslogin, (void) );
|
_PROTOTYPE( int do_fslogin, (void) );
|
||||||
_PROTOTYPE( int do_mount, (void) );
|
_PROTOTYPE( int do_mount, (void) );
|
||||||
_PROTOTYPE( int do_umount, (void) );
|
_PROTOTYPE( int do_umount, (void) );
|
||||||
_PROTOTYPE( int unmount, (Dev_t dev) );
|
_PROTOTYPE( int unmount, (Dev_t dev, char *label) );
|
||||||
|
|
||||||
/* open.c */
|
/* open.c */
|
||||||
_PROTOTYPE( int do_close, (void) );
|
_PROTOTYPE( int do_close, (void) );
|
||||||
|
|
|
@ -4,8 +4,9 @@ EXTERN struct vmnt {
|
||||||
int m_fs_e; /* FS process' kernel endpoint */
|
int m_fs_e; /* FS process' kernel endpoint */
|
||||||
dev_t m_dev; /* device number */
|
dev_t m_dev; /* device number */
|
||||||
int m_flags; /* mount flags */
|
int m_flags; /* mount flags */
|
||||||
struct vnode *m_mounted_on; /* the vnode on which the partition is mounted */
|
struct vnode *m_mounted_on; /* vnode on which the partition is mounted */
|
||||||
struct vnode *m_root_node; /* root vnode */
|
struct vnode *m_root_node; /* root vnode */
|
||||||
|
char m_label[LABEL_MAX]; /* label of the file system process */
|
||||||
} vmnt[NR_MNTS];
|
} vmnt[NR_MNTS];
|
||||||
|
|
||||||
#define NIL_VMNT (struct vmnt *) 0
|
#define NIL_VMNT (struct vmnt *) 0
|
||||||
|
|
Loading…
Reference in a new issue