diff --git a/lib/9p.js b/lib/9p.js index 4551ab91..5e9074d0 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -296,7 +296,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { ); break; - case 70: // link (just copying) + case 70: // link var req = marshall.Unmarshall(["w", "w", "s"], buffer, state); var dfid = req[0]; var fid = req[1]; diff --git a/lib/filesystem.js b/lib/filesystem.js index 9fc30f8d..03fa6bcb 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -360,8 +360,9 @@ FS.prototype.link_under_dir = function(parentid, idx, name) parent_inode.direntries.set(name, idx); parent_inode.updatedir = true; - // Root inode of other filesystems are already linked to themselves. - if(real_inode.fid !== 0) + // Root inodes of other filesystems have already accounted for their nlinks (due to their '..'). + // Also, don't mess with other filesystem's nlinks. + if(!this.is_a_root(idx)) { // Never store link information on forwarder. real_inode.nlinks++; @@ -400,8 +401,9 @@ FS.prototype.unlink_from_dir = function(parentid, name) const exists = parent_inode.direntries.delete(name); dbg_assert(exists, "Filesystem: Can't unlink non-existent file: " + name); - // Root inode of other filesystems are still linked to themselves. - if(real_inode.fid !== 0) + // Root inodes of other filesystems have already accounted for their nlinks (due to their '..'). + // Also, don't mess with other filesystem's nlinks. + if(!this.is_a_root(idx)) { // Never store link information on forwarder. real_inode.nlinks--; @@ -840,7 +842,7 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { if(ret < 0) return ret; } - else if(this.GetInode(idx).fid === 0) + else if(this.is_a_root(idx)) { // The actual inode is a root of some descendant filesystem. // Moving mountpoint across fs not supported - needs to update all corresponding forwarders. @@ -1598,6 +1600,17 @@ FS.prototype.is_forwarder = function(inode) return inode.status === STATUS_FORWARDING; }; +/** + * Whether the inode it points to is a root of some filesystem. + * @private + * @param {number} idx + * @return {boolean} + */ +FS.prototype.is_a_root = function(idx) +{ + return this.GetInode(idx).fid === 0; +}; + /** * Ensures forwarder exists, and returns such forwarder, for the described foreign inode. * @private