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