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 ENOENT = 2; /* No such file or directory */
|
||||
var EEXIST = 17; /* File exists */
|
||||
var EINVAL = 22; /* Invalid argument */
|
||||
var EOPNOTSUPP = 95; /* Operation is not supported */
|
||||
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)
|
||||
{
|
||||
dbg_assert(foreign_id !== 0, "Filesystem: root forwarder should not be created.");
|
||||
|
||||
const inode = this.CreateInode();
|
||||
|
||||
const idx = this.inodes.length;
|
||||
|
@ -1578,9 +1576,10 @@ FS.prototype.follow_fs = function(inode)
|
|||
};
|
||||
|
||||
/**
|
||||
* Mount another filesystem onto an existing directory.
|
||||
* @param {string} path Path to existing directrory relative to this filesystem.
|
||||
* Mount another filesystem to given path.
|
||||
* @param {string} path
|
||||
* @param {FS} fs
|
||||
* @return {number} inode id of mount point if successful, or -errno if mounting failed.
|
||||
*/
|
||||
FS.prototype.Mount = function(path, fs)
|
||||
{
|
||||
|
@ -1589,23 +1588,30 @@ FS.prototype.Mount = function(path, fs)
|
|||
|
||||
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);
|
||||
return -1;
|
||||
dbg_log("Mount failed: parent for path not found: " + path, LOG_9P);
|
||||
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)
|
||||
{
|
||||
const parent = this.inodes[path_infos.parentid];
|
||||
this.follow_fs(parent).Mount(path_infos.forward_path, fs);
|
||||
return;
|
||||
const ret = this.follow_fs(parent).Mount(path_infos.forward_path, fs);
|
||||
if(ret < 0) return ret;
|
||||
return this.get_forwarder(parent.mount_id, ret);
|
||||
}
|
||||
|
||||
const mount_id = this.mounts.length;
|
||||
this.mounts.push(new FSMountInfo(fs));
|
||||
|
||||
// Existing inode is already linked. Just set forwarding information.
|
||||
this.set_forwarder(path_infos.id, mount_id, 0);
|
||||
const idx = this.create_forwarder(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;
|
||||
}
|
||||
if(idx === -1)
|
||||
if(idx === -ENOENT)
|
||||
{
|
||||
callback(new FileNotFoundError());
|
||||
}
|
||||
if(idx === -EEXIST)
|
||||
{
|
||||
callback(new FileExistsError());
|
||||
}
|
||||
if(idx < 0)
|
||||
{
|
||||
callback(new Error("Failed to mount. Error number: " + (-idx)));
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
* @constructor
|
||||
|
|
|
@ -1337,6 +1337,7 @@ function do_mounts()
|
|||
{
|
||||
const path = tests[test_num].mounts[mount_num].path;
|
||||
emulator.serial0_send("mkdir -p /mnt" + path + "\n");
|
||||
emulator.serial0_send("rmdir /mnt" + path + "\n");
|
||||
emulator.serial0_send("echo done-premount\n");
|
||||
next_trigger = "done-premount";
|
||||
next_trigger_handler = () => mount(mount_num);
|
||||
|
|
Loading…
Reference in a new issue