]> Zhao Yanbai Git Server - minix.git/commitdiff
mtab: support moving mount points
authorThomas Veerman <thomas@minix3.org>
Tue, 27 Nov 2012 17:33:59 +0000 (17:33 +0000)
committerThomas Veerman <thomas@minix3.org>
Thu, 29 Nov 2012 10:50:51 +0000 (10:50 +0000)
Also fix canonical_path function; it fails to parse some paths

servers/vfs/misc.c
servers/vfs/path.c
servers/vfs/proto.h
servers/vfs/vmnt.c

index 4c15d124911174f40ca278b4fe7b381ae5ab0836..3e4730dec4089159486053f2744c17a219e06acb 100644 (file)
@@ -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;
index 63de98f8000860623cd5d813ba0b33dccb027773..4b5de554ddff3ea282520f721b1b99d71d6ee91e 100644 (file)
@@ -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);
 }
 
index 1b528b7fa3bc4cb1d3dde9212419d858165d7c5e..d4277332fa22ebef2a10e10d6c031f98b336d846 100644 (file)
@@ -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);
index 5813e5435fe414617e20566613cce580ce44b8a3..6a074fb991b9581bf754220564b9a516d6b82b76 100644 (file)
@@ -6,6 +6,7 @@
 #include "threads.h"
 #include "vmnt.h"
 #include <assert.h>
+#include <string.h>
 #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 */
+       }
+  }
+}