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 *===========================================================================*/
45 check_vmnt_locks(void)
50 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; vmp
++)
51 if (is_vmnt_locked(vmp
)) {
53 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
);
56 if (count
) panic("%d locked vmnts\n", count
);
58 printf("check_vmnt_locks OK\n");
62 /*===========================================================================*
64 *===========================================================================*/
65 void mark_vmnt_free(struct vmnt
*vmp
)
73 /*===========================================================================*
75 *===========================================================================*/
76 static void clear_vmnt(struct vmnt
*vmp
)
78 /* Reset vmp to initial parameters */
84 vmp
->m_mounted_on
= NULL
;
85 vmp
->m_root_node
= NULL
;
86 vmp
->m_label
[0] = '\0';
87 vmp
->m_comm
.c_max_reqs
= 1;
88 vmp
->m_comm
.c_cur_reqs
= 0;
89 vmp
->m_comm
.c_req_queue
= NULL
;
92 /*===========================================================================*
94 *===========================================================================*/
95 struct vmnt
*get_free_vmnt(void)
99 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; ++vmp
) {
100 if (vmp
->m_dev
== NO_DEV
) {
109 /*===========================================================================*
111 *===========================================================================*/
112 struct vmnt
*find_vmnt(endpoint_t fs_e
)
114 /* Find the vmnt belonging to an FS with endpoint 'fs_e' iff it's in use */
117 for (vp
= &vmnt
[0]; vp
< &vmnt
[NR_MNTS
]; ++vp
)
118 if (vp
->m_fs_e
== fs_e
&& vp
->m_dev
!= NO_DEV
)
124 /*===========================================================================*
126 *===========================================================================*/
127 void init_vmnts(void)
129 /* Initialize vmnt table */
132 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; vmp
++) {
134 tll_init(&vmp
->m_lock
);
138 /*===========================================================================*
140 *===========================================================================*/
141 static int is_vmnt_locked(struct vmnt
*vmp
)
144 return(tll_islocked(&vmp
->m_lock
) || tll_haspendinglock(&vmp
->m_lock
));
147 /*===========================================================================*
149 *===========================================================================*/
150 int lock_vmnt(struct vmnt
*vmp
, tll_access_t locktype
)
153 tll_access_t initial_locktype
;
157 initial_locktype
= (locktype
== VMNT_EXCL
) ? VMNT_WRITE
: locktype
;
159 if (vmp
->m_fs_e
== who_e
) return(EDEADLK
);
161 r
= tll_lock(&vmp
->m_lock
, initial_locktype
);
163 if (r
== EBUSY
) return(r
);
165 if (initial_locktype
!= locktype
) {
166 upgrade_vmnt_lock(vmp
);
170 if (locktype
== VMNT_READ
)
171 fp
->fp_vmnt_rdlocks
++;
177 /*===========================================================================*
178 * vmnt_unmap_by_endpoint *
179 *===========================================================================*/
180 void vmnt_unmap_by_endpt(endpoint_t proc_e
)
184 if ((vmp
= find_vmnt(proc_e
)) != NULL
) {
187 invalidate_filp_by_endpt(proc_e
);
188 if (vmp
->m_mounted_on
) {
189 /* Only put mount point when it was actually used as mount
190 * point. That is, the mount was succesful. */
191 put_vnode(vmp
->m_mounted_on
);
196 /*===========================================================================*
198 *===========================================================================*/
199 void unlock_vmnt(struct vmnt
*vmp
)
204 /* Decrease read-only lock counter when not locked as VMNT_WRITE or
206 if (!tll_locked_by_me(&vmp
->m_lock
))
207 fp
->fp_vmnt_rdlocks
--;
210 tll_unlock(&vmp
->m_lock
);
213 assert(!tll_locked_by_me(&vmp
->m_lock
));
218 /*===========================================================================*
219 * downgrade_vmnt_lock *
220 *===========================================================================*/
221 void downgrade_vmnt_lock(struct vmnt
*vmp
)
224 tll_downgrade(&vmp
->m_lock
);
227 /* If we're no longer the owner of a lock, we downgraded to VMNT_READ */
228 if (!tll_locked_by_me(&vmp
->m_lock
)) {
229 fp
->fp_vmnt_rdlocks
++;
234 /*===========================================================================*
235 * upgrade_vmnt_lock *
236 *===========================================================================*/
237 void upgrade_vmnt_lock(struct vmnt
*vmp
)
240 tll_upgrade(&vmp
->m_lock
);
243 /*===========================================================================*
245 *===========================================================================*/
246 void fetch_vmnt_paths(void)
249 struct vnode
*cur_wd
;
250 char orig_path
[PATH_MAX
];
254 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; vmp
++) {
255 if (vmp
->m_dev
== NO_DEV
)
257 if (vmp
->m_fs_e
== PFS_PROC_NR
)
260 strlcpy(orig_path
, vmp
->m_mount_path
, PATH_MAX
);
262 /* Find canonical path */
263 if (canonical_path(vmp
->m_mount_path
, fp
) != OK
) {
264 /* We failed to find it (moved somewhere else?). Let's try
265 * again by starting at the node on which we are mounted:
266 * pretend that node is our working directory and look for the
267 * canonical path of the relative path to the mount point
268 * (which should be in our 'working directory').
273 fp
->fp_wd
= vmp
->m_mounted_on
; /* Change our working dir */
275 /* Isolate the mount point name of the full path */
276 len
= strlen(vmp
->m_mount_path
);
277 if (vmp
->m_mount_path
[len
- 1] == '/') {
278 vmp
->m_mount_path
[len
- 1] = '\0';
280 mp
= strrchr(vmp
->m_mount_path
, '/');
281 strlcpy(vmp
->m_mount_path
, mp
+1, NAME_MAX
+1);
283 if (canonical_path(vmp
->m_mount_path
, fp
) != OK
) {
284 /* Our second try failed too. Maybe an FS has crashed
285 * and we're missing part of the tree. Revert path.
287 strlcpy(vmp
->m_mount_path
, orig_path
, PATH_MAX
);
289 fp
->fp_wd
= cur_wd
; /* Revert working dir */