tools/llvm: Do not build with symbols
[minix3.git] / minix / servers / vfs / vmnt.c
blob7e17d204fcaa6d3ad471e4a9bf70db9fbce8a976
1 /* Virtual mount table related routines.
3 */
5 #include "fs.h"
6 #include "vmnt.h"
7 #include <assert.h>
8 #include <string.h>
10 static int is_vmnt_locked(struct vmnt *vmp);
11 static void clear_vmnt(struct vmnt *vmp);
13 /* Is vmp pointer reasonable? */
14 #define SANEVMP(v) ((((v) >= &vmnt[0] && (v) < &vmnt[NR_MNTS])))
15 #define BADVMP(v, f, l) printf("%s:%d: bad vmp %p\n", f, l, v)
16 /* vp check that panics */
17 #define ASSERTVMP(v) if(!SANEVMP(v)) { \
18 BADVMP(v, __FILE__, __LINE__); panic("bad vmp"); }
20 #if LOCK_DEBUG
21 /*===========================================================================*
22 * check_vmnt_locks_by_me *
23 *===========================================================================*/
24 void check_vmnt_locks_by_me(struct fproc *rfp)
26 /* Check whether this thread still has locks held on vmnts */
27 struct vmnt *vmp;
29 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
30 if (tll_locked_by_me(&vmp->m_lock))
31 panic("Thread %d still holds vmnt lock on vmp %p call_nr=%d\n",
32 mthread_self(), vmp, job_call_nr);
35 if (rfp->fp_vmnt_rdlocks != 0)
36 panic("Thread %d still holds read locks on a vmnt (%d) call_nr=%d\n",
37 mthread_self(), rfp->fp_vmnt_rdlocks, job_call_nr);
39 #endif
41 /*===========================================================================*
42 * check_vmnt_locks *
43 *===========================================================================*/
44 void check_vmnt_locks()
46 struct vmnt *vmp;
47 int count = 0;
49 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++)
50 if (is_vmnt_locked(vmp)) {
51 count++;
52 printf("vmnt %p is %s, fs_e=%d dev=%llx\n", vmp, (tll_islocked(&vmp->m_lock) ? "locked":"pending locked"), vmp->m_fs_e, vmp->m_dev);
55 if (count) panic("%d locked vmnts\n", count);
56 #if 0
57 printf("check_vmnt_locks OK\n");
58 #endif
61 /*===========================================================================*
62 * mark_vmnt_free *
63 *===========================================================================*/
64 void mark_vmnt_free(struct vmnt *vmp)
66 ASSERTVMP(vmp);
68 vmp->m_fs_e = NONE;
69 vmp->m_dev = NO_DEV;
72 /*===========================================================================*
73 * clear_vmnt *
74 *===========================================================================*/
75 static void clear_vmnt(struct vmnt *vmp)
77 /* Reset vmp to initial parameters */
78 ASSERTVMP(vmp);
80 vmp->m_fs_e = NONE;
81 vmp->m_dev = NO_DEV;
82 vmp->m_flags = 0;
83 vmp->m_mounted_on = NULL;
84 vmp->m_root_node = NULL;
85 vmp->m_label[0] = '\0';
86 vmp->m_comm.c_max_reqs = 1;
87 vmp->m_comm.c_cur_reqs = 0;
88 vmp->m_comm.c_req_queue = NULL;
91 /*===========================================================================*
92 * get_free_vmnt *
93 *===========================================================================*/
94 struct vmnt *get_free_vmnt(void)
96 struct vmnt *vmp;
98 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
99 if (vmp->m_dev == NO_DEV) {
100 clear_vmnt(vmp);
101 return(vmp);
105 return(NULL);
108 /*===========================================================================*
109 * find_vmnt *
110 *===========================================================================*/
111 struct vmnt *find_vmnt(endpoint_t fs_e)
113 /* Find the vmnt belonging to an FS with endpoint 'fs_e' iff it's in use */
114 struct vmnt *vp;
116 for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp)
117 if (vp->m_fs_e == fs_e && vp->m_dev != NO_DEV)
118 return(vp);
120 return(NULL);
123 /*===========================================================================*
124 * init_vmnts *
125 *===========================================================================*/
126 void init_vmnts(void)
128 /* Initialize vmnt table */
129 struct vmnt *vmp;
131 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
132 clear_vmnt(vmp);
133 tll_init(&vmp->m_lock);
137 /*===========================================================================*
138 * is_vmnt_locked *
139 *===========================================================================*/
140 static int is_vmnt_locked(struct vmnt *vmp)
142 ASSERTVMP(vmp);
143 return(tll_islocked(&vmp->m_lock) || tll_haspendinglock(&vmp->m_lock));
146 /*===========================================================================*
147 * lock_vmnt *
148 *===========================================================================*/
149 int lock_vmnt(struct vmnt *vmp, tll_access_t locktype)
151 int r;
152 tll_access_t initial_locktype;
154 ASSERTVMP(vmp);
156 initial_locktype = (locktype == VMNT_EXCL) ? VMNT_WRITE : locktype;
158 if (vmp->m_fs_e == who_e) return(EDEADLK);
160 r = tll_lock(&vmp->m_lock, initial_locktype);
162 if (r == EBUSY) return(r);
164 if (initial_locktype != locktype) {
165 upgrade_vmnt_lock(vmp);
168 #if LOCK_DEBUG
169 if (locktype == VMNT_READ)
170 fp->fp_vmnt_rdlocks++;
171 #endif
173 return(OK);
176 /*===========================================================================*
177 * vmnt_unmap_by_endpoint *
178 *===========================================================================*/
179 void vmnt_unmap_by_endpt(endpoint_t proc_e)
181 struct vmnt *vmp;
183 if ((vmp = find_vmnt(proc_e)) != NULL) {
184 mark_vmnt_free(vmp);
185 fs_cancel(vmp);
186 invalidate_filp_by_endpt(proc_e);
187 if (vmp->m_mounted_on) {
188 /* Only put mount point when it was actually used as mount
189 * point. That is, the mount was succesful. */
190 put_vnode(vmp->m_mounted_on);
195 /*===========================================================================*
196 * unlock_vmnt *
197 *===========================================================================*/
198 void unlock_vmnt(struct vmnt *vmp)
200 ASSERTVMP(vmp);
202 #if LOCK_DEBUG
203 /* Decrease read-only lock counter when not locked as VMNT_WRITE or
204 * VMNT_EXCL */
205 if (!tll_locked_by_me(&vmp->m_lock))
206 fp->fp_vmnt_rdlocks--;
207 #endif
209 tll_unlock(&vmp->m_lock);
211 #if LOCK_DEBUG
212 assert(!tll_locked_by_me(&vmp->m_lock));
213 #endif
217 /*===========================================================================*
218 * downgrade_vmnt_lock *
219 *===========================================================================*/
220 void downgrade_vmnt_lock(struct vmnt *vmp)
222 ASSERTVMP(vmp);
223 tll_downgrade(&vmp->m_lock);
225 #if LOCK_DEBUG
226 /* If we're no longer the owner of a lock, we downgraded to VMNT_READ */
227 if (!tll_locked_by_me(&vmp->m_lock)) {
228 fp->fp_vmnt_rdlocks++;
230 #endif
233 /*===========================================================================*
234 * upgrade_vmnt_lock *
235 *===========================================================================*/
236 void upgrade_vmnt_lock(struct vmnt *vmp)
238 ASSERTVMP(vmp);
239 tll_upgrade(&vmp->m_lock);
242 /*===========================================================================*
243 * fetch_vmnt_paths *
244 *===========================================================================*/
245 void fetch_vmnt_paths(void)
247 struct vmnt *vmp;
248 struct vnode *cur_wd;
249 char orig_path[PATH_MAX];
251 cur_wd = fp->fp_wd;
253 for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
254 if (vmp->m_dev == NO_DEV)
255 continue;
256 if (vmp->m_fs_e == PFS_PROC_NR)
257 continue;
259 strlcpy(orig_path, vmp->m_mount_path, PATH_MAX);
261 /* Find canonical path */
262 if (canonical_path(vmp->m_mount_path, fp) != OK) {
263 /* We failed to find it (moved somewhere else?). Let's try
264 * again by starting at the node on which we are mounted:
265 * pretend that node is our working directory and look for the
266 * canonical path of the relative path to the mount point
267 * (which should be in our 'working directory').
269 char *mp;
270 int len;
272 fp->fp_wd = vmp->m_mounted_on; /* Change our working dir */
274 /* Isolate the mount point name of the full path */
275 len = strlen(vmp->m_mount_path);
276 if (vmp->m_mount_path[len - 1] == '/') {
277 vmp->m_mount_path[len - 1] = '\0';
279 mp = strrchr(vmp->m_mount_path, '/');
280 strlcpy(vmp->m_mount_path, mp+1, NAME_MAX+1);
282 if (canonical_path(vmp->m_mount_path, fp) != OK) {
283 /* Our second try failed too. Maybe an FS has crashed
284 * and we're missing part of the tree. Revert path.
286 strlcpy(vmp->m_mount_path, orig_path, PATH_MAX);
288 fp->fp_wd = cur_wd; /* Revert working dir */