📄 nfs_gfsops.c
字号:
dprint(nfsdebug, 4, "called by 0x%x\n", *(&foo + 5));#endif if(gp->g_count <= 0) panic("nfs_rele: zero count");/* grele will take care of this if(gp->g_count == 1) nfs_inactive(gp, u.u_cred);*/ /* * Check the count again before freeing up the gnode, in case * another reference has been created (we may block in the * nfs_inactive call). * We have to worry about this because the gnode is still in the * cache during the period that we are making it inactive. *//* if (--gp->g_count == 0) { vp = (struct vnode *)gp; ((struct mntinfo *)vp->v_vfsp->vfs_data)->mi_refct--; if (vtor(vp)->r_cred) { crfree(vtor(vp)->r_cred); vtor(vp)->r_cred = NULL; } freegnode(gp); }*/ grele(gp);}nfs_unlink(gp, ndp) register struct gnode *gp; register struct nameidata *ndp;{#ifdef NFSDEBUG dprint(nfsdebug, 4, "nfs_unlink: trying to remove '%s' from gp 0x%x (%d)\n", ndp->ni_cp, ndp->ni_pdir, ndp->ni_pdir->g_number);#endif u.u_error = nfs_remove(ndp->ni_pdir, gp, ndp->ni_cp, u.u_cred); return(u.u_error);}struct fs_data *nfs_getfsdata(mp) register struct mount *mp;{ register struct fs_data *fsdata = mp->m_fs_data; struct statfs statfs;#ifdef GFSDEBUG if(GFS[14]) printf("nfs_getfsdata: mp 0x%x\n", mp);#endif u.u_error = nfs_statfs(mp, &statfs); if (!u.u_error) { fsdata->fd_fstype = GT_NFS; fsdata->fd_gtot = 0; fsdata->fd_gfree = 0; fsdata->fd_btot = statfs.f_blocks; fsdata->fd_bfree = statfs.f_bfree; fsdata->fd_bfreen = statfs.f_bavail; fsdata->fd_mtsize = fsdata->fd_otsize = MP_TO_MIP(mp)->mi_stsize; } return(fsdata);}nfs_gsymlink(ndp, to) register struct nameidata *ndp; register char *to;{ struct vattr va;#ifdef NFSDEBUG dprint(nfsdebug, 4, "nfs_symlink: creating a link with name '%s' parent 0x%x (%d)\n", ndp->ni_cp, ndp->ni_pdir, ndp->ni_pdir->g_number);#endif vattr_null(&va); va.va_mode = (0777 & ~u.u_cmask) & 0xffff; nfs_unlock(ndp->ni_pdir); u.u_error = nfs_symlink(ndp->ni_pdir, ndp->ni_cp, &va, to, u.u_cred); nfs_rele(ndp->ni_pdir); return(u.u_error);}struct gnode *nfs_makenode(mode, dev, ndp) register int mode; register dev_t dev; register struct nameidata *ndp;{ struct vattr _va; register struct vattr *va = &_va; struct gnode *vpp; #ifdef NFSDEBUG dprint(nfsdebug, 4, "nfs_makenode: trying to make '%s' mode 0%o\n", ndp->ni_cp, mode);#endif /* * replication of the gross mknod hack */ vattr_null(va); switch (mode & GFMT) { case GFREG: va->va_type = VREG; break; case GFCHR: va->va_type = VCHR;/* printf("nfs_makenode: making chr file '%s'\n",ndp->ni_cp); */ break; case GFBLK: va->va_type = VBLK;/* printf("nfs_makenode: making blk file '%s'\n",ndp->ni_cp); */ break; case GFPORT: va->va_type = VFIFO;/* printf("nfs_makenode: making fifo file '%s'\n",ndp->ni_cp); */ break; case GFSOCK: va->va_type = VSOCK;/* printf("nfs_makenode: making sock file '%s'\n",ndp->ni_cp); */ break; default: u.u_error = EINVAL; goto bad; } va->va_mode = (mode & ~u.u_cmask) & 0xffff; va->va_size = 0; va->va_rdev = dev; u.u_error = nfs_create(ndp->ni_pdir, ndp->ni_cp, va, NONEXCL, &vpp, u.u_cred);bad: gput(ndp->ni_pdir); if (u.u_error) return(NULL); else { nfs_lock(vpp); return(vpp); }}int nfsnameidebug = 0;/* * The routine nfs_namei performs pathname lookup in remote filesystems, * with side effects. * * Unlike the ufs namei, we leave a pointer to the last pathname component * in ndp->ni_cp. Other NFS code depends on this. */ struct gnode *nfs_namei(ndp) register struct nameidata *ndp;{ struct gnode *gpp, *gp; register char *slash, *ptr, *cp, *ncp; int lockparent, flag, i; char name[NFS_MAXNAMLEN+1]; struct uio _auio; register struct uio *auio = &_auio; struct iovec _aiov; register struct iovec *aiov = &_aiov; struct mount *mpp; int name_len; u_int sl_len, rem_len; #ifdef NFSDEBUG if (nfsnameidebug) printf("Entering nfs_namei to look up %s\n", ndp->ni_cp);#endif flag = ndp->ni_nameiop & (LOOKUP | CREATE | DELETE); lockparent = ndp->ni_nameiop & LOCKPARENT; gp = ndp->ni_pdir; nfs_unlock(gp);#ifdef NFSDEBUG if (gp == NULL) panic("nfs_namei: no parent"); if ((flag != LOOKUP) && (flag != CREATE) && (flag != DELETE)) panic("nfs_namei: bad flags");#endif NFSDEBUG cp = ndp->ni_cp; /* * This is a hack for the automounter which mounts itself as * a symbolic link for a direct map entry and expects to be * sent a readlink call. */ if ((gp->g_mode & GFMT) == GFLNK && ((ndp->ni_nameiop & FOLLOW) || *cp == '/')) { ncp = cp; gpp = gp; gref(gp); /* bump ref count */ goto MPLINK; } while (*cp == '/') cp++; while(*cp) { /* * Find the next pathname component, move it into name[]. */ for (i = 0; cp[i] != 0 && cp[i] != '/'; i++) { if (i == NFS_MAXNAMLEN) u.u_error = ENAMETOOLONG; /* disable parity checking for internationalization */ /* if (cp[i] & 0200) */ /* u.u_error = EINVAL; */ if (u.u_error) { nfs_rele(gp); return(NULL); } name[i] = cp[i]; } name_len = i + 1; name[i] = '\0'; ncp = cp + i; /* * If we're at the root of a filesystem and the next * component is ".." then we just bounce back to caller. */ if ((name[0] == '.') && (name[1] == '.') && !name[2] && ((gp == gp->g_mp->m_rootgp) || (gp == u.u_rdir))) { nfs_rele(gp); /* * If we are not at the system root directory, nor * at the processes root directory, set gp to the * mounted on gp. */ if ((gp->g_mp->m_gnodp != (struct gnode *) NULL) && gp != u.u_rdir) gp = gp->g_mp->m_gnodp; gref(gp); /* bump ref count */ gfs_lock(gp); gp->g_flag |= GINCOMPLETE; ndp->ni_pdir = gp; /* * If we're at the system root directory, or the * processes root directory, strip off ".." */ if (gp == gp->g_mp->m_rootgp || gp == u.u_rdir) ndp->ni_cp = ncp; else ndp->ni_cp = cp; return(gp); } /* * Now look up the current pathname component. */#ifdef NFSDEBUG if (nfsnameidebug) printf("nfs_namei: about to do an nfs_lookup for \"%s\"\n", name);#endif NFSDEBUG u.u_error = nfs_lookup(gp, name, &gpp, u.u_cred);#ifdef NFSDEBUGif (nfsnameidebug) { if (u.u_error) printf ("nfs_namei: nfs_lookup error return %d\n", u.u_error); if (gpp) printf("nfs_namei: nfs_lookup returned #%d\n", (gpp)->g_number); else printf("nfs_namei: nfs_lookup returned null\n");}#endif NFSDEBUG /* * Take appropriate action if the lookup fails. * Negate the error if the file doesn't exist and * the operation is create. */ if (u.u_error) { if ((flag == CREATE) && (cp[i] == '\0') && (u.u_error == ENOENT)) { nfs_lock(gp); if (!access(gp, GWRITE)) { u.u_error = 0; ndp->ni_pdir = gp; ndp->ni_cp = cp; } else { nfs_unlock(gp); nfs_rele(gp); } } else { nfs_rele(gp); } return(NULL); } /* * The lookup has succeeded. If we've hit a mount point * traverse it if it's type NFS, else bounce back to * caller. * * XXX Should check that unmount is not in progress on fs. */ if (gpp->g_flag & GMOUNT) { mpp = gpp->g_mpp; if (mpp->m_fstype != GT_NFS) { nfs_rele(gp); nfs_rele(gpp); gp = mpp->m_rootgp; gref(gp); /* bump ref count */ gfs_lock(gp); ndp->ni_cp = ncp; ndp->ni_pdir = gp; gp->g_flag |= GINCOMPLETE; return(gp); } else { nfs_rele(gp); gp = gpp; gpp = mpp->m_rootgp; gref(gpp); } } /* * Check for symbolic links */MPLINK: if ((gpp->g_mode & GFMT) == GFLNK && ((ndp->ni_nameiop & FOLLOW) || *ncp == '/')) { char *tcp; rem_len = 0; if (ncp != '\0') { /* * If more pathname to parse, save it * in the upper boundary of ni_dirp, because * the call to readlink will destroy path. */ rem_len = strlen(ncp); tcp = ndp->ni_dirp + (MAXPATHLEN - rem_len); ovbcopy(ncp, tcp, rem_len); } if (++ndp->ni_slcnt > MAXSYMLINKS) { u.u_error = ELOOP; nfs_rele(gp); nfs_rele(gpp); return (NULL); } aiov->iov_base = ndp->ni_dirp; aiov->iov_len = auio->uio_resid = MAXPATHLEN; auio->uio_iov = aiov; auio->uio_iovcnt = 1; auio->uio_segflg = UIO_SYSSPACE; auio->uio_offset = 0; u.u_error = nfs_readlink((struct vnode *)gpp, auio, u.u_cred); if (u.u_error) { nfs_rele(gp); nfs_rele(gpp); return (NULL); } /* * Since we set iov_len and uio_resid to MAXPATHLEN, * we can calculate the size of the symbolic link * name by subtracting the remainder of the * translation from MAXPATHLEN. */ sl_len = MAXPATHLEN - auio->uio_resid; /* * The remainder of path was stored in * the upper boundary of ni_dirp, verify it * was not overwritten by the readlink call. */ if (sl_len + rem_len + 1 >= MAXPATHLEN - 1) { u.u_error = ENAMETOOLONG; nfs_rele(gp); nfs_rele(gpp); return (NULL); } /* * Append remainder of path to symbolic link name * returned from server, so we can parse entire * path locally. tcp still points to the beginning * offset where we stored the remainder. */ if (rem_len) ovbcopy(tcp, ndp->ni_dirp + sl_len, rem_len); /* * Append NULL to new path. */ tcp = ndp->ni_dirp + sl_len + rem_len; *tcp = '\0'; /* * Set cp to point at the new path, and check * if absolute path. */ cp = ndp->ni_dirp; nfs_rele(gpp); if (*cp == '/') { nfs_rele(gp); while (*cp == '/') cp++; if ((gp = u.u_rdir) == NULL) gp = rootdir; gref(gp); /* bump ref count */ gfs_lock(gp); ndp->ni_cp = cp; ndp->ni_pdir = gp; gp->g_flag |= GINCOMPLETE; return(gp); } else { continue; } } /* * The lookup has succeeded and we haven't hit a mount * point. Handle the case where this is the last component * of the pathname. */ while (*ncp == '/') ncp++; if (*ncp == '\0') { if (ndp->ni_nameiop & NOCACHE) dnlc_purge_vp(gpp); if (flag == DELETE) { nfs_lock(gp); if (access(gp, GWRITE)) { nfs_unlock(gp); nfs_rele(gp); nfs_rele(gpp); return(NULL); } nfs_unlock(gp); } ndp->ni_cp = cp; if (lockparent) { if (gp != gpp) nfs_lock(gp); ndp->ni_pdir = gp; } else { nfs_rele(gp); } /* * Copy in the last component name in * ni_dent for accounting. */ bcopy(ndp->ni_cp, ndp->ni_dent.d_name, name_len); ndp->ni_dent.d_namlen = name_len; nfs_lock(gpp); gpp->g_flag &= ~GINCOMPLETE; return(gpp); } /* * The lookup has succeeded, but this is not the last * component of the pathname. */ nfs_rele(gp); gp = gpp; cp = ncp; } /* * "Temporary" hack for handling null pathnames, which denote the * starting directory by convention. If the path is null and the * operation is a create or delete we return EISDIR for hysterical * reasons. Note: we can also get here if the pathname resolves * to an NFS mount point. */ if (flag != LOOKUP) { if (gp == gp->g_mp->m_rootgp) { if (flag == CREATE) if ((gp->g_mode & GFMT) == GFDIR) u.u_error = EEXIST; else { nfs_lock(gp); gp->g_flag &= ~GINCOMPLETE; return(gp); } else u.u_error = EBUSY; } else u.u_error = EISDIR; nfs_rele(gp); return(NULL); } nfs_lock(gp); gp->g_flag &= ~GINCOMPLETE; return(gp);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -