📄 nfs_subr.c
字号:
clfree(cht); timeout(nfs_hardpause, (caddr_t)u.u_procp, MAX(((timeo * hz) / 10), hz)); sleep((caddr_t)u.u_procp, PRIBIO); cht = clget(mi, cred); client = cht->ch_client; client->cl_xid = hold_nfs_xid; } } } } while (tryagain); if (status != RPC_SUCCESS) { if (status == RPC_INTR) { rpcerr.re_status = RPC_INTR; rpcerr.re_errno = EINTR; u.u_error = EINTR; } else { CLNT_GETERR(client, &rpcerr); mprintf("NFS %s failed for server %s: %s\n", rfsnames[which], mi->mi_hostname, rpcstatnames[(int)status]); if (do_uprintf && u.u_procp->p_ttyp) uprintf("NFS %s failed for server %s: %s\n", rfsnames[which], mi->mi_hostname, rpcstatnames[(int)status]); if (!u.u_error) u.u_error = EIO; /* if in doubt ... */ } smp_lock(&lk_nfsstat, LK_RETRY); clstat.nbadcalls++; smp_unlock(&lk_nfsstat); mi->mi_down = 1; } else if (resp && *(int *)resp == EACCES && newcred == NULL && cred->cr_uid == 0 && cred->cr_ruid != 0) { /* * Boy is this a kludge! If the reply status is EACCES * it may be because we are root (no root net access). * Check the real uid, if it isn't root make that * the uid instead and retry the call. */ newcred = crdup(cred); cred = newcred; cred->cr_uid = cred->cr_ruid; clfree(cht); goto retry; } else if (mi->mi_hard) { if (mi->mi_printed) { mprintf("NFS server %s ok\n", mi->mi_hostname); mi->mi_printed = 0; } if (user_told) { uprintf("NFS server %s ok\n", mi->mi_hostname); } } else { mi->mi_down = 0; } clfree(cht); if (newcred) { crfree(newcred); } return (rpcerr.re_errno);}/* * Set vattr structure to a null value. */voidvattr_null(vap) struct vattr *vap;{ register int n; register char *cp; n = sizeof(struct vattr); cp = (char *)vap; while (n--) { *cp++ = -1; }}int attrdebug = 0;vattr_to_sattr(vap, sa) register struct vattr *vap; register struct nfssattr *sa;{ sa->sa_mode = vap->va_mode; sa->sa_uid = vap->va_uid; sa->sa_gid = vap->va_gid; sa->sa_size = vap->va_size; sa->sa_atime = vap->va_atime; sa->sa_mtime = vap->va_mtime;if (attrdebug) { printf("vattr_to_sattr: atime: %d, %d mtime: %d, %d\n", sa->sa_atime.tv_sec, sa->sa_atime.tv_usec, sa->sa_mtime.tv_sec, sa->sa_mtime.tv_usec);}}setdiropargs(da, nm, dvp) struct nfsdiropargs *da; char *nm; struct vnode *dvp;{ da->da_fhandle = *vtofh(dvp); da->da_name = nm;}/* * Return a gnode for the given fhandle. If no gnode exists for this * fhandle create one and put it in the gnode table. If a gnode is found, * return it with its reference count incremented. */struct rnode_data { fhandle_t *rn_fh; struct nfsfattr *rn_attr; int rn_newnode;};/* * Return a gnode for the given fhandle. If no gnode exists for this * fhandle create one and put it in the gnode table. If a gnode is found, * return it with its reference count incremented. KLUDGE: the GFS buffer * hashing scheme will not work unless we reuse the same gnode slot when * we reopen a given file. For this reason we leave gnodes on their * hash chain when we free them, so gget can find them and reclaim them. * We must take care when reinitializing reclaimed gnodes; some parts must * be reinitialized and others must be kept from the last invocation (such * as the modify time). */struct vnode *makenfsnode(fh, attr, vfsp, mp) fhandle_t *fh; struct nfsfattr *attr; struct vfs *vfsp; struct mount *mp;{ char newnode = 0; register struct gnode *gp; struct rnode_data rnd; register struct vnode *vp; gno_t gno; rnd.rn_fh = fh; rnd.rn_attr = attr; rnd.rn_newnode = 0; gno = (attr) ? attr->na_nodeid : fh->fh_fno; gp = gget(mp, gno, 1, &rnd); if (gp != NULL) { gfs_unlock(gp); if (attr && rnd.rn_newnode == 0) nfs_attrcache(gp, attr, SFLUSH); } return ((struct vnode *)gp);}intnfs_match(gp, rdp) struct gnode *gp; struct rnode_data *rdp;{ return(!bcmp(vtofh((struct vnode *)gp), rdp->rn_fh, sizeof(fhandle_t)));}/* * Initialize the gnode if this is the first reference (the gnode * is either new or reclaimed). */nfs_ginit(gp, iflag, rdp) struct gnode *gp; int iflag; struct rnode_data *rdp;{ register struct vnode *vp = (struct vnode *)gp; register struct nfsfattr *attr; int type;/* * if we get here via ggrab, rdp is null, so we need to return an * error, so ufs_namei will keep its hands off this gnode... */ if (rdp == NULL) return(NULL); attr = rdp->rn_attr; gp->g_ops = nfs_gnode_ops; bzero(vtor((struct vnode *)gp), sizeof(struct rnode)); vtor(vp)->r_fh = *(rdp->rn_fh); if (attr) vp->v_type = (enum vtype)attr->na_type; vp->v_vfsp = MP_TO_VFSP(gp->g_mp); ((struct mntinfo *)(vp->v_vfsp->vfs_data))->mi_refct++; if (attr) nfs_attrcache(gp, attr, (iflag == NEW_GNODE) ? NOFLUSH : SFLUSH); type = gp->g_mode & GFMT; if ((type == GFCHR) || (type == GFBLK) || (type == GFPORT)) specvp(gp); rdp->rn_newnode = 1; return(1);}/* * Kludge an "invisible temp name from an existing name. * Attempt to make a unique one, * but can't guarantee this. This new name is used for the * "rename game" - renaming an open file that is unlinked over NFS. * Use hostid, pid, and a generation # in the temp name. */#define PREFIXLEN 4static char prefix[PREFIXLEN+1] = ".nfs";u_long rename_gennum;char *newname(s) char *s;{ register char *news; register char *s1, *s2; register int i; register u_long id; kmem_alloc(news, char *, (u_int)NFS_MAXNAMLEN, KM_NFS); for (s1 = news, s2 = prefix; s2 < &prefix[PREFIXLEN]; ) { *s1++ = *s2++; } id = hostid; for (i = 0; i < sizeof(id)*2; i++) { *s1++ = "0123456789ABCDEF"[id & 0x0f]; id = id >> 4; } id = u.u_procp->p_pid; for (i = 0; i < sizeof(id)*2; i++) { *s1++ = "0123456789ABCDEF"[id & 0x0f]; id = id >> 4; } if (!rename_gennum) rename_gennum = timepick->tv_usec; id = rename_gennum++; for (i = 0; i < sizeof(id)*2; i++) { *s1++ = "0123456789ABCDEF"[id & 0x0f]; id = id >> 4; } *s1 = '\0'; return (news);}/* * Server side utilities */vattr_to_nattr(vap, na) register struct vattr *vap; register struct nfsfattr *na;{ na->na_type = (enum nfsftype)vap->va_type; na->na_mode = vap->va_mode; na->na_uid = vap->va_uid; na->na_gid = vap->va_gid; na->na_fsid = vap->va_fsid; na->na_nodeid = vap->va_nodeid; na->na_nlink = vap->va_nlink; na->na_size = vap->va_size; na->na_atime = vap->va_atime; na->na_mtime = vap->va_mtime; na->na_ctime = vap->va_ctime; na->na_rdev = vap->va_rdev; na->na_blocks = vap->va_blocks; na->na_blocksize = vap->va_blocksize; /* * This bit of ugliness is a *TEMPORARY* hack to preserve the * over-the-wire protocols for named-pipe vnodes. It remaps the * VFIFO type to the special over-the-wire type. (see note in nfs.h) * * BUYER BEWARE: * If you are porting the NFS to a non-SUN server, you probably * don't want to include the following block of code. The * over-the-wire special file types will be changing with the * NFS Protocol Revision. */ if ((vap->va_mode&GFMT) == GFPORT) { na->na_type = (enum nfsftype)VCHR; na->na_rdev = NFS_FIFO_DEV; na->na_mode = (na->na_mode&~GFMT)|GFCHR; }}sattr_to_vattr(sa, vap) register struct nfssattr *sa; register struct vattr *vap;{ vattr_null(vap); vap->va_mode = sa->sa_mode; vap->va_uid = sa->sa_uid; vap->va_gid = sa->sa_gid; vap->va_size = sa->sa_size; vap->va_atime = sa->sa_atime; vap->va_mtime = sa->sa_mtime; if (attrdebug) { printf("sattr_to_vattr: atime: %d, %d mtime: %d, %d\n", sa->sa_atime.tv_sec, sa->sa_atime.tv_usec, sa->sa_mtime.tv_sec, sa->sa_mtime.tv_usec); }}/* * Make an fhandle from a ufs gnode */makefh(fh, gp, enumber, egen) register fhandle_t *fh; struct gnode *gp; u_long enumber, egen;{ if (gp->g_mp->m_ops == nfs_mount_ops) return(EREMOTE); bzero((caddr_t)fh, NFS_FHSIZE); fh->fh_fsid = gp->g_dev; fh->fh_fno = gp->g_number; fh->fh_fgen = gp->g_gennum; fh->fh_eno = enumber; fh->fh_egen = egen; return (0);}/* * Global "constants" and defines used for stale file handle processing */long stalefh_count = 0;long nfs_n_nomount = 0;long nfs_last_nomount = 0;long nfs_nomount_thresh = 10;long nfs_nomount_timeout = 600;long nfs_noexport_thresh = 10;long nfs_noexport_timeout = 600;long nfs_stale_thresh = 10;long nfs_stale_timeout = 600;#define NFS_N_NOEXPORT(mp) ((mp)->m_fs_data->fd_spare[100])#define NFS_LAST_NOEXPORT(mp) ((mp)->m_fs_data->fd_spare[101])#define NFS_N_STALE(mp) ((mp)->m_fs_data->fd_spare[102])#define NFS_LAST_STALE(mp) ((mp)->m_fs_data->fd_spare[103])/* * Convert a fhandle into a gnode. Uses the inode number in the * fhandle (fh_fno) to get the locked inode. The inode is unlocked * and used to get the gnode. WARNING: users of this routine must * do a VN_RELE on the gnode when they are done with it. */struct vnode *fhtovp(fh, xprt, which, xpd) fhandle_t *fh; SVCXPRT *xprt; int which; struct exportdata *xpd;{ register struct mount *mp; register struct gnode *gp; register int *grp; /* group ID pointer */ register struct gnode *rgp; struct export *ep; extern struct mount *getmp(); extern struct gnode *fref(); int print; print = 1; /* * Check that the file system is mounted on and * if so get a ref on it. */ GETMP(mp, fh->fh_fsid); if ((rgp = fref(mp, fh->fh_fsid)) == NULL) { /* * These messages can be a pain - sometimes you want them, * sometimes (most of the time) you don't. * Print the first nfs_nomount_thresh, then keep a * timestamp and throw the rest away until nfs_nomount_timeout * seconds have passed; after that, start over with the * same algorithm. * * If nfs_nomount_thresh is set (via adb or the like) * to zero, then all messages will be printed. * * If nfs_nomount_thresh is positive, and * nfs_nomount_timeout is set to zero, * then no more than nfs_nomount_thresh messages will be * printed. */ if (nfs_nomount_thresh) { ++nfs_n_nomount; if (nfs_n_nomount == nfs_nomount_thresh) { nfs_last_nomount = timepick->tv_sec; } else if (nfs_n_nomount > nfs_nomount_thresh) { if (nfs_nomount_timeout && timepick->tv_sec > nfs_last_nomount + nfs_nomount_timeout) { nfs_n_nomount = 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -