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