Mount only onto non-existent paths, existent parent
If mountpoint already exists, then we're silently making its children inaccessible which may not be what we expected/intended. Create a new forwarder inode upon mounting.
This commit is contained in:
parent
3fe75a9130
commit
e683e812fd
|
@ -18,6 +18,7 @@ const VIRTIO_9P_MAX_TAGLEN = 254;
|
||||||
|
|
||||||
var EPERM = 1; /* Operation not permitted */
|
var EPERM = 1; /* Operation not permitted */
|
||||||
var ENOENT = 2; /* No such file or directory */
|
var ENOENT = 2; /* No such file or directory */
|
||||||
|
var EEXIST = 17; /* File exists */
|
||||||
var EINVAL = 22; /* Invalid argument */
|
var EINVAL = 22; /* Invalid argument */
|
||||||
var EOPNOTSUPP = 95; /* Operation is not supported */
|
var EOPNOTSUPP = 95; /* Operation is not supported */
|
||||||
var ENOTEMPTY = 39; /* Directory not empty */
|
var ENOTEMPTY = 39; /* Directory not empty */
|
||||||
|
|
|
@ -1489,8 +1489,6 @@ FS.prototype.set_forwarder = function(idx, mount_id, foreign_id)
|
||||||
*/
|
*/
|
||||||
FS.prototype.create_forwarder = function(mount_id, foreign_id)
|
FS.prototype.create_forwarder = function(mount_id, foreign_id)
|
||||||
{
|
{
|
||||||
dbg_assert(foreign_id !== 0, "Filesystem: root forwarder should not be created.");
|
|
||||||
|
|
||||||
const inode = this.CreateInode();
|
const inode = this.CreateInode();
|
||||||
|
|
||||||
const idx = this.inodes.length;
|
const idx = this.inodes.length;
|
||||||
|
@ -1578,9 +1576,10 @@ FS.prototype.follow_fs = function(inode)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mount another filesystem onto an existing directory.
|
* Mount another filesystem to given path.
|
||||||
* @param {string} path Path to existing directrory relative to this filesystem.
|
* @param {string} path
|
||||||
* @param {FS} fs
|
* @param {FS} fs
|
||||||
|
* @return {number} inode id of mount point if successful, or -errno if mounting failed.
|
||||||
*/
|
*/
|
||||||
FS.prototype.Mount = function(path, fs)
|
FS.prototype.Mount = function(path, fs)
|
||||||
{
|
{
|
||||||
|
@ -1589,23 +1588,30 @@ FS.prototype.Mount = function(path, fs)
|
||||||
|
|
||||||
const path_infos = this.SearchPath(path);
|
const path_infos = this.SearchPath(path);
|
||||||
|
|
||||||
if(path_infos.id === -1)
|
if(path_infos.parentid === -1)
|
||||||
{
|
{
|
||||||
dbg_log("Mount failed: path not found: " + path, LOG_9P);
|
dbg_log("Mount failed: parent for path not found: " + path, LOG_9P);
|
||||||
return -1;
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
if(path_infos.id !== -1)
|
||||||
|
{
|
||||||
|
dbg_log("Mount failed: file already exists at path: " + path, LOG_9P);
|
||||||
|
return -EEXIST;
|
||||||
}
|
}
|
||||||
if(path_infos.forward_path)
|
if(path_infos.forward_path)
|
||||||
{
|
{
|
||||||
const parent = this.inodes[path_infos.parentid];
|
const parent = this.inodes[path_infos.parentid];
|
||||||
this.follow_fs(parent).Mount(path_infos.forward_path, fs);
|
const ret = this.follow_fs(parent).Mount(path_infos.forward_path, fs);
|
||||||
return;
|
if(ret < 0) return ret;
|
||||||
|
return this.get_forwarder(parent.mount_id, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
const mount_id = this.mounts.length;
|
const mount_id = this.mounts.length;
|
||||||
this.mounts.push(new FSMountInfo(fs));
|
this.mounts.push(new FSMountInfo(fs));
|
||||||
|
|
||||||
// Existing inode is already linked. Just set forwarding information.
|
const idx = this.create_forwarder(mount_id, 0);
|
||||||
this.set_forwarder(path_infos.id, mount_id, 0);
|
this.inodes[idx].name = path_infos.name;
|
||||||
|
this.link_under_dir(idx, path_infos.parentid);
|
||||||
|
|
||||||
return path_infos.id;
|
return idx;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1089,10 +1089,18 @@ V86Starter.prototype.mount_fs = function(path, baseurl, basefs, callback)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(idx === -1)
|
if(idx === -ENOENT)
|
||||||
{
|
{
|
||||||
callback(new FileNotFoundError());
|
callback(new FileNotFoundError());
|
||||||
}
|
}
|
||||||
|
if(idx === -EEXIST)
|
||||||
|
{
|
||||||
|
callback(new FileExistsError());
|
||||||
|
}
|
||||||
|
if(idx < 0)
|
||||||
|
{
|
||||||
|
callback(new Error("Failed to mount. Error number: " + (-idx)));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
callback(null);
|
callback(null);
|
||||||
|
@ -1204,6 +1212,18 @@ V86Starter.prototype.read_file = function(file, callback)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
* @constructor
|
||||||
|
*
|
||||||
|
* @param {string=} message
|
||||||
|
*/
|
||||||
|
function FileExistsError(message)
|
||||||
|
{
|
||||||
|
this.message = message || "File already exists";
|
||||||
|
}
|
||||||
|
FileNotFoundError.prototype = Error.prototype;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ignore
|
* @ignore
|
||||||
* @constructor
|
* @constructor
|
||||||
|
|
|
@ -1337,6 +1337,7 @@ function do_mounts()
|
||||||
{
|
{
|
||||||
const path = tests[test_num].mounts[mount_num].path;
|
const path = tests[test_num].mounts[mount_num].path;
|
||||||
emulator.serial0_send("mkdir -p /mnt" + path + "\n");
|
emulator.serial0_send("mkdir -p /mnt" + path + "\n");
|
||||||
|
emulator.serial0_send("rmdir /mnt" + path + "\n");
|
||||||
emulator.serial0_send("echo done-premount\n");
|
emulator.serial0_send("echo done-premount\n");
|
||||||
next_trigger = "done-premount";
|
next_trigger = "done-premount";
|
||||||
next_trigger_handler = () => mount(mount_num);
|
next_trigger_handler = () => mount(mount_num);
|
||||||
|
|
Loading…
Reference in a new issue