xref: /minix3/minix/servers/vfs/vmnt.c (revision a0814afb2e128f52ed10c9a5d4c91bf6abc22290)
1433d6423SLionel Sambuc /* Virtual mount table related routines.
2433d6423SLionel Sambuc  *
3433d6423SLionel Sambuc  */
4433d6423SLionel Sambuc 
5433d6423SLionel Sambuc #include "fs.h"
6433d6423SLionel Sambuc #include "vmnt.h"
7433d6423SLionel Sambuc #include <assert.h>
8433d6423SLionel Sambuc #include <string.h>
9433d6423SLionel Sambuc 
10433d6423SLionel Sambuc static int is_vmnt_locked(struct vmnt *vmp);
11433d6423SLionel Sambuc static void clear_vmnt(struct vmnt *vmp);
12433d6423SLionel Sambuc 
13433d6423SLionel Sambuc /* Is vmp pointer reasonable? */
14433d6423SLionel Sambuc #define SANEVMP(v) ((((v) >= &vmnt[0] && (v) < &vmnt[NR_MNTS])))
15433d6423SLionel Sambuc #define BADVMP(v, f, l) printf("%s:%d: bad vmp %p\n", f, l, v)
16433d6423SLionel Sambuc /* vp check that panics */
17433d6423SLionel Sambuc #define ASSERTVMP(v) if(!SANEVMP(v)) { \
18433d6423SLionel Sambuc 	BADVMP(v, __FILE__, __LINE__); panic("bad vmp"); }
19433d6423SLionel Sambuc 
20433d6423SLionel Sambuc #if LOCK_DEBUG
21433d6423SLionel Sambuc /*===========================================================================*
22433d6423SLionel Sambuc  *				check_vmnt_locks_by_me			     *
23433d6423SLionel Sambuc  *===========================================================================*/
check_vmnt_locks_by_me(struct fproc * rfp)24433d6423SLionel Sambuc void check_vmnt_locks_by_me(struct fproc *rfp)
25433d6423SLionel Sambuc {
26433d6423SLionel Sambuc /* Check whether this thread still has locks held on vmnts */
27433d6423SLionel Sambuc   struct vmnt *vmp;
28433d6423SLionel Sambuc 
29433d6423SLionel Sambuc   for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
30433d6423SLionel Sambuc 	if (tll_locked_by_me(&vmp->m_lock))
31433d6423SLionel Sambuc 		panic("Thread %d still holds vmnt lock on vmp %p call_nr=%d\n",
32433d6423SLionel Sambuc 		      mthread_self(), vmp, job_call_nr);
33433d6423SLionel Sambuc   }
34433d6423SLionel Sambuc 
35433d6423SLionel Sambuc   if (rfp->fp_vmnt_rdlocks != 0)
36433d6423SLionel Sambuc 	panic("Thread %d still holds read locks on a vmnt (%d) call_nr=%d\n",
37433d6423SLionel Sambuc 	      mthread_self(), rfp->fp_vmnt_rdlocks, job_call_nr);
38433d6423SLionel Sambuc }
39433d6423SLionel Sambuc #endif
40433d6423SLionel Sambuc 
41433d6423SLionel Sambuc /*===========================================================================*
42433d6423SLionel Sambuc  *				check_vmnt_locks			     *
43433d6423SLionel Sambuc  *===========================================================================*/
44*a0814afbSRichard Sailer void
check_vmnt_locks(void)45*a0814afbSRichard Sailer check_vmnt_locks(void)
46433d6423SLionel Sambuc {
47433d6423SLionel Sambuc   struct vmnt *vmp;
48433d6423SLionel Sambuc   int count = 0;
49433d6423SLionel Sambuc 
50433d6423SLionel Sambuc   for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++)
51433d6423SLionel Sambuc 	if (is_vmnt_locked(vmp)) {
52433d6423SLionel Sambuc 		count++;
53433d6423SLionel Sambuc 		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);
54433d6423SLionel Sambuc 	}
55433d6423SLionel Sambuc 
56433d6423SLionel Sambuc   if (count) panic("%d locked vmnts\n", count);
57433d6423SLionel Sambuc #if 0
58433d6423SLionel Sambuc   printf("check_vmnt_locks OK\n");
59433d6423SLionel Sambuc #endif
60433d6423SLionel Sambuc }
61433d6423SLionel Sambuc 
62433d6423SLionel Sambuc /*===========================================================================*
63433d6423SLionel Sambuc  *                             mark_vmnt_free				     *
64433d6423SLionel Sambuc  *===========================================================================*/
mark_vmnt_free(struct vmnt * vmp)65433d6423SLionel Sambuc void mark_vmnt_free(struct vmnt *vmp)
66433d6423SLionel Sambuc {
67433d6423SLionel Sambuc   ASSERTVMP(vmp);
68433d6423SLionel Sambuc 
69433d6423SLionel Sambuc   vmp->m_fs_e = NONE;
70433d6423SLionel Sambuc   vmp->m_dev = NO_DEV;
71433d6423SLionel Sambuc }
72433d6423SLionel Sambuc 
73433d6423SLionel Sambuc /*===========================================================================*
74433d6423SLionel Sambuc  *                             clear_vmnt				     *
75433d6423SLionel Sambuc  *===========================================================================*/
clear_vmnt(struct vmnt * vmp)76433d6423SLionel Sambuc static void clear_vmnt(struct vmnt *vmp)
77433d6423SLionel Sambuc {
78433d6423SLionel Sambuc /* Reset vmp to initial parameters */
79433d6423SLionel Sambuc   ASSERTVMP(vmp);
80433d6423SLionel Sambuc 
81433d6423SLionel Sambuc   vmp->m_fs_e = NONE;
82433d6423SLionel Sambuc   vmp->m_dev = NO_DEV;
83433d6423SLionel Sambuc   vmp->m_flags = 0;
84433d6423SLionel Sambuc   vmp->m_mounted_on = NULL;
85433d6423SLionel Sambuc   vmp->m_root_node = NULL;
86433d6423SLionel Sambuc   vmp->m_label[0] = '\0';
87433d6423SLionel Sambuc   vmp->m_comm.c_max_reqs = 1;
88433d6423SLionel Sambuc   vmp->m_comm.c_cur_reqs = 0;
89433d6423SLionel Sambuc   vmp->m_comm.c_req_queue = NULL;
90433d6423SLionel Sambuc }
91433d6423SLionel Sambuc 
92433d6423SLionel Sambuc /*===========================================================================*
93433d6423SLionel Sambuc  *                             get_free_vmnt				     *
94433d6423SLionel Sambuc  *===========================================================================*/
get_free_vmnt(void)95433d6423SLionel Sambuc struct vmnt *get_free_vmnt(void)
96433d6423SLionel Sambuc {
97433d6423SLionel Sambuc   struct vmnt *vmp;
98433d6423SLionel Sambuc 
99433d6423SLionel Sambuc   for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
100433d6423SLionel Sambuc 	if (vmp->m_dev == NO_DEV) {
101433d6423SLionel Sambuc 		clear_vmnt(vmp);
102433d6423SLionel Sambuc 		return(vmp);
103433d6423SLionel Sambuc 	}
104433d6423SLionel Sambuc   }
105433d6423SLionel Sambuc 
106433d6423SLionel Sambuc   return(NULL);
107433d6423SLionel Sambuc }
108433d6423SLionel Sambuc 
109433d6423SLionel Sambuc /*===========================================================================*
110433d6423SLionel Sambuc  *                             find_vmnt				     *
111433d6423SLionel Sambuc  *===========================================================================*/
find_vmnt(endpoint_t fs_e)112433d6423SLionel Sambuc struct vmnt *find_vmnt(endpoint_t fs_e)
113433d6423SLionel Sambuc {
114433d6423SLionel Sambuc /* Find the vmnt belonging to an FS with endpoint 'fs_e' iff it's in use */
115433d6423SLionel Sambuc   struct vmnt *vp;
116433d6423SLionel Sambuc 
117433d6423SLionel Sambuc   for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp)
118433d6423SLionel Sambuc 	if (vp->m_fs_e == fs_e && vp->m_dev != NO_DEV)
119433d6423SLionel Sambuc 		return(vp);
120433d6423SLionel Sambuc 
121433d6423SLionel Sambuc   return(NULL);
122433d6423SLionel Sambuc }
123433d6423SLionel Sambuc 
124433d6423SLionel Sambuc /*===========================================================================*
125433d6423SLionel Sambuc  *                             init_vmnts				     *
126433d6423SLionel Sambuc  *===========================================================================*/
init_vmnts(void)127433d6423SLionel Sambuc void init_vmnts(void)
128433d6423SLionel Sambuc {
129433d6423SLionel Sambuc /* Initialize vmnt table */
130433d6423SLionel Sambuc   struct vmnt *vmp;
131433d6423SLionel Sambuc 
132433d6423SLionel Sambuc   for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
133433d6423SLionel Sambuc 	clear_vmnt(vmp);
134433d6423SLionel Sambuc 	tll_init(&vmp->m_lock);
135433d6423SLionel Sambuc   }
136433d6423SLionel Sambuc }
137433d6423SLionel Sambuc 
138433d6423SLionel Sambuc /*===========================================================================*
139433d6423SLionel Sambuc  *                             is_vmnt_locked				     *
140433d6423SLionel Sambuc  *===========================================================================*/
is_vmnt_locked(struct vmnt * vmp)141433d6423SLionel Sambuc static int is_vmnt_locked(struct vmnt *vmp)
142433d6423SLionel Sambuc {
143433d6423SLionel Sambuc   ASSERTVMP(vmp);
144433d6423SLionel Sambuc   return(tll_islocked(&vmp->m_lock) || tll_haspendinglock(&vmp->m_lock));
145433d6423SLionel Sambuc }
146433d6423SLionel Sambuc 
147433d6423SLionel Sambuc /*===========================================================================*
148433d6423SLionel Sambuc  *                             lock_vmnt				     *
149433d6423SLionel Sambuc  *===========================================================================*/
lock_vmnt(struct vmnt * vmp,tll_access_t locktype)150433d6423SLionel Sambuc int lock_vmnt(struct vmnt *vmp, tll_access_t locktype)
151433d6423SLionel Sambuc {
152433d6423SLionel Sambuc   int r;
153433d6423SLionel Sambuc   tll_access_t initial_locktype;
154433d6423SLionel Sambuc 
155433d6423SLionel Sambuc   ASSERTVMP(vmp);
156433d6423SLionel Sambuc 
157433d6423SLionel Sambuc   initial_locktype = (locktype == VMNT_EXCL) ? VMNT_WRITE : locktype;
158433d6423SLionel Sambuc 
159433d6423SLionel Sambuc   if (vmp->m_fs_e == who_e) return(EDEADLK);
160433d6423SLionel Sambuc 
161433d6423SLionel Sambuc   r = tll_lock(&vmp->m_lock, initial_locktype);
162433d6423SLionel Sambuc 
163433d6423SLionel Sambuc   if (r == EBUSY) return(r);
164433d6423SLionel Sambuc 
165433d6423SLionel Sambuc   if (initial_locktype != locktype) {
166433d6423SLionel Sambuc 	upgrade_vmnt_lock(vmp);
167433d6423SLionel Sambuc   }
168433d6423SLionel Sambuc 
169433d6423SLionel Sambuc #if LOCK_DEBUG
170433d6423SLionel Sambuc   if (locktype == VMNT_READ)
171433d6423SLionel Sambuc 	fp->fp_vmnt_rdlocks++;
172433d6423SLionel Sambuc #endif
173433d6423SLionel Sambuc 
174433d6423SLionel Sambuc   return(OK);
175433d6423SLionel Sambuc }
176433d6423SLionel Sambuc 
177433d6423SLionel Sambuc /*===========================================================================*
178433d6423SLionel Sambuc  *                             vmnt_unmap_by_endpoint			     *
179433d6423SLionel Sambuc  *===========================================================================*/
vmnt_unmap_by_endpt(endpoint_t proc_e)180433d6423SLionel Sambuc void vmnt_unmap_by_endpt(endpoint_t proc_e)
181433d6423SLionel Sambuc {
182433d6423SLionel Sambuc   struct vmnt *vmp;
183433d6423SLionel Sambuc 
184433d6423SLionel Sambuc   if ((vmp = find_vmnt(proc_e)) != NULL) {
185433d6423SLionel Sambuc 	mark_vmnt_free(vmp);
186433d6423SLionel Sambuc 	fs_cancel(vmp);
187433d6423SLionel Sambuc 	invalidate_filp_by_endpt(proc_e);
188433d6423SLionel Sambuc 	if (vmp->m_mounted_on) {
189433d6423SLionel Sambuc 		/* Only put mount point when it was actually used as mount
190433d6423SLionel Sambuc 		 * point. That is, the mount was succesful. */
191433d6423SLionel Sambuc 		put_vnode(vmp->m_mounted_on);
192433d6423SLionel Sambuc 	}
193433d6423SLionel Sambuc   }
194433d6423SLionel Sambuc }
195433d6423SLionel Sambuc 
196433d6423SLionel Sambuc /*===========================================================================*
197433d6423SLionel Sambuc  *                             unlock_vmnt				     *
198433d6423SLionel Sambuc  *===========================================================================*/
unlock_vmnt(struct vmnt * vmp)199433d6423SLionel Sambuc void unlock_vmnt(struct vmnt *vmp)
200433d6423SLionel Sambuc {
201433d6423SLionel Sambuc   ASSERTVMP(vmp);
202433d6423SLionel Sambuc 
203433d6423SLionel Sambuc #if LOCK_DEBUG
204433d6423SLionel Sambuc   /* Decrease read-only lock counter when not locked as VMNT_WRITE or
205433d6423SLionel Sambuc    * VMNT_EXCL */
206433d6423SLionel Sambuc   if (!tll_locked_by_me(&vmp->m_lock))
207433d6423SLionel Sambuc 	fp->fp_vmnt_rdlocks--;
208433d6423SLionel Sambuc #endif
209433d6423SLionel Sambuc 
210433d6423SLionel Sambuc   tll_unlock(&vmp->m_lock);
211433d6423SLionel Sambuc 
212433d6423SLionel Sambuc #if LOCK_DEBUG
213433d6423SLionel Sambuc   assert(!tll_locked_by_me(&vmp->m_lock));
214433d6423SLionel Sambuc #endif
215433d6423SLionel Sambuc 
216433d6423SLionel Sambuc }
217433d6423SLionel Sambuc 
218433d6423SLionel Sambuc /*===========================================================================*
219433d6423SLionel Sambuc  *                             downgrade_vmnt_lock			     *
220433d6423SLionel Sambuc  *===========================================================================*/
downgrade_vmnt_lock(struct vmnt * vmp)221433d6423SLionel Sambuc void downgrade_vmnt_lock(struct vmnt *vmp)
222433d6423SLionel Sambuc {
223433d6423SLionel Sambuc   ASSERTVMP(vmp);
224433d6423SLionel Sambuc   tll_downgrade(&vmp->m_lock);
225433d6423SLionel Sambuc 
226433d6423SLionel Sambuc #if LOCK_DEBUG
227433d6423SLionel Sambuc   /* If we're no longer the owner of a lock, we downgraded to VMNT_READ */
228433d6423SLionel Sambuc   if (!tll_locked_by_me(&vmp->m_lock)) {
229433d6423SLionel Sambuc 	fp->fp_vmnt_rdlocks++;
230433d6423SLionel Sambuc   }
231433d6423SLionel Sambuc #endif
232433d6423SLionel Sambuc }
233433d6423SLionel Sambuc 
234433d6423SLionel Sambuc /*===========================================================================*
235433d6423SLionel Sambuc  *                             upgrade_vmnt_lock			     *
236433d6423SLionel Sambuc  *===========================================================================*/
upgrade_vmnt_lock(struct vmnt * vmp)237433d6423SLionel Sambuc void upgrade_vmnt_lock(struct vmnt *vmp)
238433d6423SLionel Sambuc {
239433d6423SLionel Sambuc   ASSERTVMP(vmp);
240433d6423SLionel Sambuc   tll_upgrade(&vmp->m_lock);
241433d6423SLionel Sambuc }
242433d6423SLionel Sambuc 
243433d6423SLionel Sambuc /*===========================================================================*
244433d6423SLionel Sambuc  *                             fetch_vmnt_paths				     *
245433d6423SLionel Sambuc  *===========================================================================*/
fetch_vmnt_paths(void)246433d6423SLionel Sambuc void fetch_vmnt_paths(void)
247433d6423SLionel Sambuc {
248433d6423SLionel Sambuc   struct vmnt *vmp;
249433d6423SLionel Sambuc   struct vnode *cur_wd;
250433d6423SLionel Sambuc   char orig_path[PATH_MAX];
251433d6423SLionel Sambuc 
252433d6423SLionel Sambuc   cur_wd = fp->fp_wd;
253433d6423SLionel Sambuc 
254433d6423SLionel Sambuc   for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
255433d6423SLionel Sambuc 	if (vmp->m_dev == NO_DEV)
256433d6423SLionel Sambuc 		continue;
257433d6423SLionel Sambuc 	if (vmp->m_fs_e == PFS_PROC_NR)
258433d6423SLionel Sambuc 		continue;
259433d6423SLionel Sambuc 
260433d6423SLionel Sambuc 	strlcpy(orig_path, vmp->m_mount_path, PATH_MAX);
261433d6423SLionel Sambuc 
262433d6423SLionel Sambuc 	/* Find canonical path */
263433d6423SLionel Sambuc 	if (canonical_path(vmp->m_mount_path, fp) != OK) {
264433d6423SLionel Sambuc 		/* We failed to find it (moved somewhere else?). Let's try
265433d6423SLionel Sambuc 		 * again by starting at the node on which we are mounted:
266433d6423SLionel Sambuc 		 * pretend that node is our working directory and look for the
267433d6423SLionel Sambuc 		 * canonical path of the relative path to the mount point
268433d6423SLionel Sambuc 		 * (which should be in our 'working directory').
269433d6423SLionel Sambuc 		 */
270433d6423SLionel Sambuc 		char *mp;
271433d6423SLionel Sambuc 		int len;
272433d6423SLionel Sambuc 
273433d6423SLionel Sambuc 		fp->fp_wd = vmp->m_mounted_on;	/* Change our working dir */
274433d6423SLionel Sambuc 
275433d6423SLionel Sambuc 		/* Isolate the mount point name of the full path */
276433d6423SLionel Sambuc 		len = strlen(vmp->m_mount_path);
277433d6423SLionel Sambuc 		if (vmp->m_mount_path[len - 1] == '/') {
278433d6423SLionel Sambuc 			vmp->m_mount_path[len - 1] = '\0';
279433d6423SLionel Sambuc 		}
280433d6423SLionel Sambuc 		mp = strrchr(vmp->m_mount_path, '/');
281433d6423SLionel Sambuc 		strlcpy(vmp->m_mount_path, mp+1, NAME_MAX+1);
282433d6423SLionel Sambuc 
283433d6423SLionel Sambuc 		if (canonical_path(vmp->m_mount_path, fp) != OK) {
284433d6423SLionel Sambuc 			/* Our second try failed too. Maybe an FS has crashed
285433d6423SLionel Sambuc 			 * and we're missing part of the tree. Revert path.
286433d6423SLionel Sambuc 			 */
287433d6423SLionel Sambuc 			strlcpy(vmp->m_mount_path, orig_path, PATH_MAX);
288433d6423SLionel Sambuc 		}
289433d6423SLionel Sambuc 		fp->fp_wd = cur_wd;		/* Revert working dir */
290433d6423SLionel Sambuc 	}
291433d6423SLionel Sambuc   }
292433d6423SLionel Sambuc }
293