📄 nfs_vfsops.c
字号:
/* * nfs_mountroot is called from mount_root() to mount the rootfs */struct mount *nfs_mountroot(special, path, flag, mp, ops)caddr_t special;caddr_t path;int flag;struct mount *mp;struct nfs_gfs_mount *ops;{ struct vnode *rootvp = NULL; /* root vnode */ struct vnode *hidvp = NULL; /* local vnode to be hidden */ struct vfs *vfsp; /* nfs vfs handle */ struct mntinfo *mi; /* mount info, pointed at by vfs */ struct vattr va; /* root vnode attributes */ struct nfsfattr na; /* root vnode attributes in nfs form */ struct statfs sb; /* server's file system stats */ fhandle_t fh; int i;#ifdef NFSDEBUG nfsdebug=0; dprint(nfsdebug, 4, "nfs_mount: special=%s, path=%s, flag=%d\n", special, path, flag); dprint(nfsdebug, 4, "nfs_mount: mp = 0x%x, ops = 0x%x\n", mp, ops);#endif /* * Set up data structures in fsdata spare area */ mi = MP_TO_MIP(mp); vfsp = MP_TO_VFSP(mp); mp->m_bufp = (struct buf *) (NODEV); /* to reserve this slot */ mp->m_dev = rootdev = getpdev(); /* pseudo-device number */ mp->iostrat = nfs_strategy; /* set it immediately */ mp->m_ops = nfs_mount_ops; mp->m_fstype = GT_NFS; mp->m_flags = (flag ? M_RONLY : 0); mp->m_flags |= (ops->gfs_flags & (M_NOEXEC | M_NOSUID | M_NODEV | M_SYNC)); if (ops->flags & NFSMNT_PGTHRESH) { int pg_thresh = ops->pg_thresh * 1024; mp->m_fs_data->fd_pgthresh = (pg_thresh > MINPGTHRESH) ? pg_thresh : MINPGTHRESH; } else { mp->m_fs_data->fd_pgthresh = MINPGTHRESH * 8; } /* * Clear out full size of fh and stuff in fhandle from ops */ bcopy(ops->fh, &fh, sizeof(fhandle_t)); bcopy(ops->addr,&mi->mi_addr,sizeof(struct sockaddr_in)); bcopy(ops->hostname,mi->mi_hostname,sizeof(mi->mi_hostname));#ifdef NFSDEBUG dprint(nfsdebug, 4, "nfs_mount: saddr 0x%x, fh dev 0x%x gno %d\n", &(mi->mi_addr), fh.fh_fsid, fh.fh_fno);#endif /* * Create a mount record */ mi->mi_refct = 0; mi->mi_stsize = 0; mi->mi_hard = ((ops->flags & NFSMNT_SOFT) == 0); mi->mi_int = ((ops->flags & NFSMNT_INT) == NFSMNT_INT); mi->mi_noac = ((ops->flags & NFSMNT_NOAC) == NFSMNT_NOAC); if (!mi->mi_noac) { mi->mi_acregmin = ops->acregmin; mi->mi_acregmax = ops->acregmax; mi->mi_acdirmin = ops->acdirmin; mi->mi_acdirmax = ops->acdirmax; } if (ops->flags & NFSMNT_RETRANS) { mi->mi_retrans = ops->retrans; if (ops->retrans < 0) { u.u_error = EINVAL; goto error; } } else { mi->mi_retrans = NFS_RETRIES; } if (ops->flags & NFSMNT_TIMEO) { mi->mi_timeo = ops->timeo; if (ops->timeo <= 0) { u.u_error = EINVAL; goto error; } } else { mi->mi_timeo = NFS_TIMEO; } mi->mi_mntno = nfsmntno++; mi->mi_printed = 0;#ifdef NFSDEBUG dprint(nfsdebug, 4, "nfs_mount: mi_addr 0x%x port %d addr 0x%x\n", &mi->mi_addr, mi->mi_addr.sin_port, (int)mi->mi_addr.sin_addr.s_addr);#endif /* * For now we just support AF_INET */ if (mi->mi_addr.sin_family != AF_INET) { u.u_error = EPFNOSUPPORT; goto error; } /* * Make a vfs struct for nfs. We do this here instead of below * because rootvp needs a vfs before we can do a getattr on it. */ VFS_INIT(vfsp, (caddr_t)mi); /* * Make the root vnode */ rootvp = makenfsnode(&fh, (struct nfsfattr *) 0, vfsp, mp); /* * Get attributes of the root vnode. */ u.u_error = nfs_makeroot(&fh, &rootvp); if (u.u_error) { goto error; } mp->m_rootgp = (struct gnode *) rootvp; mi->mi_rootvp = rootvp; if(u.u_uid) { ((struct gnode *) rootvp)->g_uid = u.u_uid; ((struct gnode *) rootvp)->g_flag |= GCHG; } /* * Get server's filesystem stats. Use these to set transfer sizes */ mi->mi_tsize = min(NFS_MAXDATA, nfstsize()); if (ops->flags & NFSMNT_RSIZE) { if (ops->rsize <= 0) { u.u_error = EINVAL; goto error; } mi->mi_tsize = MIN(mi->mi_tsize, ops->rsize); } if (ops->flags & NFSMNT_WSIZE) { if (ops->wsize <= 0) { u.u_error = EINVAL; goto error; } mi->mi_stsize = ops->wsize; /* touched by nfs_getfsdata */ } (void) nfs_getfsdata(mp); if (u.u_error) { goto error; }#ifdef NFSDEBUG dprint(nfsdebug, 10, "nfs_mount: vfs %x: vnodecov = %x, data = %x\n", vfsp, vfsp->vfs_vnodecovered, vfsp->vfs_data); dprint(nfsdebug, 10, "rootvp %x: vfs %x\n", rootvp, rootvp->v_vfsp); dprint(nfsdebug, 4, "nfs_mount: hard %d timeo %d retries %d wsize %d rsize %d\n", mi->mi_hard, mi->mi_timeo, mi->mi_retrans, mi->mi_stsize, mi->mi_tsize); dprint(nfsdebug, 4, "nfs_mount: mp->m_flags = 0x%x\n", mp->m_flags); dprint(nfsdebug, 4, "nfs_mount: fd_otsize = %d, fd_mtsize=%d\n", mp->m_fs_data->fd_otsize, mp->m_fs_data->fd_mtsize);#endif /* * Should set read only here! */ mi->mi_bsize = NFS_MAXDATA; vfsp->vfs_bsize = mi->mi_bsize; mp->m_bsize = mi->mi_bsize; bzero(mp->m_fs_data->fd_path,sizeof(mp->m_fs_data->fd_path)); bcopy("/",mp->m_fs_data->fd_path,sizeof("/")); bzero(mp->m_fs_data->fd_devname,sizeof(mp->m_fs_data->fd_devname)); bcopy(special,mp->m_fs_data->fd_devname,NFS_MAXPATHLEN); mp->m_fs_data->fd_dev=mp->m_dev; inittodr(rootvp->g_in.gn.gc_ctime);#ifdef NFSDEBUG dprint(nfsdebug, 4, "nfs_mount: vfs_bsize %d\n",vfsp->vfs_bsize);#endif dnlc_purge(); return(mp);error:#ifdef NFSDEBUG dprint(nfsdebug, 4, "nfs_mount: returning error, %d\n", u.u_error);#endif if (u.u_error) { if (hidvp) { VN_RELE(hidvp); } if (rootvp) { VN_RELE(rootvp); } } return((struct mount *)NULL);}/* * callrpc */enum clnt_stat callrpc(sin, prognum, versnum, procnum, inproc, in, outproc, out) struct sockaddr_in *sin; int prognum, versnum, procnum; xdrproc_t inproc, outproc; char *in, *out;{ CLIENT *cl; struct timeval tv; enum clnt_stat cl_stat; int i; struct ucred *tmpcred, *savecred; /* Set up credential */ tmpcred = crdup(u.u_cred); savecred = u.u_cred; u.u_cred = tmpcred; u.u_uid = 0; u.u_gid = 0; for (i=1; i<NGROUPS; i++) u.u_groups[i] = NOGROUP; cl = clntkudp_create(sin, prognum, versnum, 1, u.u_cred); tv.tv_sec = 20; tv.tv_usec = 0; cl_stat = CLNT_CALL(cl, procnum, inproc, in, outproc, out, tv); AUTH_DESTROY(cl->cl_auth); CLNT_DESTROY(cl); /* * Reset credentials */ u.u_cred = savecred; crfree(tmpcred); return (cl_stat);}/* * Call mount daemon on server sin to mount path. * sin_port is set to nfs port and fh is the fhandle * returned from the server. */mountrpc(sin, path, fh) struct sockaddr_in *sin; char *path; fhandle_t *fh;{ struct fhstatus fhs; int error; int i; enum clnt_stat status; error = pmap_kgetport(sin, MOUNTPROG, MOUNTVERS, IPPROTO_UDP); if (error) { printf("mountrpc: pmap_kgetport returned error %d\n", error); panic("nfs_mountrpc cannot get port for mount service"); } status = callrpc(sin, MOUNTPROG, MOUNTVERS, MOUNTPROC_MNT, xdr_path, &path, xdr_fhstatus, &fhs); if (status != RPC_SUCCESS) { printf("mountrpc: callrpc returned error %d\n", status); panic("mountrpc: cannot NFS mount file"); } sin->sin_port = htons(NFS_PORT); bcopy((caddr_t)&fhs.fhs_fh, (caddr_t)fh, sizeof(fhandle_t)); return (fhs.fhs_status);}/* * nfs_resolvfh - resolve a file handle using the MOP server IP and * input path * * inputs: destination file handle ptr, source pathname * */nfs_resolvfh(fhdl,path) fhandle_t *fhdl; char *path;{ int erret; struct sockaddr_in sin; extern struct netblk *netblk_ptr; bzero(&sin, sizeof(sin)); sin.sin_addr.s_addr=ntohl(netblk_ptr->srvipadr); sin.sin_family=AF_INET; sin.sin_port=htons(NFS_PORT); erret=mountrpc(&sin,path,fhdl); if(erret!=0) panic("resolvfh: cannot resolve file handle"); return(0);}/* * Get file system statistics. */intnfs_statfs(mp, sbp)register struct mount *mp;struct statfs *sbp;{ struct nfsstatfs fs; struct mntinfo *mi; fhandle_t *fh; mi = MP_TO_MIP(mp); fh = vtofh(mi->mi_rootvp);#ifdef NFSDEBUG dprint(nfsdebug, 4, "nfs_statfs fh %o %d\n", fh->fh_fsid, fh->fh_fno);#endif u.u_error = rfscall(mi, RFS_STATFS, xdr_fhandle, (caddr_t)fh, xdr_statfs, (caddr_t)&fs, u.u_cred); if (u.u_error) { register struct fs_data *fsd = mp->m_fs_data; if (u.u_error == ETIMEDOUT) { u.u_error = 0; sbp->f_bsize = fsd->fd_bsize; sbp->f_blocks = fsd->fd_btot; sbp->f_bfree = fsd->fd_bfree; sbp->f_bavail = fsd->fd_bfreen; } } else { if (!(u.u_error = geterrno(fs.fs_status))) { if (mi->mi_stsize) { mi->mi_stsize = min(mi->mi_stsize, fs.fs_tsize); } else { mi->mi_stsize = fs.fs_tsize; } /* * XXX - Calculate file system stats returned * by the server into 1K denominations. User level * land expects this. */ sbp->f_bsize = fs.fsstat_bsize; sbp->f_blocks = (long)(fs.fs_blocks * fs.fsstat_bsize) / FSDUNIT; sbp->f_bfree = (long)(fs.fs_bfree * fs.fsstat_bsize) / FSDUNIT; sbp->f_bavail = (long)(fs.fs_bavail * fs.fsstat_bsize) / FSDUNIT; /* * ULTRIX doesn't use the fsid */ bzero((caddr_t)sbp->f_fsid, sizeof(fsid_t)); } } #ifdef NFSDEBUG dprint(nfsdebug, 5, "nfs_statfs returning %d\n", u.u_error); dprint(nfsdebug, 5, "fs_tsize = %d, fsstat_bsize = %d, fs_blocks = %d\n", fs.fs_tsize, fs.fsstat_bsize, fs.fs_blocks); dprint(nfsdebug, 5, "fs_bfree = %d, fs_bavail = %d\n", fs.fs_bfree, fs.fs_bavail);#endif return (u.u_error);}static char *itoa(n, str) u_short n; char *str;{ char prbuf[11]; register char *cp; cp = prbuf; do { *cp++ = "0123456789"[n%10]; n /= 10; } while (n); do { *str++ = *--cp; } while (cp > prbuf); return (str);}/* * Convert a INET address into a string for printing */addr_to_str(addr, str) struct sockaddr_in *addr; char *str;{ str = itoa(addr->sin_addr.s_net, str); *str++ = '.'; str = itoa(addr->sin_addr.s_host, str); *str++ = '.'; str = itoa(addr->sin_addr.s_lh, str); *str++ = '.'; str = itoa(addr->sin_addr.s_impno, str); *str = '\0';}intnfs_makeroot(fh, vpp) fhandle_t *fh; struct vnode **vpp;{ struct nfsattrstat *ns; int error = 0; struct mount *mp; struct vfs *vfsp; struct vnode *vp; vp = *vpp; mp = (*vpp)->g_mp; vfsp = (*vpp)->v_vfsp; kmem_alloc(ns, struct nfsattrstat *, (u_int)sizeof(*ns), KM_NFS); error = rfscall(vtomi(*vpp), RFS_GETATTR, xdr_fhandle, (caddr_t)vtofh(vp), xdr_attrstat, (caddr_t)ns, u.u_cred); if (!error) { if (error = geterrno(ns->ns_status)) goto out; } nfs_rele(*vpp); *vpp = makenfsnode(fh, &(ns->ns_attr), vfsp, mp); if (*vpp == NULL) error = u.u_error;out: kmem_free(ns, KM_NFS); return(error);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -