📄 afs_ops.c
字号:
return mp; /* "." is the current node */ if (fname[1] == '.' && fname[2] == '\0') { if (mp->am_parent) {#ifdef DEBUG dlog(".. in %s gives %s", mp->am_path, mp->am_parent->am_path);#endif /* DEBUG */ return mp->am_parent; /* ".." is the parent node */ } ereturn(ESTALE); } } /* * Check for valid key name. * If it is invalid then pretend it doesn't exist. */ if (!valid_key(fname)) { plog(XLOG_WARNING, "Key \"%s\" contains a disallowed character", fname); ereturn(ENOENT); } /* * Expand key name. * fname is now a private copy. */ fname = expand_key(fname); for (ap_hung = 0, ap = mp->am_child; ap; ap = ap->am_osib) { /* * Otherwise search children of this node */ if (FSTREQ(ap->am_name, fname)) { mf = ap->am_mnt; if (ap->am_error) { error = ap->am_error; continue; } /* * If the error code is undefined then it must be * in progress. */ if (mf->mf_error < 0) goto in_progrss; /* * Check for a hung node */ if (FSRV_ISDOWN(mf->mf_server)) {#ifdef DEBUG dlog("server hung");#endif /* DEBUG */ error = ap->am_error; ap_hung = ap; continue; } /* * If there was a previous error with this node * then return that error code. */ if (mf->mf_flags & MFF_ERROR) { error = mf->mf_error; continue; } if (!(mf->mf_flags & MFF_MOUNTED) /*|| (mf->mf_flags & MFF_UNMOUNTING)*/) {in_progrss: /* * If the fs is not mounted or it is unmounting then there * is a background (un)mount in progress. In this case * we just drop the RPC request (return nil) and * wait for a retry, by which time the (un)mount may * have completed. */#ifdef DEBUG dlog("ignoring mount of %s in %s -- in progress", fname, mf->mf_mount);#endif /* DEBUG */ in_progress++; continue; } /* * Otherwise we have a hit: return the current mount point. */#ifdef DEBUG dlog("matched %s in %s", fname, ap->am_path);#endif /* DEBUG */ free(fname); return ap; } } if (in_progress) {#ifdef DEBUG dlog("Waiting while %d mount(s) in progress", in_progress);#endif /* DEBUG */ free(fname); ereturn(-1); } /* * If an error occured then return it. */ if (error) {#ifdef DEBUG errno = error; /* XXX */ dlog("Returning error: %m", error);#endif /* DEBUG */ free(fname); ereturn(error); } /* * If doing a delete then don't create again! */ switch (op) { case VLOOK_DELETE: ereturn(ENOENT); break; case VLOOK_CREATE: break; default: plog(XLOG_FATAL, "Unknown op to afs_lookuppn: 0x%x", op); ereturn(EINVAL); break; } /* * If the server is going down then just return, * don't try to mount any more file systems */ if ((int)amd_state >= (int)Finishing) {#ifdef DEBUG dlog("not found - server going down anyway");#endif /* DEBUG */ free(fname); ereturn(ENOENT); } /* * If we get there then this is a reference to an, * as yet, unknown name so we need to search the mount * map for it. */ if (mp->am_pref) { sprintf(path_name, "%s%s", mp->am_pref, fname); pfname = path_name; } else { pfname = fname; } mf = mp->am_mnt;#ifdef DEBUG dlog("will search map info in %s to find %s", mf->mf_info, pfname);#endif /* DEBUG */ /* * Consult the oracle for some mount information. * info is malloc'ed and belongs to this routine. * It ends up being free'd in free_continuation(). * * Note that this may return -1 indicating that information * is not yet available. */ error = mapc_search((mnt_map*) mf->mf_private, pfname, &info); if (error) { if (error > 0) plog(XLOG_MAP, "No map entry for %s", pfname); else plog(XLOG_MAP, "Waiting on map entry for %s", pfname); free(fname); ereturn(error); }#ifdef DEBUG dlog("mount info is %s", info);#endif /* DEBUG */ /* * Split info into an argument vector. * The vector is malloc'ed and belongs to * this routine. It is free'd in free_continuation() */ xivec = ivec = strsplit(info, ' ', '\"'); /* * Default error code... */ if (ap_hung) error = EWOULDBLOCK; else error = ENOENT; /* * Allocate a new map */ new_mp = exported_ap_alloc(); if (new_mp == 0) { free((voidp) xivec); free((voidp) info); free((voidp) fname); ereturn(ENOSPC); } if (mf->mf_auto) auto_opts = mf->mf_auto; else auto_opts = ""; auto_opts = strdup(auto_opts);#ifdef DEBUG dlog("searching for /defaults entry");#endif /* DEBUG */ if (mapc_search((mnt_map*) mf->mf_private, "/defaults", &dflts) == 0) { char *dfl; char **rvec;#ifdef DEBUG dlog("/defaults gave %s", dflts);#endif /* DEBUG */ if (*dflts == '-') dfl = dflts+1; else dfl = dflts; /* * Chop the defaults up */ rvec = strsplit(dfl, ' ', '\"'); /* * Extract first value */ dfl = rvec[0]; /* * If there were any values at all... */ if (dfl) { /* * Log error if there were other values */ if (rvec[1]) {#ifdef DEBUG dlog("/defaults chopped into %s", dfl);#endif /* DEBUG */ plog(XLOG_USER, "More than a single value for /defaults in %s", mf->mf_info); } /* * Prepend to existing defaults if they exist, * otherwise just use these defaults. */ if (*auto_opts && *dfl) { char *nopts = (char *) xmalloc(strlen(auto_opts)+strlen(dfl)+2); sprintf(nopts, "%s;%s", dfl, auto_opts); free(auto_opts); auto_opts = nopts; } else if (*dfl) { auto_opts = strealloc(auto_opts, dfl); } } free(dflts); /* * Don't need info vector any more */ free((voidp) rvec); } /* * Fill it in */ init_map(new_mp, fname); /* * Put it in the table */ insert_am(new_mp, mp); /* * Fill in some other fields, * path and mount point. * * bugfix: do not prepend old am_path if direct map * <wls@astro.umd.edu> William Sebok */ new_mp->am_path = str3cat(new_mp->am_path, mf->mf_ops == &dfs_ops ? "" : mp->am_path, *fname == '/' ? "" : "/", fname);#ifdef DEBUG dlog("setting path to %s", new_mp->am_path);#endif /* DEBUG */ /* * Take private copy of pfname */ pfname = strdup(pfname); /* * Construct a continuation */ cp = ALLOC(continuation); cp->mp = new_mp; cp->xivec = xivec; cp->ivec = ivec; cp->info = info; cp->key = pfname; cp->auto_opts = auto_opts; cp->retry = FALSE; cp->tried = FALSE; cp->start = clocktime(); cp->def_opts = strdup(auto_opts); bzero((voidp) &cp->fs_opts, sizeof(cp->fs_opts)); /* * Try and mount the file system * If this succeeds immediately (possible * for a ufs file system) then return * the attributes, otherwise just * return an error. */ error = afs_bgmount(cp, error); reschedule_timeout_mp(); if (!error) { free(fname); return new_mp; } if (error && (cp->mp->am_mnt->mf_ops == &efs_ops)) cp->mp->am_error = error; assign_error_mntfs(new_mp); free(fname); ereturn(error);#undef ereturn}/* * Locate next node in sibling list which is mounted * and is not an error node. */static am_node *next_nonerror_node P((am_node *xp));static am_node *next_nonerror_node(xp)am_node *xp;{ mntfs *mf; /* * Bug report (7/12/89) from Rein Tollevik <rein@ifi.uio.no> * Fixes a race condition when mounting direct automounts. * Also fixes a problem when doing a readdir on a directory * containing hung automounts. */ while (xp && (!(mf = xp->am_mnt) || /* No mounted filesystem */ mf->mf_error != 0 || /* There was a mntfs error */ xp->am_error != 0 || /* There was a mount error */ !(mf->mf_flags & MFF_MOUNTED) || /* The fs is not mounted */ (mf->mf_server->fs_flags & FSF_DOWN)) /* The fs may be down */ ) xp = xp->am_osib; return xp;}static int afs_readdir P((am_node *mp, nfscookie cookie, struct dirlist *dp, struct entry *ep, int count));static int afs_readdir(mp, cookie, dp, ep, count)am_node *mp;nfscookie cookie;struct dirlist *dp;struct entry *ep;int count;{ unsigned int gen = *(unsigned int*) cookie; am_node *xp; dp->eof = FALSE; if (gen == 0) { /* * In the default instance (which is used to * start a search) we return "." and "..". * * This assumes that the count is big enough * to allow both "." and ".." to be returned in * a single packet. If it isn't (which would * be fairly unbelievable) then tough. */#ifdef DEBUG dlog("default search");#endif /* DEBUG */ /* * Check for enough room. This is extremely * approximate but is more than enough space. * Really need 2 times: * 4byte fileid * 4byte cookie * 4byte name length * 4byte name * plus the dirlist structure */ if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp)))) return EINVAL; xp = next_nonerror_node(mp->am_child); dp->entries = ep; /* construct "." */ ep[0].fileid = mp->am_gen; ep[0].name = "."; ep[0].nextentry = &ep[1]; *(unsigned int *) ep[0].cookie = 0; /* construct ".." */ if (mp->am_parent) ep[1].fileid = mp->am_parent->am_gen; else ep[1].fileid = mp->am_gen; ep[1].name = ".."; ep[1].nextentry = 0; *(unsigned int *) ep[1].cookie = xp ? xp->am_gen : ~(unsigned int)0; if (!xp) dp->eof = TRUE; return 0; }#ifdef DEBUG dlog("real child");#endif /* DEBUG */ if (gen == ~(unsigned int)0) {#ifdef DEBUG dlog("End of readdir in %s", mp->am_path);#endif /* DEBUG */ dp->eof = TRUE; dp->entries = 0; return 0; } xp = mp->am_child; while (xp && xp->am_gen != gen) xp = xp->am_osib; if (xp) { int nbytes = count / 2; /* conservative */ int todo = MAX_READDIR_ENTRIES; dp->entries = ep; do { am_node *xp_next = next_nonerror_node(xp->am_osib); if (xp_next) { *(unsigned int *) ep->cookie = xp_next->am_gen; } else { *(unsigned int *) ep->cookie = ~(unsigned int)0; dp->eof = TRUE; } ep->fileid = xp->am_gen; ep->name = xp->am_name; nbytes -= sizeof(*ep) + strlen(xp->am_name) + 1; xp = xp_next; if (nbytes > 0 && !dp->eof && todo > 1) { ep->nextentry = ep + 1; ep++; --todo; } else { todo = 0; } } while (todo > 0); ep->nextentry = 0; return 0; } return ESTALE;}static am_node *dfs_readlink P((am_node *mp, int *error_return));static am_node *dfs_readlink(mp, error_return)am_node *mp;int *error_return;{ am_node *xp; int rc = 0; xp = next_nonerror_node(mp->am_child); if (!xp) { if (!mp->am_mnt->mf_private) afs_mkcacheref(mp->am_mnt); /* XXX */ xp = afs_lookuppn(mp, mp->am_path+1, &rc, VLOOK_CREATE); } if (xp) { new_ttl(xp); /* (7/12/89) from Rein Tollevik */ return xp; } if (amd_state == Finishing) rc = ENOENT; *error_return = rc; return 0;}/* * Ops structure */am_ops root_ops = { "root", 0, /* root_match */ 0, /* root_init */ root_mount, 0, afs_umount, 0, afs_lookuppn, afs_readdir, 0, /* root_readlink */ 0, /* root_mounted */ 0, /* root_umounted */ find_afs_srvr, FS_NOTIMEOUT|FS_AMQINFO|FS_DIRECTORY};am_ops afs_ops = { "auto", afs_match, 0, /* afs_init */ afs_mount, 0, afs_umount, 0, afs_lookuppn, afs_readdir, 0, /* afs_readlink */ 0, /* afs_mounted */ afs_umounted, find_afs_srvr, FS_AMQINFO|FS_DIRECTORY};am_ops toplvl_ops = { "toplvl", afs_match, 0, /* afs_init */ toplvl_mount, 0, toplvl_umount, 0, afs_lookuppn, afs_readdir, 0, /* toplvl_readlink */ toplvl_mounted, 0, /* toplvl_umounted */ find_afs_srvr, FS_MKMNT|FS_NOTIMEOUT|FS_BACKGROUND|FS_AMQINFO|FS_DIRECTORY};am_ops dfs_ops = { "direct", afs_match, 0, /* dfs_init */ toplvl_mount, 0, toplvl_umount, 0, efs_lookuppn, efs_readdir, dfs_readlink, toplvl_mounted, 0, /* afs_umounted */ find_afs_srvr, FS_MKMNT|FS_NOTIMEOUT|FS_BACKGROUND|FS_AMQINFO};#ifdef HAS_UNION_FSam_ops union_ops = { "union", afs_match, 0, /* afs_init */ toplvl_mount, 0, toplvl_umount, 0, afs_lookuppn, afs_readdir, 0, /* toplvl_readlink */ union_mounted, 0, /* toplvl_umounted */ find_afs_srvr, FS_MKMNT|FS_NOTIMEOUT|FS_BACKGROUND|FS_AMQINFO|FS_DIRECTORY};#endif /* HAS_UNION_FS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -