Date: Mon, 4 Jun 2007 17:23:58 GMT From: Roman Divacky <rdivacky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 120919 for review Message-ID: <200706041723.l54HNwjT082718@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=120919 Change 120919 by rdivacky@rdivacky_witten on 2007/06/04 17:23:48 o Introduce kern_get_at() function instead of duplicating the same code everywhere o Reimplement kern_symlink and kern_unlink as wrappers around their *at counterparts to avoid code duplication o vrele(dir_vn) in kern_symlink and kern_unlink as necessary The code upto this commit has bugs :( including panics, deadlocks etc. Affected files ... .. //depot/projects/soc2007/rdivacky/linux_at/sys/kern/vfs_syscalls.c#15 edit Differences ... ==== //depot/projects/soc2007/rdivacky/linux_at/sys/kern/vfs_syscalls.c#15 (text+ko) ==== @@ -85,6 +85,7 @@ static int setfflags(struct thread *td, struct vnode *, int); static int setutimes(struct thread *td, struct vnode *, const struct timespec *, int, int); +static int kern_get_at(struct thread *td, int dirfd, struct vnode **dir_vn); static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred, struct thread *td); static int kern_common_open(struct thread *td, int flags, int mode, @@ -984,6 +985,26 @@ return kern_common_open(td, flags, mode, &nd); } +static int +kern_get_at(struct thread *td, int dirfd, struct vnode **dir_vn) +{ + int error; + + if (dirfd == AT_FDCWD) + *dir_vn = NULL; + else { + error = fgetvp(td, dirfd, dir_vn); + if (error) + return (error); + if ((*dir_vn)->v_type != VDIR) { + vrele(*dir_vn); + return (ENOTDIR); + } + } + + return (0); +} + int kern_openat(struct thread *td, char *path, enum uio_seg pathseg, int flags, int mode, int dirfd) @@ -996,22 +1017,14 @@ AUDIT_ARG(mode, mode); /* XXX: audit dirfd */ - if (dirfd == AT_FDCWD) - dir_vn = NULL; - else { - error = fgetvp(td, dirfd, &dir_vn); - if (error) - return (error); - if (dir_vn->v_type != VDIR) { - vrele(dir_vn); - return (ENOTDIR); - } - } + error = kern_get_at(td, dirfd, &dir_vn); + if (error) + return (error); NDINIT_AT(&nd, LOOKUP, FOLLOW | AUDITVNODE1 | MPSAFE, pathseg, path, td, dir_vn); error = kern_common_open(td, flags, mode, &nd); - if (dirfd != AT_FDCWD) + if (dir_vn) vrele(dir_vn); return (error); } @@ -1462,47 +1475,25 @@ int error; struct vnode *pdir_vn, *ldir_vn; - if (olddirfd == AT_FDCWD) - pdir_vn = NULL; - else { - error = fgetvp(td, olddirfd, &pdir_vn); - if (error) - return (error); - if (pdir_vn->v_type != VDIR) { - vrele(pdir_vn); - return (ENOTDIR); - } - } + error = kern_get_at(td, olddirfd, &pdir_vn); + if (error) + return (error); NDINIT_AT(&ndp, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, segflg, path, td, pdir_vn); - if (newdirfd == AT_FDCWD) - ldir_vn = NULL; - else { - error = fgetvp(td, newdirfd, &ldir_vn); - if (error) - return (error); - if (ldir_vn->v_type != VDIR) { - vrele(ldir_vn); - return (ENOTDIR); - } - } + error = kern_get_at(td, newdirfd, &ldir_vn); + if (error) + return (error); NDINIT_AT(&ndl, CREATE, LOCKPARENT | SAVENAME| MPSAFE | AUDITVNODE1, segflg, link, td, ldir_vn); error = kern_common_link(td, &ndp, &ndl); - if (olddirfd != AT_FDCWD) + if (pdir_vn) vrele(pdir_vn); - if (newdirfd != AT_FDCWD) + if (ldir_vn) vrele(ldir_vn); return (error); - - NDINIT(&ndp, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, segflg, path, td); - NDINIT(&ndl, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE2, - segflg, link, td); - - return kern_common_link(td, &ndp, &ndl); } static int @@ -1587,73 +1578,7 @@ int kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg) { - struct mount *mp; - struct vattr vattr; - char *syspath; - int error; - struct nameidata nd; - int vfslocked; - - if (segflg == UIO_SYSSPACE) { - syspath = path; - } else { - syspath = uma_zalloc(namei_zone, M_WAITOK); - if ((error = copyinstr(path, syspath, MAXPATHLEN, NULL)) != 0) - goto out; - } - AUDIT_ARG(text, syspath); -restart: - bwillwrite(); - NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, - segflg, link, td); - if ((error = namei(&nd)) != 0) - goto out; - vfslocked = NDHASGIANT(&nd); - if (nd.ni_vp) { - NDFREE(&nd, NDF_ONLY_PNBUF); - if (nd.ni_vp == nd.ni_dvp) - vrele(nd.ni_dvp); - else - vput(nd.ni_dvp); - vrele(nd.ni_vp); - VFS_UNLOCK_GIANT(vfslocked); - error = EEXIST; - goto out; - } - if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { - NDFREE(&nd, NDF_ONLY_PNBUF); - vput(nd.ni_dvp); - VFS_UNLOCK_GIANT(vfslocked); - if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) - goto out; - goto restart; - } - VATTR_NULL(&vattr); - FILEDESC_SLOCK(td->td_proc->p_fd); - vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask; - FILEDESC_SUNLOCK(td->td_proc->p_fd); -#ifdef MAC - vattr.va_type = VLNK; - error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd, - &vattr); - if (error) - goto out2; -#endif - VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); - error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath); - if (error == 0) - vput(nd.ni_vp); -#ifdef MAC -out2: -#endif - NDFREE(&nd, NDF_ONLY_PNBUF); - vput(nd.ni_dvp); - vn_finished_write(mp); - VFS_UNLOCK_GIANT(vfslocked); -out: - if (segflg != UIO_SYSSPACE) - uma_zfree(namei_zone, syspath); - return (error); + return kern_symlinkat(td, path, link, segflg, AT_FDCWD); } int @@ -1666,7 +1591,7 @@ int error; struct nameidata nd; int vfslocked; - struct vnode *dir_vn; + struct vnode *dir_vn = NULL; if (segflg == UIO_SYSSPACE) { syspath = path; @@ -1677,17 +1602,11 @@ } AUDIT_ARG(text, syspath); restart: - if (dirfd == AT_FDCWD) - dir_vn = NULL; - else { - error = fgetvp(td, dirfd, &dir_vn); - if (error) - return (error); - if (dir_vn->v_type != VDIR) { - vrele(dir_vn); - return (ENOTDIR); - } - } + if (dir_vn) + vrele(dir_vn); + error = kern_get_at(td, dirfd, &dir_vn); + if (error) + return (error); bwillwrite(); NDINIT_AT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, segflg, link, td, dir_vn); @@ -1736,6 +1655,8 @@ vn_finished_write(mp); VFS_UNLOCK_GIANT(vfslocked); out: + if (dir_vn) + vrele(dir_vn); if (segflg != UIO_SYSSPACE) uma_zfree(namei_zone, syspath); return (error); @@ -1817,94 +1738,32 @@ int kern_unlink(struct thread *td, char *path, enum uio_seg pathseg) { - struct mount *mp; - struct vnode *vp; - int error; - struct nameidata nd; - int vfslocked; - -restart: - bwillwrite(); - NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); - if ((error = namei(&nd)) != 0) - return (error == EINVAL ? EPERM : error); - vfslocked = NDHASGIANT(&nd); - vp = nd.ni_vp; - if (vp->v_type == VDIR) - error = EPERM; /* POSIX */ - else { - /* - * The root of a mounted filesystem cannot be deleted. - * - * XXX: can this only be a VDIR case? - */ - if (vp->v_vflag & VV_ROOT) - error = EBUSY; - } - if (error == 0) { - if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { - NDFREE(&nd, NDF_ONLY_PNBUF); - vput(nd.ni_dvp); - if (vp == nd.ni_dvp) - vrele(vp); - else - vput(vp); - VFS_UNLOCK_GIANT(vfslocked); - if ((error = vn_start_write(NULL, &mp, - V_XSLEEP | PCATCH)) != 0) - return (error); - goto restart; - } -#ifdef MAC - error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp, - &nd.ni_cnd); - if (error) - goto out; -#endif - VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); - error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd); -#ifdef MAC -out: -#endif - vn_finished_write(mp); - } - NDFREE(&nd, NDF_ONLY_PNBUF); - vput(nd.ni_dvp); - if (vp == nd.ni_dvp) - vrele(vp); - else - vput(vp); - VFS_UNLOCK_GIANT(vfslocked); - return (error); + return kern_unlinkat(td, path, pathseg, AT_FDCWD); } int kern_unlinkat(struct thread *td, char *path, enum uio_seg pathseg, int dirfd) { struct mount *mp; - struct vnode *vp, *dir_vn; + struct vnode *vp, *dir_vn = NULL; int error; struct nameidata nd; int vfslocked; restart: - if (dirfd == AT_FDCWD) - dir_vn = NULL; - else { - error = fgetvp(td, dirfd, &dir_vn); - if (error) - return (error); - if (dir_vn->v_type != VDIR) { - vrele(dir_vn); - return (ENOTDIR); - } - } + if (dir_vn) + vrele(dir_vn); + error = kern_get_at(td, dirfd, &dir_vn); + if (error) + return (error); bwillwrite(); NDINIT_AT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1, pathseg, path, td, dir_vn); - if ((error = namei(&nd)) != 0) + if ((error = namei(&nd)) != 0) { + if (dir_vn) + vrele(dir_vn); return (error == EINVAL ? EPERM : error); + } vfslocked = NDHASGIANT(&nd); vp = nd.ni_vp; if (vp->v_type == VDIR) @@ -1928,8 +1787,11 @@ vput(vp); VFS_UNLOCK_GIANT(vfslocked); if ((error = vn_start_write(NULL, &mp, - V_XSLEEP | PCATCH)) != 0) + V_XSLEEP | PCATCH)) != 0) { + if (dir_vn) + vrele(dir_vn); return (error); + } goto restart; } #ifdef MAC @@ -1947,6 +1809,8 @@ } NDFREE(&nd, NDF_ONLY_PNBUF); vput(nd.ni_dvp); + if (dir_vn) + vrele(dir_vn); if (vp == nd.ni_dvp) vrele(vp); else @@ -2149,23 +2013,15 @@ struct nameidata nd; struct vnode *dir_vn; - if (dirfd == AT_FDCWD) - dir_vn = NULL; - else { - error = fgetvp(td, dirfd, &dir_vn); - if (error) - return (error); - if (dir_vn->v_type != VDIR) { - vrele(dir_vn); - return (ENOTDIR); - } - } + error = kern_get_at(td, dirfd, &dir_vn); + if (error) + return (error); NDINIT_AT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, pathseg, path, td, dir_vn); error = kern_common_access(td, flags, &nd); - if (dirfd != AT_FDCWD) + if (dir_vn) vrele(dir_vn); return (error); } @@ -2379,23 +2235,15 @@ struct nameidata nd; struct vnode *dir_vn; - if (dirfd == AT_FDCWD) - dir_vn = NULL; - else { - error = fgetvp(td, dirfd, &dir_vn); - if (error) - return (error); - if (dir_vn->v_type != VDIR) { - vrele(dir_vn); - return (ENOTDIR); - } - } + error = kern_get_at(td, dirfd, &dir_vn); + if (error) + return (error); NDINIT_AT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1 | MPSAFE, pathseg, path, td, dir_vn); error = kern_common_stat(td, sbp, &nd); - if (dirfd != AT_FDCWD) + if (dir_vn) vrele(dir_vn); return (error); } @@ -2466,23 +2314,15 @@ struct nameidata nd; struct vnode *dir_vn; - if (dirfd == AT_FDCWD) - dir_vn = NULL; - else { - error = fgetvp(td, dirfd, &dir_vn); - if (error) - return (error); - if (dir_vn->v_type != VDIR) { - vrele(dir_vn); - return (ENOTDIR); - } - } + error = kern_get_at(td, dirfd, &dir_vn); + if (error) + return (error); NDINIT_AT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKSHARED | AUDITVNODE1 | MPSAFE, pathseg, path, td, dir_vn); error = kern_common_lstat(td, sbp, &nd); - if (dirfd != AT_FDCWD) + if (dir_vn) vrele(dir_vn); return (error); } @@ -2677,23 +2517,15 @@ struct nameidata nd; struct vnode *dir_vn; - if (dirfd == AT_FDCWD) - dir_vn = NULL; - else { - error = fgetvp(td, dirfd, &dir_vn); - if (error) - return (error); - if (dir_vn->v_type != VDIR) { - vrele(dir_vn); - return (ENOTDIR); - } - } + error = kern_get_at(td, dirfd, &dir_vn); + if (error) + return (error); NDINIT_AT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, pathseg, path, td, dir_vn); error = kern_common_readlink(td, buf, bufseg, count, &nd); - if (dirfd != AT_FDCWD) + if (dir_vn) vrele(dir_vn); return (error); } @@ -2950,22 +2782,14 @@ struct nameidata nd; struct vnode *dir_vn; - if (dirfd == AT_FDCWD) - dir_vn = NULL; - else { - error = fgetvp(td, dirfd, &dir_vn); - if (error) - return (error); - if (dir_vn->v_type != VDIR) { - vrele(dir_vn); - return (ENOTDIR); - } - } + error = kern_get_at(td, dirfd, &dir_vn); + if (error) + return (error); NDINIT_AT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td, dir_vn); error = kern_common_chmod(td, mode, &nd); - if (dirfd != AT_FDCWD) + if (dir_vn) vrele(dir_vn); return (error); } @@ -3132,22 +2956,14 @@ struct nameidata nd; struct vnode *dir_vn; - if (dirfd == AT_FDCWD) - dir_vn = NULL; - else { - error = fgetvp(td, dirfd, &dir_vn); - if (error) - return (error); - if (dir_vn->v_type != VDIR) { - vrele(dir_vn); - return (ENOTDIR); - } - } + error = kern_get_at(td, dirfd, &dir_vn); + if (error) + return (error); NDINIT_AT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td, dir_vn); error = kern_common_chown(td, uid, gid, &nd); - if (dirfd != AT_FDCWD) + if (dir_vn) vrele(dir_vn); return (error); } @@ -3211,22 +3027,14 @@ struct nameidata nd; struct vnode *dir_vn; - if (dirfd == AT_FDCWD) - dir_vn = NULL; - else { - error = fgetvp(td, dirfd, &dir_vn); - if (error) - return (error); - if (dir_vn->v_type != VDIR) { - vrele(dir_vn); - return (ENOTDIR); - } - } + error = kern_get_at(td, dirfd, &dir_vn); + if (error) + return (error); NDINIT_AT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td, dir_vn); error = kern_common_chown(td, uid, gid, &nd); - if (dirfd != AT_FDCWD) + if (dir_vn) vrele(dir_vn); return (error); @@ -3978,69 +3786,7 @@ int kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg) { - struct mount *mp; - struct vnode *vp; - int error; - struct nameidata nd; - int vfslocked; - -restart: - bwillwrite(); - NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); - if ((error = namei(&nd)) != 0) - return (error); - vfslocked = NDHASGIANT(&nd); - vp = nd.ni_vp; - if (vp->v_type != VDIR) { - error = ENOTDIR; - goto out; - } - /* - * No rmdir "." please. - */ - if (nd.ni_dvp == vp) { - error = EINVAL; - goto out; - } - /* - * The root of a mounted filesystem cannot be deleted. - */ - if (vp->v_vflag & VV_ROOT) { - error = EBUSY; - goto out; - } -#ifdef MAC - error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp, - &nd.ni_cnd); - if (error) - goto out; -#endif - if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { - NDFREE(&nd, NDF_ONLY_PNBUF); - vput(vp); - if (nd.ni_dvp == vp) - vrele(nd.ni_dvp); - else - vput(nd.ni_dvp); - VFS_UNLOCK_GIANT(vfslocked); - if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) - return (error); - goto restart; - } - VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); - VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); - error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); - vn_finished_write(mp); -out: - NDFREE(&nd, NDF_ONLY_PNBUF); - vput(vp); - if (nd.ni_dvp == vp) - vrele(nd.ni_dvp); - else - vput(nd.ni_dvp); - VFS_UNLOCK_GIANT(vfslocked); - return (error); + return kern_rmdirat(td, path, pathseg, AT_FDCWD); } int @@ -4053,17 +3799,9 @@ int vfslocked; restart: - if (dirfd == AT_FDCWD) - dir_vn = NULL; - else { - error = fgetvp(td, dirfd, &dir_vn); - if (error) - return (error); - if (dir_vn->v_type != VDIR) { - vrele(dir_vn); - return (ENOTDIR); - } - } + error = kern_get_at(td, dirfd, &dir_vn); + if (error) + return (error); bwillwrite(); NDINIT_AT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1, pathseg, path, td, dir_vn);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200706041723.l54HNwjT082718>