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 5.3 (Berkeley) 05/12/91 13 * 14 * $Id: mntfs.c,v 5.2.1.7 91/05/07 22:18:11 jsp Alpha $ 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 int init_mntfs P((mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts)); 68 static int init_mntfs(mf, ops, mo, mp, info, auto_opts, mopts) 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 { 77 mf->mf_ops = ops; 78 mf->mf_fo = mo; 79 mf->mf_mount = strdup(mp); 80 mf->mf_info = strdup(info); 81 mf->mf_auto = strdup(auto_opts); 82 mf->mf_mopts = strdup(mopts); 83 mf->mf_refc = 1; 84 mf->mf_flags = 0; 85 mf->mf_error = -1; 86 mf->mf_cid = 0; 87 mf->mf_private = 0; 88 mf->mf_prfree = 0; 89 #ifdef notdef 90 mf->mf_attr.status = NFS_OK; 91 mf->mf_fattr = gen_fattr; 92 mf->mf_fattr.fsid = 42; 93 mf->mf_fattr.fileid = 0; 94 mf->mf_fattr.atime.seconds = clocktime(); 95 mf->mf_fattr.atime.useconds = 0; 96 mf->mf_fattr.mtime = mf->mf_fattr.ctime = mf->mf_fattr.atime; 97 #endif 98 99 if (ops->ffserver) 100 mf->mf_server = (*ops->ffserver)(mf); 101 else 102 mf->mf_server = 0; 103 } 104 105 static mntfs *alloc_mntfs P((am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts)); 106 static mntfs *alloc_mntfs(ops, mo, mp, info, auto_opts, mopts) 107 am_ops *ops; 108 am_opts *mo; 109 char *mp; 110 char *info; 111 char *auto_opts; 112 char *mopts; 113 { 114 mntfs *mf = ALLOC(mntfs); 115 init_mntfs(mf, ops, mo, mp, info, auto_opts, mopts); 116 ins_que(&mf->mf_q, &mfhead); 117 mntfs_allocated++; 118 119 return mf; 120 } 121 122 mntfs *find_mntfs P((am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts)); 123 mntfs *find_mntfs(ops, mo, mp, info, auto_opts, mopts) 124 am_ops *ops; 125 am_opts *mo; 126 char *mp; 127 char *info; 128 char *auto_opts; 129 char *mopts; 130 { 131 mntfs *mf; 132 133 #ifdef DEBUG 134 dlog("Locating mntfs reference to %s", mp); 135 #endif /* DEBUG */ 136 ITER(mf, mntfs, &mfhead) { 137 if (STREQ(mf->mf_mount, mp)) { 138 /* 139 * Handle cases where error ops are involved 140 */ 141 if (ops == &efs_ops) { 142 /* 143 * If the existing ops are not efs_ops 144 * then continue... 145 */ 146 if (mf->mf_ops != &efs_ops) 147 continue; 148 } else /* ops != &efs_ops */ { 149 /* 150 * If the existing ops are efs_ops 151 * then continue... 152 */ 153 if (mf->mf_ops == &efs_ops) 154 continue; 155 } 156 157 if ((mf->mf_flags & MFF_RESTART) && amd_state == Run) { 158 /* 159 * Restart a previously mounted filesystem. 160 */ 161 mntfs *mf2 = alloc_mntfs(&ifs_ops, mo, mp, info, auto_opts, mopts); 162 #ifdef DEBUG 163 dlog("Restarting filesystem %s", mf->mf_mount); 164 #endif /* DEBUG */ 165 /* 166 * Remember who we are restarting 167 */ 168 mf2->mf_private = (voidp) dup_mntfs(mf); 169 mf2->mf_prfree = free_mntfs; 170 return mf2; 171 } 172 mf->mf_fo = mo; 173 if (!(mf->mf_flags & (MFF_MOUNTED|MFF_MOUNTING|MFF_UNMOUNTING))) { 174 fserver *fs; 175 mf->mf_flags &= ~MFF_ERROR; 176 mf->mf_error = -1; 177 mf->mf_auto = strealloc(mf->mf_auto, auto_opts); 178 mf->mf_mopts = strealloc(mf->mf_mopts, mopts); 179 mf->mf_info = strealloc(mf->mf_info, info); 180 if (mf->mf_private && mf->mf_prfree) { 181 (*mf->mf_prfree)(mf->mf_private); 182 mf->mf_private = 0; 183 } 184 fs = ops->ffserver ? (*ops->ffserver)(mf) : (fserver *) 0; 185 if (mf->mf_server) 186 free_srvr(mf->mf_server); 187 mf->mf_server = fs; 188 } 189 return dup_mntfs(mf); 190 } 191 } 192 193 return alloc_mntfs(ops, mo, mp, info, auto_opts, mopts); 194 } 195 196 mntfs *new_mntfs() 197 { 198 return alloc_mntfs(&efs_ops, (am_opts *) 0, "//nil//", ".", "", ""); 199 } 200 201 static void uninit_mntfs(mf, rmd) 202 mntfs *mf; 203 int rmd; 204 { 205 if (mf->mf_mount) free((voidp) mf->mf_mount); 206 if (mf->mf_auto) free((voidp) mf->mf_auto); 207 if (mf->mf_mopts) free((voidp) mf->mf_mopts); 208 if (mf->mf_info) free((voidp) mf->mf_info); 209 if (mf->mf_private && mf->mf_prfree) 210 (*mf->mf_prfree)(mf->mf_private); 211 /* 212 * Clean up any directories that were made 213 */ 214 if (rmd && (mf->mf_flags & MFF_MKMNT)) 215 rmdirs(mf->mf_mount); 216 217 /* 218 * Clean up the file server 219 */ 220 if (mf->mf_server) 221 free_srvr(mf->mf_server); 222 223 /* 224 * Don't do a callback on this mount 225 */ 226 if (mf->mf_cid) { 227 untimeout(mf->mf_cid); 228 mf->mf_cid = 0; 229 } 230 } 231 232 static void discard_mntfs(mf) 233 mntfs *mf; 234 { 235 rem_que(&mf->mf_q); 236 /* 237 * Free memory 238 */ 239 uninit_mntfs(mf, TRUE); 240 free((voidp) mf); 241 242 --mntfs_allocated; 243 } 244 245 void flush_mntfs() 246 { 247 mntfs *mf; 248 249 mf = FIRST(mntfs, &mfhead); 250 while (mf != HEAD(mntfs, &mfhead)) { 251 mntfs *mf2 = mf; 252 mf = NEXT(mntfs, mf); 253 if (mf2->mf_refc == 0 && mf2->mf_cid) 254 discard_mntfs(mf2); 255 } 256 } 257 258 void free_mntfs(mf) 259 mntfs *mf; 260 { 261 if (--mf->mf_refc == 0) { 262 if (mf->mf_flags & MFF_MOUNTED) { 263 int quoted; 264 mf->mf_flags &= ~MFF_MOUNTED; 265 266 /* 267 * Record for posterity 268 */ 269 quoted = strchr(mf->mf_info, ' ') != 0; /* cheap */ 270 plog(XLOG_INFO, "%s%s%s %sed fstype %s from %s", 271 quoted ? "\"" : "", 272 mf->mf_info, 273 quoted ? "\"" : "", 274 mf->mf_error ? "discard" : "unmount", 275 mf->mf_ops->fs_type, mf->mf_mount); 276 } 277 278 if (mf->mf_ops->fs_flags & FS_DISCARD) { 279 #ifdef DEBUG 280 dlog("Immediately discarding mntfs for %s", mf->mf_mount); 281 #endif /* DEBUG */ 282 discard_mntfs(mf); 283 } else { 284 #ifdef DEBUG 285 if (mf->mf_flags & MFF_RESTART) { 286 dlog("Discarding remount hook for %s", mf->mf_mount); 287 } else { 288 dlog("Discarding last mntfs reference to %s fstype %s", 289 mf->mf_mount, mf->mf_ops->fs_type); 290 } 291 if (mf->mf_flags & (MFF_MOUNTED|MFF_MOUNTING|MFF_UNMOUNTING)) 292 dlog("mntfs reference for %s still active", mf->mf_mount); 293 #endif /* DEBUG */ 294 mf->mf_cid = timeout(ALLOWED_MOUNT_TIME, discard_mntfs, (voidp) mf); 295 } 296 } 297 } 298 299 mntfs *realloc_mntfs P((mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts)); 300 mntfs *realloc_mntfs(mf, ops, mo, mp, info, auto_opts, mopts) 301 mntfs *mf; 302 am_ops *ops; 303 am_opts *mo; 304 char *mp; 305 char *info; 306 char *auto_opts; 307 char *mopts; 308 { 309 mntfs *mf2; 310 if (mf->mf_refc == 1 && mf->mf_ops == &ifs_ops && STREQ(mf->mf_mount, mp)) { 311 /* 312 * If we are inheriting then just return 313 * the same node... 314 */ 315 return mf; 316 } 317 318 /* 319 * Re-use the existing mntfs if it is mounted. 320 * This traps a race in nfsx. 321 */ 322 if (mf->mf_ops != &efs_ops && 323 (mf->mf_flags & MFF_MOUNTED) && 324 !FSRV_ISDOWN(mf->mf_server)) { 325 mf->mf_fo = mo; 326 return mf; 327 } 328 329 mf2 = find_mntfs(ops, mo, mp, info, auto_opts, mopts); 330 free_mntfs(mf); 331 return mf2; 332 } 333