1 /*- 2 * Copyright (c) 1990 Jan-Simon Pendry 3 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Jan-Simon Pendry at Imperial College, London. 9 * 10 * %sccs.include.redist.c% 11 * 12 * $Id: mntfs.c,v 5.2.2.1 1992/02/09 15:08:42 jsp beta $ 13 */ 14 15 #ifndef lint 16 static char sccsid[] = "@(#)mntfs.c 8.1 (Berkeley) 06/06/93"; 17 #endif /* not lint */ 18 19 20 #include "am.h" 21 22 extern qelem mfhead; 23 qelem mfhead = { &mfhead, &mfhead }; 24 25 int mntfs_allocated; 26 27 #ifdef notdef 28 /* 29 * This is the default attributes field which 30 * is copied into every new node to be created. 31 * The individual filesystem fs_init() routines 32 * patch the copy to represent the particular 33 * details for the relevant filesystem type 34 */ 35 static struct fattr gen_fattr = { 36 NFDIR, /* type */ 37 NFSMODE_DIR | 0555, /* mode */ 38 2, /* nlink */ 39 0, /* uid */ 40 0, /* gid */ 41 512, /* size */ 42 4096, /* blocksize */ 43 0, /* rdev */ 44 1, /* blocks */ 45 0, /* fsid */ 46 0, /* fileid */ 47 { 0, 0 }, /* atime */ 48 { 0, 0 }, /* mtime */ 49 { 0, 0 }, /* ctime */ 50 }; 51 #endif /* notdef */ 52 53 mntfs *dup_mntfs(mf) 54 mntfs *mf; 55 { 56 if (mf->mf_refc == 0) { 57 if (mf->mf_cid) 58 untimeout(mf->mf_cid); 59 mf->mf_cid = 0; 60 #ifdef notdef 61 mf->mf_error = -1; 62 mf->mf_flags &= ~MFF_ERROR; 63 #endif 64 } 65 mf->mf_refc++; 66 return mf; 67 } 68 69 static void init_mntfs P((mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)); 70 static void init_mntfs(mf, ops, mo, mp, info, auto_opts, mopts, remopts) 71 mntfs *mf; 72 am_ops *ops; 73 am_opts *mo; 74 char *mp; 75 char *info; 76 char *auto_opts; 77 char *mopts; 78 char *remopts; 79 { 80 mf->mf_ops = ops; 81 mf->mf_fo = mo; 82 mf->mf_mount = strdup(mp); 83 mf->mf_info = strdup(info); 84 mf->mf_auto = strdup(auto_opts); 85 mf->mf_mopts = strdup(mopts); 86 mf->mf_remopts = strdup(remopts); 87 mf->mf_refc = 1; 88 mf->mf_flags = 0; 89 mf->mf_error = -1; 90 mf->mf_cid = 0; 91 mf->mf_private = 0; 92 mf->mf_prfree = 0; 93 #ifdef notdef 94 mf->mf_attr.status = NFS_OK; 95 mf->mf_fattr = gen_fattr; 96 mf->mf_fattr.fsid = 42; 97 mf->mf_fattr.fileid = 0; 98 mf->mf_fattr.atime.seconds = clocktime(); 99 mf->mf_fattr.atime.useconds = 0; 100 mf->mf_fattr.mtime = mf->mf_fattr.ctime = mf->mf_fattr.atime; 101 #endif 102 103 if (ops->ffserver) 104 mf->mf_server = (*ops->ffserver)(mf); 105 else 106 mf->mf_server = 0; 107 } 108 109 static mntfs *alloc_mntfs P((am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)); 110 static mntfs *alloc_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts) 111 am_ops *ops; 112 am_opts *mo; 113 char *mp; 114 char *info; 115 char *auto_opts; 116 char *mopts; 117 char *remopts; 118 { 119 mntfs *mf = ALLOC(mntfs); 120 init_mntfs(mf, ops, mo, mp, info, auto_opts, mopts, remopts); 121 ins_que(&mf->mf_q, &mfhead); 122 mntfs_allocated++; 123 124 return mf; 125 } 126 127 mntfs *find_mntfs P((am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)); 128 mntfs *find_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts) 129 am_ops *ops; 130 am_opts *mo; 131 char *mp; 132 char *info; 133 char *auto_opts; 134 char *mopts; 135 char *remopts; 136 { 137 mntfs *mf; 138 139 #ifdef DEBUG 140 dlog("Locating mntfs reference to %s", mp); 141 #endif /* DEBUG */ 142 ITER(mf, mntfs, &mfhead) { 143 if (STREQ(mf->mf_mount, mp)) { 144 /* 145 * Handle cases where error ops are involved 146 */ 147 if (ops == &efs_ops) { 148 /* 149 * If the existing ops are not efs_ops 150 * then continue... 151 */ 152 if (mf->mf_ops != &efs_ops) 153 continue; 154 } else /* ops != &efs_ops */ { 155 /* 156 * If the existing ops are efs_ops 157 * then continue... 158 */ 159 if (mf->mf_ops == &efs_ops) 160 continue; 161 } 162 163 if ((mf->mf_flags & MFF_RESTART) && amd_state == Run) { 164 /* 165 * Restart a previously mounted filesystem. 166 */ 167 mntfs *mf2 = alloc_mntfs(&ifs_ops, mo, mp, info, auto_opts, mopts, remopts); 168 #ifdef DEBUG 169 dlog("Restarting filesystem %s", mf->mf_mount); 170 #endif /* DEBUG */ 171 /* 172 * Remember who we are restarting 173 */ 174 mf2->mf_private = (voidp) dup_mntfs(mf); 175 mf2->mf_prfree = free_mntfs; 176 return mf2; 177 } 178 mf->mf_fo = mo; 179 if (!(mf->mf_flags & (MFF_MOUNTED|MFF_MOUNTING|MFF_UNMOUNTING))) { 180 fserver *fs; 181 mf->mf_flags &= ~MFF_ERROR; 182 mf->mf_error = -1; 183 mf->mf_auto = strealloc(mf->mf_auto, auto_opts); 184 mf->mf_mopts = strealloc(mf->mf_mopts, mopts); 185 mf->mf_remopts = strealloc(mf->mf_remopts, remopts); 186 mf->mf_info = strealloc(mf->mf_info, info); 187 if (mf->mf_private && mf->mf_prfree) { 188 (*mf->mf_prfree)(mf->mf_private); 189 mf->mf_private = 0; 190 } 191 fs = ops->ffserver ? (*ops->ffserver)(mf) : (fserver *) 0; 192 if (mf->mf_server) 193 free_srvr(mf->mf_server); 194 mf->mf_server = fs; 195 } 196 return dup_mntfs(mf); 197 } 198 } 199 200 return alloc_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts); 201 } 202 203 mntfs *new_mntfs() 204 { 205 return alloc_mntfs(&efs_ops, (am_opts *) 0, "//nil//", ".", "", "", ""); 206 } 207 208 static void uninit_mntfs(mf, rmd) 209 mntfs *mf; 210 int rmd; 211 { 212 if (mf->mf_mount) free((voidp) mf->mf_mount); 213 if (mf->mf_auto) free((voidp) mf->mf_auto); 214 if (mf->mf_mopts) free((voidp) mf->mf_mopts); 215 if (mf->mf_remopts) free((voidp) mf->mf_remopts); 216 if (mf->mf_info) free((voidp) mf->mf_info); 217 if (mf->mf_private && mf->mf_prfree) 218 (*mf->mf_prfree)(mf->mf_private); 219 /* 220 * Clean up any directories that were made 221 */ 222 if (rmd && (mf->mf_flags & MFF_MKMNT)) 223 rmdirs(mf->mf_mount); 224 225 /* 226 * Clean up the file server 227 */ 228 if (mf->mf_server) 229 free_srvr(mf->mf_server); 230 231 /* 232 * Don't do a callback on this mount 233 */ 234 if (mf->mf_cid) { 235 untimeout(mf->mf_cid); 236 mf->mf_cid = 0; 237 } 238 } 239 240 static void discard_mntfs(mf) 241 mntfs *mf; 242 { 243 rem_que(&mf->mf_q); 244 /* 245 * Free memory 246 */ 247 uninit_mntfs(mf, TRUE); 248 free((voidp) mf); 249 250 --mntfs_allocated; 251 } 252 253 void flush_mntfs() 254 { 255 mntfs *mf; 256 257 mf = FIRST(mntfs, &mfhead); 258 while (mf != HEAD(mntfs, &mfhead)) { 259 mntfs *mf2 = mf; 260 mf = NEXT(mntfs, mf); 261 if (mf2->mf_refc == 0 && mf2->mf_cid) 262 discard_mntfs(mf2); 263 } 264 } 265 266 void free_mntfs(mf) 267 mntfs *mf; 268 { 269 if (--mf->mf_refc == 0) { 270 if (mf->mf_flags & MFF_MOUNTED) { 271 int quoted; 272 mf->mf_flags &= ~MFF_MOUNTED; 273 274 /* 275 * Record for posterity 276 */ 277 quoted = strchr(mf->mf_info, ' ') != 0; /* cheap */ 278 plog(XLOG_INFO, "%s%s%s %sed fstype %s from %s", 279 quoted ? "\"" : "", 280 mf->mf_info, 281 quoted ? "\"" : "", 282 mf->mf_error ? "discard" : "unmount", 283 mf->mf_ops->fs_type, mf->mf_mount); 284 } 285 286 if (mf->mf_ops->fs_flags & FS_DISCARD) { 287 #ifdef DEBUG 288 dlog("Immediately discarding mntfs for %s", mf->mf_mount); 289 #endif /* DEBUG */ 290 discard_mntfs(mf); 291 } else { 292 #ifdef DEBUG 293 if (mf->mf_flags & MFF_RESTART) { 294 dlog("Discarding remount hook for %s", mf->mf_mount); 295 } else { 296 dlog("Discarding last mntfs reference to %s fstype %s", 297 mf->mf_mount, mf->mf_ops->fs_type); 298 } 299 if (mf->mf_flags & (MFF_MOUNTED|MFF_MOUNTING|MFF_UNMOUNTING)) 300 dlog("mntfs reference for %s still active", mf->mf_mount); 301 #endif /* DEBUG */ 302 mf->mf_cid = timeout(ALLOWED_MOUNT_TIME, discard_mntfs, (voidp) mf); 303 } 304 } 305 } 306 307 mntfs *realloc_mntfs P((mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)); 308 mntfs *realloc_mntfs(mf, ops, mo, mp, info, auto_opts, mopts, remopts) 309 mntfs *mf; 310 am_ops *ops; 311 am_opts *mo; 312 char *mp; 313 char *info; 314 char *auto_opts; 315 char *mopts; 316 char *remopts; 317 { 318 mntfs *mf2; 319 if (mf->mf_refc == 1 && mf->mf_ops == &ifs_ops && STREQ(mf->mf_mount, mp)) { 320 /* 321 * If we are inheriting then just return 322 * the same node... 323 */ 324 return mf; 325 } 326 327 /* 328 * Re-use the existing mntfs if it is mounted. 329 * This traps a race in nfsx. 330 */ 331 if (mf->mf_ops != &efs_ops && 332 (mf->mf_flags & MFF_MOUNTED) && 333 !FSRV_ISDOWN(mf->mf_server)) { 334 mf->mf_fo = mo; 335 return mf; 336 } 337 338 mf2 = find_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts); 339 free_mntfs(mf); 340 return mf2; 341 } 342