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