From: Thomas Veerman Date: Tue, 27 Nov 2012 17:33:59 +0000 (+0000) Subject: mtab: support moving mount points X-Git-Tag: v3.2.1~180 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/doc/syslog.3.html?a=commitdiff_plain;h=179261a9b61c9ed8ce3df1e32d9a0808a91e2bb7;p=minix.git mtab: support moving mount points Also fix canonical_path function; it fails to parse some paths --- diff --git a/servers/vfs/misc.c b/servers/vfs/misc.c index 4c15d1249..3e4730dec 100644 --- a/servers/vfs/misc.c +++ b/servers/vfs/misc.c @@ -92,6 +92,7 @@ int do_getsysinfo() break; #endif case SI_VMNT_TAB: + fetch_vmnt_paths(); src_addr = (vir_bytes) vmnt; len = sizeof(struct vmnt) * NR_MNTS; break; diff --git a/servers/vfs/path.c b/servers/vfs/path.c index 63de98f80..4b5de554d 100644 --- a/servers/vfs/path.c +++ b/servers/vfs/path.c @@ -656,7 +656,8 @@ struct fproc *rfp; char temp_path[PATH_MAX]; struct lookup resolve; - dir_vp = NULL; + parent_dir = dir_vp = NULL; + parent_vmp = dir_vmp = NULL; strlcpy(temp_path, orig_path, PATH_MAX); temp_path[PATH_MAX - 1] = '\0'; @@ -678,6 +679,9 @@ struct fproc *rfp; */ strlcpy(orig_path, temp_path, NAME_MAX+1); /* Store file name */ + /* If we're just crossing a mount point, our name has changed to '.' */ + if (!strcmp(orig_path, ".")) orig_path[0] = '\0'; + /* check if the file is a symlink, if so resolve it */ r = rdlink_direct(orig_path, temp_path, rfp); @@ -706,6 +710,10 @@ struct fproc *rfp; /* check if we're at the root node of the file system */ if (dir_vp->v_vmnt->m_root_node == dir_vp) { + if (dir_vp->v_vmnt->m_mounted_on == NULL) { + /* Bail out, we can't go any higher */ + break; + } unlock_vnode(dir_vp); unlock_vmnt(dir_vmp); put_vnode(dir_vp); @@ -769,18 +777,23 @@ struct fproc *rfp; unlock_vmnt(dir_vmp); put_vnode(dir_vp); dir_vp = parent_dir; + dir_vmp = parent_vmp; + parent_vmp = NULL; } + unlock_vmnt(dir_vmp); unlock_vnode(dir_vp); - unlock_vmnt(parent_vmp); - put_vnode(dir_vp); /* add the leading slash */ + len = strlen(orig_path); if (strlen(orig_path) >= PATH_MAX) return(ENAMETOOLONG); - memmove(orig_path+1, orig_path, strlen(orig_path)); + memmove(orig_path+1, orig_path, len); orig_path[0] = '/'; + /* remove trailing slash if there is any */ + if (len > 1 && orig_path[len] == '/') orig_path[len] = '\0'; + return(OK); } diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index 1b528b7fa..d4277332f 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -315,6 +315,7 @@ void init_vmnts(void); int lock_vmnt(struct vmnt *vp, tll_access_t locktype); void unlock_vmnt(struct vmnt *vp); void vmnt_unmap_by_endpt(endpoint_t proc_e); +void fetch_vmnt_paths(void); /* vnode.c */ void check_vnode_locks(void); diff --git a/servers/vfs/vmnt.c b/servers/vfs/vmnt.c index 5813e5435..6a074fb99 100644 --- a/servers/vfs/vmnt.c +++ b/servers/vfs/vmnt.c @@ -6,6 +6,7 @@ #include "threads.h" #include "vmnt.h" #include +#include #include "fproc.h" static int is_vmnt_locked(struct vmnt *vmp); @@ -214,3 +215,54 @@ void unlock_vmnt(struct vmnt *vmp) #endif } + +/*===========================================================================* + * fetch_vmnt_paths * + *===========================================================================*/ +void fetch_vmnt_paths(void) +{ + struct vmnt *vmp; + struct vnode *cur_wd; + char orig_path[PATH_MAX]; + + cur_wd = fp->fp_wd; + + for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) { + if (vmp->m_dev == NO_DEV) + continue; + if (vmp->m_fs_e == PFS_PROC_NR) + continue; + + strlcpy(orig_path, vmp->m_mount_path, PATH_MAX); + + /* Find canonical path */ + if (canonical_path(vmp->m_mount_path, fp) != OK) { + /* We failed to find it (moved somewhere else?). Let's try + * again by starting at the node on which we are mounted: + * pretend that node is our working directory and look for the + * canonical path of the relative path to the mount point + * (which should be in our 'working directory'). + */ + char *mp; + int len; + + fp->fp_wd = vmp->m_mounted_on; /* Change our working dir */ + + /* Isolate the mount point name of the full path */ + len = strlen(vmp->m_mount_path); + if (vmp->m_mount_path[len - 1] == '/') { + vmp->m_mount_path[len - 1] = '\0'; + } + mp = strrchr(vmp->m_mount_path, '/'); + strlcpy(vmp->m_mount_path, mp+1, NAME_MAX+1); + + if (canonical_path(vmp->m_mount_path, fp) != OK) { + /* Our second try failed too. Maybe an FS has crashed + * and we're missing part of the tree. Revert path. + */ + strlcpy(vmp->m_mount_path, orig_path, PATH_MAX); + } + fp->fp_wd = cur_wd; /* Revert working dir */ + } + } +}