1 /* Virtual mount table related routines.
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"); }
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 */
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
);
41 /*===========================================================================*
43 *===========================================================================*/
44 void check_vmnt_locks()
49 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; vmp
++)
50 if (is_vmnt_locked(vmp
)) {
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
);
57 printf("check_vmnt_locks OK\n");
61 /*===========================================================================*
63 *===========================================================================*/
64 void mark_vmnt_free(struct vmnt
*vmp
)
72 /*===========================================================================*
74 *===========================================================================*/
75 static void clear_vmnt(struct vmnt
*vmp
)
77 /* Reset vmp to initial parameters */
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 /*===========================================================================*
93 *===========================================================================*/
94 struct vmnt
*get_free_vmnt(void)
98 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; ++vmp
) {
99 if (vmp
->m_dev
== NO_DEV
) {
108 /*===========================================================================*
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 */
116 for (vp
= &vmnt
[0]; vp
< &vmnt
[NR_MNTS
]; ++vp
)
117 if (vp
->m_fs_e
== fs_e
&& vp
->m_dev
!= NO_DEV
)
123 /*===========================================================================*
125 *===========================================================================*/
126 void init_vmnts(void)
128 /* Initialize vmnt table */
131 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; vmp
++) {
133 tll_init(&vmp
->m_lock
);
137 /*===========================================================================*
139 *===========================================================================*/
140 static int is_vmnt_locked(struct vmnt
*vmp
)
143 return(tll_islocked(&vmp
->m_lock
) || tll_haspendinglock(&vmp
->m_lock
));
146 /*===========================================================================*
148 *===========================================================================*/
149 int lock_vmnt(struct vmnt
*vmp
, tll_access_t locktype
)
152 tll_access_t initial_locktype
;
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
);
169 if (locktype
== VMNT_READ
)
170 fp
->fp_vmnt_rdlocks
++;
176 /*===========================================================================*
177 * vmnt_unmap_by_endpoint *
178 *===========================================================================*/
179 void vmnt_unmap_by_endpt(endpoint_t proc_e
)
183 if ((vmp
= find_vmnt(proc_e
)) != NULL
) {
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 /*===========================================================================*
197 *===========================================================================*/
198 void unlock_vmnt(struct vmnt
*vmp
)
203 /* Decrease read-only lock counter when not locked as VMNT_WRITE or
205 if (!tll_locked_by_me(&vmp
->m_lock
))
206 fp
->fp_vmnt_rdlocks
--;
209 tll_unlock(&vmp
->m_lock
);
212 assert(!tll_locked_by_me(&vmp
->m_lock
));
217 /*===========================================================================*
218 * downgrade_vmnt_lock *
219 *===========================================================================*/
220 void downgrade_vmnt_lock(struct vmnt
*vmp
)
223 tll_downgrade(&vmp
->m_lock
);
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
++;
233 /*===========================================================================*
234 * upgrade_vmnt_lock *
235 *===========================================================================*/
236 void upgrade_vmnt_lock(struct vmnt
*vmp
)
239 tll_upgrade(&vmp
->m_lock
);
242 /*===========================================================================*
244 *===========================================================================*/
245 void fetch_vmnt_paths(void)
248 struct vnode
*cur_wd
;
249 char orig_path
[PATH_MAX
];
253 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; vmp
++) {
254 if (vmp
->m_dev
== NO_DEV
)
256 if (vmp
->m_fs_e
== PFS_PROC_NR
)
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').
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 */