📄 afs_ops.c
字号:
* completes. */static void afs_cont P((int rc, int term, voidp closure));static void afs_cont(rc, term, closure)int rc;int term;voidp closure;{ struct continuation *cp = (struct continuation *) closure; mntfs *mf = cp->mp->am_mnt; /* * Definitely not trying to mount at the moment */ mf->mf_flags &= ~MFF_MOUNTING; /* * While we are mounting - try to avoid race conditions */ new_ttl(cp->mp); /* * Wakeup anything waiting for this mount */ wakeup((voidp) mf); /* * Check for termination signal or exit status... */ if (rc || term) { am_node *xmp; if (term) { /* * Not sure what to do for an error code. */ mf->mf_error = EIO; /* XXX ? */ mf->mf_flags |= MFF_ERROR; plog(XLOG_ERROR, "mount for %s got signal %d", cp->mp->am_path, term); } else { /* * Check for exit status... */ mf->mf_error = rc; mf->mf_flags |= MFF_ERROR; errno = rc; /* XXX */ plog(XLOG_ERROR, "%s: mount (afs_cont): %m", cp->mp->am_path); } /* * If we get here then that attempt didn't work, so * move the info vector pointer along by one and * call the background mount routine again */ amd_stats.d_merr++; cp->ivec++; xmp = cp->mp; (void) afs_bgmount(cp, 0); assign_error_mntfs(xmp); } else { /* * The mount worked. */ am_mounted(cp->mp); free_continuation(cp); } reschedule_timeout_mp();}/* * Retry a mount *//*ARGSUSED*/static void afs_retry P((int rc, int term, voidp closure));static void afs_retry(rc, term, closure)int rc;int term;voidp closure;{ struct continuation *cp = (struct continuation *) closure; int error = 0;#ifdef DEBUG dlog("Commencing retry for mount of %s", cp->mp->am_path);#endif /* DEBUG */ new_ttl(cp->mp); if ((cp->start + ALLOWED_MOUNT_TIME) < clocktime()) { /* * The entire mount has timed out. * Set the error code and skip past * all the info vectors so that * afs_bgmount will not have any more * ways to try the mount, so causing * an error. */ plog(XLOG_INFO, "mount of \"%s\" has timed out", cp->mp->am_path); error = ETIMEDOUT; while (*cp->ivec) cp->ivec++; } if (error || !IN_PROGRESS(cp)) { (void) afs_bgmount(cp, error); } reschedule_timeout_mp();}/* * Try to mount a file system. Can be called * directly or in a sub-process by run_task */static int try_mount P((voidp mvp));static int try_mount(mvp)voidp mvp;{ /* * Mount it! */ int error; am_node *mp = (am_node *) mvp; mntfs *mf = mp->am_mnt; /* * If the directory is not yet made and * it needs to be made, then make it! * This may be run in a backgroun process * in which case the flag setting won't be * noticed later - but it is set anyway * just after run_task is called. It * should probably go away totally... */ if (!(mf->mf_flags & MFF_MKMNT) && mf->mf_ops->fs_flags & FS_MKMNT) { error = mkdirs(mf->mf_mount, 0555); if (!error) mf->mf_flags |= MFF_MKMNT; } error = mount_node(mp);#ifdef DEBUG if (error > 0) { errno = error; dlog("afs call to mount_node failed: %m"); }#endif /* DEBUG */ return error;}/* * Pick a file system to try mounting and * do that in the background if necessary *For each location: if it is new -defaults then extract and process continue; fi if it is a cut then if a location has been tried then break; fi continue; fi parse mount location discard previous mount location if required find matching mounted filesystem if not applicable then this_error = No such file or directory continue fi if the filesystem failed to be mounted then this_error = error from filesystem elif the filesystem is mounting or unmounting then this_error = -1 elif the fileserver is down then this_error = -1 elif the filesystem is already mounted this_error = 0 break fi if no error on this mount then this_error = initialise mount point fi if no error on this mount and mount is delayed then this_error = -1 fi if this_error < 0 then retry = true fi if no error on this mount then make mount point if required fi if no error on this mount then if mount in background then run mount in background return -1 else this_error = mount in foreground fi fi if an error occured on this mount then update stats save error in mount point fiendfor */static int afs_bgmount P((struct continuation *cp, int mpe));static int afs_bgmount(cp, mpe)struct continuation *cp;int mpe;{ mntfs *mf = cp->mp->am_mnt; /* Current mntfs */ mntfs *mf_retry = 0; /* First mntfs which needed retrying */ int this_error = -1; /* Per-mount error */ int hard_error = -1; int mp_error = mpe; /* * Try to mount each location. * At the end: * hard_error == 0 indicates something was mounted. * hard_error > 0 indicates everything failed with a hard error * hard_error < 0 indicates nothing could be mounted now */ for (; this_error && *cp->ivec; cp->ivec++) { am_ops *p; am_node *mp = cp->mp; char *link_dir; int dont_retry; if (hard_error < 0) hard_error = this_error; this_error = -1; if (**cp->ivec == '-') { /* * Pick up new defaults */ if (cp->auto_opts && *cp->auto_opts) cp->def_opts = str3cat(cp->def_opts, cp->auto_opts, ";", *cp->ivec+1); else cp->def_opts = strealloc(cp->def_opts, *cp->ivec+1);#ifdef DEBUG dlog("Setting def_opts to \"%s\"", cp->def_opts);#endif /* DEBUG */ continue; } /* * If a mount has been attempted, and we find * a cut then don't try any more locations. */ if (strcmp(*cp->ivec, "/") == 0 || strcmp(*cp->ivec, "||") == 0) { if (cp->tried) {#ifdef DEBUG dlog("Cut: not trying any more locations for %s", mp->am_path);#endif /* DEBUG */ break; } continue; }#ifdef SUNOS4_COMPAT#ifdef nomore /* * By default, you only get this bit on SunOS4. * If you want this anyway, then define SUNOS4_COMPAT * in the relevant "os-blah.h" file. * * We make the observation that if the local key line contains * no '=' signs then either it is sick, or it is a SunOS4-style * "host:fs[:link]" line. In the latter case the am_opts field * is also assumed to be in old-style, so you can't mix & match. * You can use ${} expansions for the fs and link bits though... * * Actually, this doesn't really cover all the possibilities for * the latest SunOS automounter and it is debatable whether there * is any point bothering. */ if (strchr(*cp->ivec, '=') == 0) p = sunos4_match(&cp->fs_opts, *cp->ivec, cp->def_opts, mp->am_path, cp->key, mp->am_parent->am_mnt->mf_info); else#endif#endif /* SUNOS4_COMPAT */ p = ops_match(&cp->fs_opts, *cp->ivec, cp->def_opts, mp->am_path, cp->key, mp->am_parent->am_mnt->mf_info); /* * Find a mounted filesystem for this node. */ mp->am_mnt = mf = realloc_mntfs(mf, p, &cp->fs_opts, cp->fs_opts.opt_fs, cp->fs_opts.fs_mtab, cp->auto_opts, cp->fs_opts.opt_opts, cp->fs_opts.opt_remopts); p = mf->mf_ops;#ifdef DEBUG dlog("Got a hit with %s", p->fs_type);#endif /* DEBUG */ /* * Note whether this is a real mount attempt */ if (p == &efs_ops) { plog(XLOG_MAP, "Map entry %s for %s failed to match", *cp->ivec, mp->am_path); if (this_error <= 0) this_error = ENOENT; continue; } else { if (cp->fs_opts.fs_mtab) { plog(XLOG_MAP, "Trying mount of %s on %s fstype %s", cp->fs_opts.fs_mtab, mp->am_path, p->fs_type); } cp->tried = TRUE; } this_error = 0; dont_retry = FALSE; if (mp->am_link) { free(mp->am_link); mp->am_link = 0; } link_dir = mf->mf_fo->opt_sublink; if (link_dir && *link_dir) { if (*link_dir == '/') { mp->am_link = strdup(link_dir); } else { mp->am_link = str3cat((char *) 0, mf->mf_fo->opt_fs, "/", link_dir); normalize_slash(mp->am_link); } } if (mf->mf_error > 0) { this_error = mf->mf_error; } else if (mf->mf_flags & (MFF_MOUNTING|MFF_UNMOUNTING)) { /* * Still mounting - retry later */#ifdef DEBUG dlog("Duplicate pending mount fstype %s", p->fs_type);#endif /* DEBUG */ this_error = -1; } else if (FSRV_ISDOWN(mf->mf_server)) { /* * Would just mount from the same place * as a hung mount - so give up */#ifdef DEBUG dlog("%s is already hung - giving up", mf->mf_mount);#endif /* DEBUG */ mp_error = EWOULDBLOCK; dont_retry = TRUE; this_error = -1; } else if (mf->mf_flags & MFF_MOUNTED) {#ifdef DEBUG dlog("duplicate mount of \"%s\" ...", mf->mf_info);#endif /* DEBUG */ /* * Just call mounted() */ am_mounted(mp); this_error = 0; break; } /* * Will usually need to play around with the mount nodes * file attribute structure. This must be done here. * Try and get things initialised, even if the fileserver * is not known to be up. In the common case this will * progress things faster. */ if (!this_error) { /* * Fill in attribute fields. */ if (mf->mf_ops->fs_flags & FS_DIRECTORY) mk_fattr(mp, NFDIR); else mk_fattr(mp, NFLNK); mp->am_fattr.fileid = mp->am_gen; if (p->fs_init) this_error = (*p->fs_init)(mf); } /* * Make sure the fileserver is UP before doing any more work */ if (!FSRV_ISUP(mf->mf_server)) {#ifdef DEBUG dlog("waiting for server %s to become available", mf->mf_server->fs_host);#endif this_error = -1; } if (!this_error && mf->mf_fo->opt_delay) { /* * If there is a delay timer on the mount * then don't try to mount if the timer * has not expired. */ int i = atoi(mf->mf_fo->opt_delay); if (i > 0 && clocktime() < (cp->start + i)) {#ifdef DEBUG dlog("Mount of %s delayed by %ds", mf->mf_mount, i - clocktime() + cp->start);#endif /* DEBUG */ this_error = -1; } } if (this_error < 0 && !dont_retry) { if (!mf_retry) mf_retry = dup_mntfs(mf); cp->retry = TRUE; } if (!this_error) if (p->fs_flags & FS_MBACKGROUND) { mf->mf_flags |= MFF_MOUNTING; /*XXX*/#ifdef DEBUG dlog("backgrounding mount of \"%s\"", mf->mf_mount);#endif /* DEBUG */ if (cp->callout) { untimeout(cp->callout); cp->callout = 0; } run_task(try_mount, (voidp) mp, afs_cont, (voidp) cp); mf->mf_flags |= MFF_MKMNT; /* XXX */ if (mf_retry) free_mntfs(mf_retry); return -1; } else {#ifdef DEBUG dlog("foreground mount of \"%s\" ...", mf->mf_info);#endif /* DEBUG */ this_error = try_mount((voidp) mp); if (this_error < 0) { if (!mf_retry) mf_retry = dup_mntfs(mf); cp->retry = TRUE; } } if (this_error >= 0) { if (this_error > 0) { amd_stats.d_merr++; if (mf != mf_retry) { mf->mf_error = this_error; mf->mf_flags |= MFF_ERROR; } } /* * Wakeup anything waiting for this mount */ wakeup((voidp) mf); } } if (this_error && cp->retry) { free_mntfs(mf); mf = cp->mp->am_mnt = mf_retry; /* * Not retrying again (so far) */ cp->retry = FALSE; cp->tried = FALSE; /* * Start at the beginning. * Rewind the location vector and * reset the default options. */ cp->ivec = cp->xivec; cp->def_opts = strealloc(cp->def_opts, cp->auto_opts); /* * Arrange that afs_bgmount is called * after anything else happens. */#ifdef DEBUG dlog("Arranging to retry mount of %s", cp->mp->am_path);#endif /* DEBUG */ sched_task(afs_retry, (voidp) cp, (voidp) mf); if (cp->callout) untimeout(cp->callout); cp->callout = timeout(RETRY_INTERVAL, wakeup, (voidp) mf); cp->mp->am_ttl = clocktime() + RETRY_INTERVAL; /* * Not done yet - so don't return anything */ return -1; } if (hard_error < 0 || this_error == 0) hard_error = this_error; /* * Discard handle on duff filesystem. * This should never happen since it * should be caught by the case above. */ if (mf_retry) { if (hard_error) plog(XLOG_ERROR, "discarding a retry mntfs for %s", mf_retry->mf_mount); free_mntfs(mf_retry); } /* * If we get here, then either the mount succeeded or * there is no more mount information available. */ if (hard_error < 0 && mp_error) hard_error = cp->mp->am_error = mp_error; if (hard_error > 0) { /* * Set a small(ish) timeout on an error node if * the error was not a time out. */ switch (hard_error) { case ETIMEDOUT: case EWOULDBLOCK: cp->mp->am_timeo = 5; break; default: cp->mp->am_timeo = 17; break; } new_ttl(cp->mp); } /* * Make sure that the error value in the mntfs has a * reasonable value. */ if (mf->mf_error < 0) { mf->mf_error = hard_error; if (hard_error) mf->mf_flags |= MFF_ERROR; } /* * In any case we don't need the continuation any more */ free_continuation(cp); return hard_error;}/* * Automount interface to RPC lookup routine */static am_node *afs_lookuppn P((am_node *mp, char *fname, int *error_return, int op));static am_node *afs_lookuppn(mp, fname, error_return, op)am_node *mp;char *fname;int *error_return;int op;{#define ereturn(x) { *error_return = x; return 0; } /* * Find the corresponding entry and return * the file handle for it. */ am_node *ap, *new_mp, *ap_hung; char *info; /* Mount info - where to get the file system */ char **ivec, **xivec; /* Split version of info */ char *auto_opts; /* Automount options */ int error = 0; /* Error so far */ char path_name[MAXPATHLEN]; /* General path name buffer */ char *pfname; /* Path for database lookup */ struct continuation *cp; /* Continuation structure if we need to mount */ int in_progress = 0; /* # of (un)mount in progress */ char *dflts; mntfs *mf;#ifdef DEBUG dlog("in afs_lookuppn");#endif /* DEBUG */ /* * If the server is shutting down * then don't return information * about the mount point. */ if (amd_state == Finishing) {#ifdef DEBUG if ((mf = mp->am_mnt) == 0 || mf->mf_ops == &dfs_ops) dlog("%s mount ignored - going down", fname); else dlog("%s/%s mount ignored - going down", mp->am_path, fname);#endif /* DEBUG */ ereturn(ENOENT); } /* * Handle special case of "." and ".." */ if (fname[0] == '.') { if (fname[1] == '\0')
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -