1 /* Virtual mount table related routines.
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"); }
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 */
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
);
43 /*===========================================================================*
45 *===========================================================================*/
46 void check_vmnt_locks()
51 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; vmp
++)
52 if (is_vmnt_locked(vmp
)) {
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
);
59 printf("check_vmnt_locks OK\n");
63 /*===========================================================================*
65 *===========================================================================*/
66 void mark_vmnt_free(struct vmnt
*vmp
)
74 /*===========================================================================*
76 *===========================================================================*/
77 static void clear_vmnt(struct vmnt
*vmp
)
79 /* Reset vmp to initial parameters */
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 /*===========================================================================*
95 *===========================================================================*/
96 struct vmnt
*get_free_vmnt(void)
100 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; ++vmp
) {
101 if (vmp
->m_dev
== NO_DEV
) {
110 /*===========================================================================*
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 */
118 for (vp
= &vmnt
[0]; vp
< &vmnt
[NR_MNTS
]; ++vp
)
119 if (vp
->m_fs_e
== fs_e
&& vp
->m_dev
!= NO_DEV
)
125 /*===========================================================================*
127 *===========================================================================*/
128 void init_vmnts(void)
130 /* Initialize vmnt table */
133 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; vmp
++) {
135 tll_init(&vmp
->m_lock
);
139 /*===========================================================================*
141 *===========================================================================*/
142 static int is_vmnt_locked(struct vmnt
*vmp
)
145 return(tll_islocked(&vmp
->m_lock
) || tll_haspendinglock(&vmp
->m_lock
));
148 /*===========================================================================*
150 *===========================================================================*/
151 int lock_vmnt(struct vmnt
*vmp
, tll_access_t locktype
)
154 tll_access_t initial_locktype
;
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 upgrade_vmnt_lock(vmp
);
171 if (locktype
== VMNT_READ
)
172 fp
->fp_vmnt_rdlocks
++;
178 /*===========================================================================*
179 * vmnt_unmap_by_endpoint *
180 *===========================================================================*/
181 void vmnt_unmap_by_endpt(endpoint_t proc_e
)
185 if ((vmp
= find_vmnt(proc_e
)) != NULL
) {
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 /*===========================================================================*
199 *===========================================================================*/
200 void unlock_vmnt(struct vmnt
*vmp
)
205 /* Decrease read-only lock counter when not locked as VMNT_WRITE or
207 if (!tll_locked_by_me(&vmp
->m_lock
))
208 fp
->fp_vmnt_rdlocks
--;
211 tll_unlock(&vmp
->m_lock
);
214 assert(!tll_locked_by_me(&vmp
->m_lock
));
219 /*===========================================================================*
220 * downgrade_vmnt_lock *
221 *===========================================================================*/
222 void downgrade_vmnt_lock(struct vmnt
*vmp
)
225 tll_downgrade(&vmp
->m_lock
);
228 /* If we're no longer the owner of a lock, we downgraded to VMNT_READ */
229 if (!tll_locked_by_me(&vmp
->m_lock
)) {
230 fp
->fp_vmnt_rdlocks
++;
235 /*===========================================================================*
236 * upgrade_vmnt_lock *
237 *===========================================================================*/
238 void upgrade_vmnt_lock(struct vmnt
*vmp
)
241 tll_upgrade(&vmp
->m_lock
);
244 /*===========================================================================*
246 *===========================================================================*/
247 void fetch_vmnt_paths(void)
250 struct vnode
*cur_wd
;
251 char orig_path
[PATH_MAX
];
255 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; vmp
++) {
256 if (vmp
->m_dev
== NO_DEV
)
258 if (vmp
->m_fs_e
== PFS_PROC_NR
)
261 strlcpy(orig_path
, vmp
->m_mount_path
, PATH_MAX
);
263 /* Find canonical path */
264 if (canonical_path(vmp
->m_mount_path
, fp
) != OK
) {
265 /* We failed to find it (moved somewhere else?). Let's try
266 * again by starting at the node on which we are mounted:
267 * pretend that node is our working directory and look for the
268 * canonical path of the relative path to the mount point
269 * (which should be in our 'working directory').
274 fp
->fp_wd
= vmp
->m_mounted_on
; /* Change our working dir */
276 /* Isolate the mount point name of the full path */
277 len
= strlen(vmp
->m_mount_path
);
278 if (vmp
->m_mount_path
[len
- 1] == '/') {
279 vmp
->m_mount_path
[len
- 1] = '\0';
281 mp
= strrchr(vmp
->m_mount_path
, '/');
282 strlcpy(vmp
->m_mount_path
, mp
+1, NAME_MAX
+1);
284 if (canonical_path(vmp
->m_mount_path
, fp
) != OK
) {
285 /* Our second try failed too. Maybe an FS has crashed
286 * and we're missing part of the tree. Revert path.
288 strlcpy(vmp
->m_mount_path
, orig_path
, PATH_MAX
);
290 fp
->fp_wd
= cur_wd
; /* Revert working dir */