libexec exec fix
[minix.git] / servers / vfs / vmnt.c
blob6a074fb991b9581bf754220564b9a516d6b82b76
1 /* Virtual mount table related routines.
3 */
5 #include "fs.h"
6 #include "threads.h"
7 #include "vmnt.h"
8 #include <assert.h>
9 #include <string.h>
10 #include "fproc.h"
12 static int is_vmnt_locked(struct vmnt *vmp);
13 static void clear_vmnt(struct vmnt *vmp);
15 /* Is vmp pointer reasonable? */
16 #define SANEVMP(v) ((((v) >= &vmnt[0] && (v) < &vmnt[NR_MNTS])))
17 #define BADVMP(v, f, l) printf("%s:%d: bad vmp %p\n", f, l, v)
18 /* vp check that panics */
19 #define ASSERTVMP(v) if(!SANEVMP(v)) { \
20 BADVMP(v, __FILE__, __LINE__); panic("bad vmp"); }
22 #if LOCK_DEBUG
23 /*===========================================================================*
24 * check_vmnt_locks_by_me *
25 *===========================================================================*/
26 void check_vmnt_locks_by_me(struct fproc *rfp)
28 /* Check whether this thread still has locks held on vmnts */
29 struct vmnt *vmp;
31 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
32 if (tll_locked_by_me(&vmp->m_lock))
33 panic("Thread %d still holds vmnt lock on vmp %p call_nr=%d\n",
34 mthread_self(), vmp, job_call_nr);
37 if (rfp->fp_vmnt_rdlocks != 0)
38 panic("Thread %d still holds read locks on a vmnt (%d) call_nr=%d\n",
39 mthread_self(), rfp->fp_vmnt_rdlocks, job_call_nr);
41 #endif
43 /*===========================================================================*
44 * check_vmnt_locks *
45 *===========================================================================*/
46 void check_vmnt_locks()
48 struct vmnt *vmp;
49 int count = 0;
51 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++)
52 if (is_vmnt_locked(vmp)) {
53 count++;
54 printf("vmnt %p is %s, fs_e=%d dev=%d\n", vmp, (tll_islocked(&vmp->m_lock) ? "locked":"pending locked"), vmp->m_fs_e, vmp->m_dev);
57 if (count) panic("%d locked vmnts\n", count);
58 #if 0
59 printf("check_vmnt_locks OK\n");
60 #endif
63 /*===========================================================================*
64 * mark_vmnt_free *
65 *===========================================================================*/
66 void mark_vmnt_free(struct vmnt *vmp)
68 ASSERTVMP(vmp);
70 vmp->m_fs_e = NONE;
71 vmp->m_dev = NO_DEV;
74 /*===========================================================================*
75 * clear_vmnt *
76 *===========================================================================*/
77 static void clear_vmnt(struct vmnt *vmp)
79 /* Reset vmp to initial parameters */
80 ASSERTVMP(vmp);
82 vmp->m_fs_e = NONE;
83 vmp->m_dev = NO_DEV;
84 vmp->m_flags = 0;
85 vmp->m_mounted_on = NULL;
86 vmp->m_root_node = NULL;
87 vmp->m_label[0] = '\0';
88 vmp->m_comm.c_max_reqs = 1;
89 vmp->m_comm.c_cur_reqs = 0;
90 vmp->m_comm.c_req_queue = NULL;
93 /*===========================================================================*
94 * get_free_vmnt *
95 *===========================================================================*/
96 struct vmnt *get_free_vmnt(void)
98 struct vmnt *vmp;
100 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
101 if (vmp->m_dev == NO_DEV) {
102 clear_vmnt(vmp);
103 return(vmp);
107 return(NULL);
110 /*===========================================================================*
111 * find_vmnt *
112 *===========================================================================*/
113 struct vmnt *find_vmnt(endpoint_t fs_e)
115 /* Find the vmnt belonging to an FS with endpoint 'fs_e' iff it's in use */
116 struct vmnt *vp;
118 for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp)
119 if (vp->m_fs_e == fs_e && vp->m_dev != NO_DEV)
120 return(vp);
122 return(NULL);
125 /*===========================================================================*
126 * init_vmnts *
127 *===========================================================================*/
128 void init_vmnts(void)
130 /* Initialize vmnt table */
131 struct vmnt *vmp;
133 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
134 clear_vmnt(vmp);
135 tll_init(&vmp->m_lock);
139 /*===========================================================================*
140 * is_vmnt_locked *
141 *===========================================================================*/
142 static int is_vmnt_locked(struct vmnt *vmp)
144 ASSERTVMP(vmp);
145 return(tll_islocked(&vmp->m_lock) || tll_haspendinglock(&vmp->m_lock));
148 /*===========================================================================*
149 * lock_vmnt *
150 *===========================================================================*/
151 int lock_vmnt(struct vmnt *vmp, tll_access_t locktype)
153 int r;
154 tll_access_t initial_locktype;
156 ASSERTVMP(vmp);
158 initial_locktype = (locktype == VMNT_EXCL) ? VMNT_WRITE : locktype;
160 if (vmp->m_fs_e == who_e) return(EDEADLK);
162 r = tll_lock(&vmp->m_lock, initial_locktype);
164 if (r == EBUSY) return(r);
166 if (initial_locktype != locktype) {
167 tll_upgrade(&vmp->m_lock);
170 #if LOCK_DEBUG
171 if (locktype == VMNT_READ)
172 fp->fp_vmnt_rdlocks++;
173 #endif
175 return(OK);
178 /*===========================================================================*
179 * vmnt_unmap_by_endpoint *
180 *===========================================================================*/
181 void vmnt_unmap_by_endpt(endpoint_t proc_e)
183 struct vmnt *vmp;
185 if ((vmp = find_vmnt(proc_e)) != NULL) {
186 mark_vmnt_free(vmp);
187 fs_cancel(vmp);
188 invalidate_filp_by_endpt(proc_e);
189 if (vmp->m_mounted_on) {
190 /* Only put mount point when it was actually used as mount
191 * point. That is, the mount was succesful. */
192 put_vnode(vmp->m_mounted_on);
197 /*===========================================================================*
198 * unlock_vmnt *
199 *===========================================================================*/
200 void unlock_vmnt(struct vmnt *vmp)
202 ASSERTVMP(vmp);
204 #if LOCK_DEBUG
205 /* Decrease read-only lock counter when not locked as VMNT_WRITE or
206 * VMNT_EXCL */
207 if (!tll_locked_by_me(&vmp->m_lock))
208 fp->fp_vmnt_rdlocks--;
209 #endif
211 tll_unlock(&vmp->m_lock);
213 #if LOCK_DEBUG
214 assert(!tll_locked_by_me(&vmp->m_lock));
215 #endif
219 /*===========================================================================*
220 * fetch_vmnt_paths *
221 *===========================================================================*/
222 void fetch_vmnt_paths(void)
224 struct vmnt *vmp;
225 struct vnode *cur_wd;
226 char orig_path[PATH_MAX];
228 cur_wd = fp->fp_wd;
230 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
231 if (vmp->m_dev == NO_DEV)
232 continue;
233 if (vmp->m_fs_e == PFS_PROC_NR)
234 continue;
236 strlcpy(orig_path, vmp->m_mount_path, PATH_MAX);
238 /* Find canonical path */
239 if (canonical_path(vmp->m_mount_path, fp) != OK) {
240 /* We failed to find it (moved somewhere else?). Let's try
241 * again by starting at the node on which we are mounted:
242 * pretend that node is our working directory and look for the
243 * canonical path of the relative path to the mount point
244 * (which should be in our 'working directory').
246 char *mp;
247 int len;
249 fp->fp_wd = vmp->m_mounted_on; /* Change our working dir */
251 /* Isolate the mount point name of the full path */
252 len = strlen(vmp->m_mount_path);
253 if (vmp->m_mount_path[len - 1] == '/') {
254 vmp->m_mount_path[len - 1] = '\0';
256 mp = strrchr(vmp->m_mount_path, '/');
257 strlcpy(vmp->m_mount_path, mp+1, NAME_MAX+1);
259 if (canonical_path(vmp->m_mount_path, fp) != OK) {
260 /* Our second try failed too. Maybe an FS has crashed
261 * and we're missing part of the tree. Revert path.
263 strlcpy(vmp->m_mount_path, orig_path, PATH_MAX);
265 fp->fp_wd = cur_wd; /* Revert working dir */