X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/blobdiff_plain/217396181c21908d5ec1a8581504dda822dbe7f1..1c843a13b38e87670f8169e750b2406c3eb6e68e:/sys/vfs/ntfs/ntfs_vnops.c diff --git a/sys/vfs/ntfs/ntfs_vnops.c b/sys/vfs/ntfs/ntfs_vnops.c index 0bfd87dd73..ff64f61d76 100644 --- a/sys/vfs/ntfs/ntfs_vnops.c +++ b/sys/vfs/ntfs/ntfs_vnops.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/ntfs/ntfs_vnops.c,v 1.9.2.4 2002/08/06 19:35:18 semenu Exp $ - * $DragonFly: src/sys/vfs/ntfs/ntfs_vnops.c,v 1.16 2004/09/30 19:00:11 dillon Exp $ + * $DragonFly: src/sys/vfs/ntfs/ntfs_vnops.c,v 1.29 2006/04/07 06:38:33 dillon Exp $ * */ @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -91,7 +92,7 @@ static int ntfs_access (struct vop_access_args *ap); static int ntfs_open (struct vop_open_args *ap); static int ntfs_close (struct vop_close_args *ap); static int ntfs_readdir (struct vop_readdir_args *ap); -static int ntfs_lookup (struct vop_lookup_args *ap); +static int ntfs_lookup (struct vop_old_lookup_args *ap); static int ntfs_bmap (struct vop_bmap_args *ap); #if defined(__DragonFly__) static int ntfs_getpages (struct vop_getpages_args *ap); @@ -123,8 +124,8 @@ ntfs_putpages(struct vop_putpages_args *ap) /* * This is a noop, simply returning what one has been given. * - * ntfs_bmap(struct vnode *a_vp, daddr_t a_bn, struct vnode **a_vpp, - * daddr_t *a_bnp, int *a_runp, int *a_runb) + * ntfs_bmap(struct vnode *a_vp, off_t a_loffset, struct vnode **a_vpp, + * daddr_t *a_doffsetp, int *a_runp, int *a_runb) */ int ntfs_bmap(struct vop_bmap_args *ap) @@ -132,8 +133,8 @@ ntfs_bmap(struct vop_bmap_args *ap) dprintf(("ntfs_bmap: vn: %p, blk: %d\n", ap->a_vp,(u_int32_t)ap->a_bn)); if (ap->a_vpp != NULL) *ap->a_vpp = ap->a_vp; - if (ap->a_bnp != NULL) - *ap->a_bnp = ap->a_bn; + if (ap->a_doffsetp != NULL) + *ap->a_doffsetp = ap->a_loffset; if (ap->a_runp != NULL) *ap->a_runp = 0; #if !defined(__NetBSD__) @@ -179,7 +180,7 @@ ntfs_read(struct vop_read_args *ap) toread = min(off + resid, ntfs_cntob(1)); - error = bread(vp, cn, ntfs_cntob(1), &bp); + error = bread(vp, ntfs_cntodoff(cn), ntfs_cntob(1), &bp); if (error) { brelse(bp); break; @@ -270,9 +271,8 @@ ntfs_inactive(struct vop_inactive_args *ap) if (ntfs_prtactive && vp->v_usecount != 0) vprint("ntfs_inactive: pushing active", vp); - VOP__UNLOCK(vp, 0, ap->a_td); - - /* XXX since we don't support any filesystem changes + /* + * XXX since we don't support any filesystem changes * right now, nothing more needs to be done */ return (0); @@ -299,9 +299,6 @@ ntfs_reclaim(struct vop_reclaim_args *ap) if ((error = ntfs_ntget(ip)) != 0) return (error); - /* Purge old data structures associated with the inode. */ - cache_purge(vp); - ntfs_frele(fp); ntfs_ntput(ip); vp->v_data = NULL; @@ -322,27 +319,21 @@ ntfs_print(struct vop_print_args *ap) * Calculate the logical to physical mapping if not done already, * then call the device strategy routine. * - * ntfs_strategy(struct buf *a_bp) + * ntfs_strategy(struct vnode *a_vp, struct bio *a_bio) */ int ntfs_strategy(struct vop_strategy_args *ap) { - struct buf *bp = ap->a_bp; - struct vnode *vp = bp->b_vp; + struct bio *bio = ap->a_bio; + struct buf *bp = bio->bio_buf; + struct vnode *vp = ap->a_vp; struct fnode *fp = VTOF(vp); struct ntnode *ip = FTONT(fp); struct ntfsmount *ntmp = ip->i_mp; int error; -#ifdef __DragonFly__ - dprintf(("ntfs_strategy: offset: %d, blkno: %d, lblkno: %d\n", - (u_int32_t)bp->b_offset,(u_int32_t)bp->b_blkno, - (u_int32_t)bp->b_lblkno)); -#else - dprintf(("ntfs_strategy: blkno: %d, lblkno: %d\n", - (u_int32_t)bp->b_blkno, - (u_int32_t)bp->b_lblkno)); -#endif + dprintf(("ntfs_strategy: loffset: %lld, doffset: %lld\n", + bp->b_loffset, bio->bio_offset)); dprintf(("strategy: bcount: %d flags: 0x%lx\n", (u_int32_t)bp->b_bcount,bp->b_flags)); @@ -350,17 +341,17 @@ ntfs_strategy(struct vop_strategy_args *ap) if (bp->b_flags & B_READ) { u_int32_t toread; - if (ntfs_cntob(bp->b_blkno) >= fp->f_size) { + if (bio->bio_offset >= fp->f_size) { clrbuf(bp); error = 0; } else { toread = min(bp->b_bcount, - fp->f_size-ntfs_cntob(bp->b_blkno)); + fp->f_size - bio->bio_offset); dprintf(("ntfs_strategy: toread: %d, fsize: %d\n", toread,(u_int32_t)fp->f_size)); error = ntfs_readattr(ntmp, ip, fp->f_attrtype, - fp->f_attrname, ntfs_cntob(bp->b_blkno), + fp->f_attrname, bio->bio_offset, toread, bp->b_data, NULL); if (error) { @@ -375,18 +366,18 @@ ntfs_strategy(struct vop_strategy_args *ap) size_t tmp; u_int32_t towrite; - if (ntfs_cntob(bp->b_blkno) + bp->b_bcount >= fp->f_size) { + if (bio->bio_offset + bp->b_bcount >= fp->f_size) { printf("ntfs_strategy: CAN'T EXTEND FILE\n"); bp->b_error = error = EFBIG; bp->b_flags |= B_ERROR; } else { towrite = min(bp->b_bcount, - fp->f_size-ntfs_cntob(bp->b_blkno)); + fp->f_size - bio->bio_offset); dprintf(("ntfs_strategy: towrite: %d, fsize: %d\n", towrite,(u_int32_t)fp->f_size)); error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype, - fp->f_attrname, ntfs_cntob(bp->b_blkno),towrite, + fp->f_attrname, bio->bio_offset,towrite, bp->b_data, &tmp, NULL); if (error) { @@ -396,7 +387,7 @@ ntfs_strategy(struct vop_strategy_args *ap) } } } - biodone(bp); + biodone(bio); return (error); } @@ -528,18 +519,7 @@ ntfs_access(struct vop_access_args *ap) static int ntfs_open(struct vop_open_args *ap) { -#if NTFS_DEBUG - struct vnode *vp = ap->a_vp; - struct ntnode *ip = VTONT(vp); - - printf("ntfs_open: %d\n",ip->i_number); -#endif - - /* - * Files marked append-only must be opened for appending. - */ - - return (0); + return (vop_stdopen(ap)); } /* @@ -561,7 +541,7 @@ ntfs_close(struct vop_close_args *ap) printf("ntfs_close: %d\n",ip->i_number); #endif - return (0); + return (vop_stdclose(ap)); } /* @@ -577,49 +557,64 @@ ntfs_readdir(struct vop_readdir_args *ap) struct uio *uio = ap->a_uio; struct ntfsmount *ntmp = ip->i_mp; int i, error = 0; - u_int32_t faked = 0, num; + u_int32_t faked = 0, num, off; int ncookies = 0; - struct dirent cde; - off_t off; + char convname[NTFS_MAXFILENAME + 1]; dprintf(("ntfs_readdir %d off: %d resid: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid)); - off = uio->uio_offset; + if (uio->uio_offset < 0 || uio->uio_offset > INT_MAX) + return (EINVAL); - /* Simulate . in every dir except ROOT */ - if( ip->i_number != NTFS_ROOTINO ) { - struct dirent dot = { NTFS_ROOTINO, - sizeof(struct dirent), DT_DIR, 1, "." }; + /* + * uio->uio_offset carries the number of the entry + * where we should start returning dirents. + * + * We fake up "." if we're not reading the FS root + * and we always fake up "..". + * + * off contains the entry we are starting at, + * num increments while we are reading. + */ - if( uio->uio_offset < sizeof(struct dirent) ) { - dot.d_fileno = ip->i_number; - error = uiomove((char *)&dot,sizeof(struct dirent),uio); - if(error) - return (error); + off = num = uio->uio_offset; + faked = (ip->i_number == NTFS_ROOTINO) ? 1 : 2; - ncookies ++; - } + /* Simulate . in every dir except ROOT */ + if (ip->i_number != NTFS_ROOTINO && num == 0) { + if (vop_write_dirent(&error, uio, ip->i_number, + DT_DIR, 1, ".")) + return (0); + if (error) + return (error); + + num++; + ncookies++; } /* Simulate .. in every dir including ROOT */ - if( uio->uio_offset < 2 * sizeof(struct dirent) ) { - struct dirent dotdot = { NTFS_ROOTINO, - sizeof(struct dirent), DT_DIR, 2, ".." }; - - error = uiomove((char *)&dotdot,sizeof(struct dirent),uio); + if (num == faked - 1) { + /* XXX NTFS_ROOTINO seems to be wrong here */ + if (vop_write_dirent(&error, uio, NTFS_ROOTINO, + DT_DIR, 2, "..")) + goto readdone; if(error) return (error); - ncookies ++; + num++; + ncookies++; } - faked = (ip->i_number == NTFS_ROOTINO) ? 1 : 2; - num = uio->uio_offset / sizeof(struct dirent) - faked; - - while( uio->uio_resid >= sizeof(struct dirent) ) { + for (;;) { struct attr_indexentry *iep; - error = ntfs_ntreaddir(ntmp, fp, num, &iep); + /* + * num is the number of the entry we will return, + * but ntfs_ntreaddir takes the entry number of the + * ntfs directory listing, so subtract the faked + * . and .. entries. + */ + error = ntfs_ntreaddir(ntmp, fp, num - faked, &iep); if(error) return (error); @@ -627,26 +622,28 @@ ntfs_readdir(struct vop_readdir_args *ap) if( NULL == iep ) break; - for(; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent)); + for (; !(iep->ie_flag & NTFS_IEFLAG_LAST); iep = NTFS_NEXTREC(iep, struct attr_indexentry *)) { if(!ntfs_isnamepermitted(ntmp,iep)) continue; - for(i=0; iie_fnamelen; i++) { - cde.d_name[i] = NTFS_U28(iep->ie_fname[i]); - } - cde.d_name[i] = '\0'; - dprintf(("ntfs_readdir: elem: %d, fname:[%s] type: %d, flag: %d, ", - num, cde.d_name, iep->ie_fnametype, - iep->ie_flag)); - cde.d_namlen = iep->ie_fnamelen; - cde.d_fileno = iep->ie_number; - cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG; - cde.d_reclen = sizeof(struct dirent); - dprintf(("%s\n", (cde.d_type == DT_DIR) ? "dir":"reg")); - - error = uiomove((char *)&cde, sizeof(struct dirent), uio); + for (i=0; i < iep->ie_fnamelen; i++) + convname[i] = NTFS_U28(iep->ie_fname[i]); + convname[i] = '\0'; + + if (vop_write_dirent(&error, uio, iep->ie_number, + (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG, + iep->ie_fnamelen, convname)) + goto readdone; + + dprintf(("ntfs_readdir: elem: %d, fname:[%s] type: %d, " + "flag: %d, %s\n", + ncookies, convname, iep->ie_fnametype, + iep->ie_flag, + (iep->ie_fflag & NTFS_FFLAG_DIR) ? + "dir" : "reg")); + if(error) return (error); @@ -655,14 +652,15 @@ ntfs_readdir(struct vop_readdir_args *ap) } } +readdone: + uio->uio_offset = num; + dprintf(("ntfs_readdir: %d entries (%d bytes) read\n", ncookies,(u_int)(uio->uio_offset - off))); dprintf(("ntfs_readdir: off: %d resid: %d\n", (u_int32_t)uio->uio_offset,uio->uio_resid)); if (!error && ap->a_ncookies != NULL) { - struct dirent* dpStart; - struct dirent* dp; #if defined(__DragonFly__) u_long *cookies; u_long *cookiep; @@ -674,9 +672,6 @@ ntfs_readdir(struct vop_readdir_args *ap) ddprintf(("ntfs_readdir: %d cookies\n",ncookies)); if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) panic("ntfs_readdir: unexpected uio from NFS server"); - dpStart = (struct dirent *) - ((caddr_t)uio->uio_iov->iov_base - - (uio->uio_offset - off)); #if defined(__DragonFly__) MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP, M_WAITOK); @@ -684,12 +679,10 @@ ntfs_readdir(struct vop_readdir_args *ap) MALLOC(cookies, off_t *, ncookies * sizeof(off_t), M_TEMP, M_WAITOK); #endif - for (dp = dpStart, cookiep = cookies, i=0; - i < ncookies; - dp = (struct dirent *)((caddr_t) dp + dp->d_reclen), i++) { - off += dp->d_reclen; - *cookiep++ = (u_int) off; - } + cookiep = cookies; + while (off < num) + *cookiep++ = ++off; + *ap->a_ncookies = ncookies; *ap->a_cookies = cookies; } @@ -705,13 +698,12 @@ ntfs_readdir(struct vop_readdir_args *ap) * struct componentname *a_cnp) */ int -ntfs_lookup(struct vop_lookup_args *ap) +ntfs_lookup(struct vop_old_lookup_args *ap) { struct vnode *dvp = ap->a_dvp; struct ntnode *dip = VTONT(dvp); struct ntfsmount *ntmp = dip->i_mp; struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; int error; int lockparent = cnp->cn_flags & CNP_LOCKPARENT; #if NTFS_DEBUG @@ -721,29 +713,9 @@ ntfs_lookup(struct vop_lookup_args *ap) (int)cnp->cn_namelen, cnp->cn_nameptr, cnp->cn_namelen, dip->i_number, lockparent, wantparent)); - error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_td); - if(error) - return (error); - - if ((cnp->cn_flags & CNP_ISLASTCN) && - (dvp->v_mount->mnt_flag & MNT_RDONLY) && - (cnp->cn_nameiop == NAMEI_DELETE || cnp->cn_nameiop == NAMEI_RENAME)) - return (EROFS); - -#ifdef __NetBSD__ - /* - * We now have a segment name to search for, and a directory - * to search. - * - * Before tediously performing a linear scan of the directory, - * check the name cache to see if the directory/name pair - * we are looking for is known already. - */ - if ((error = cache_lookup(ap->a_dvp, ap->a_vpp, cnp)) >= 0) - return (error); -#endif + *ap->a_vpp = NULL; - if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { + if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { dprintf(("ntfs_lookup: faking . directory in %d\n", dip->i_number)); @@ -774,10 +746,11 @@ ntfs_lookup(struct vop_lookup_args *ap) return (error); } - if (lockparent && (cnp->cn_flags & CNP_ISLASTCN)) { + if (lockparent) { error = VN_LOCK(dvp, LK_EXCLUSIVE, cnp->cn_td); if (error) { - vput( *(ap->a_vpp) ); + vput(*ap->a_vpp); + *ap->a_vpp = NULL; return (error); } cnp->cn_flags &= ~CNP_PDIRUNLOCK; @@ -792,13 +765,9 @@ ntfs_lookup(struct vop_lookup_args *ap) dprintf(("ntfs_lookup: found ino: %d\n", VTONT(*ap->a_vpp)->i_number)); - if(!lockparent || !(cnp->cn_flags & CNP_ISLASTCN)) + if (!lockparent) VOP__UNLOCK(dvp, 0, cnp->cn_td); } - - if (cnp->cn_flags & CNP_MAKEENTRY) - cache_enter(dvp, *ap->a_vpp, cnp); - return (error); } @@ -867,31 +836,30 @@ ntfs_pathconf(void *v) struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = { { &vop_default_desc, vop_defaultop }, - { &vop_getattr_desc, (void *)ntfs_getattr }, - { &vop_inactive_desc, (void *)ntfs_inactive }, - { &vop_reclaim_desc, (void *)ntfs_reclaim }, - { &vop_print_desc, (void *)ntfs_print }, - { &vop_pathconf_desc, (void *)ntfs_pathconf }, - - { &vop_islocked_desc, (void *)vop_stdislocked }, - { &vop_unlock_desc, (void *)vop_stdunlock }, - { &vop_lock_desc, (void *)vop_stdlock }, - { &vop_cachedlookup_desc,(void *)ntfs_lookup }, - { &vop_lookup_desc, (void *)vfs_cache_lookup }, - - { &vop_access_desc, (void *)ntfs_access }, - { &vop_close_desc, (void *)ntfs_close }, - { &vop_open_desc, (void *)ntfs_open }, - { &vop_readdir_desc, (void *)ntfs_readdir }, - { &vop_fsync_desc, (void *)ntfs_fsync }, - - { &vop_bmap_desc, (void *)ntfs_bmap }, - { &vop_getpages_desc, (void *)ntfs_getpages }, - { &vop_putpages_desc, (void *)ntfs_putpages }, - { &vop_strategy_desc, (void *)ntfs_strategy }, - { &vop_bwrite_desc, (void *)vop_stdbwrite }, - { &vop_read_desc, (void *)ntfs_read }, - { &vop_write_desc, (void *)ntfs_write }, + { &vop_getattr_desc, (vnodeopv_entry_t)ntfs_getattr }, + { &vop_inactive_desc, (vnodeopv_entry_t)ntfs_inactive }, + { &vop_reclaim_desc, (vnodeopv_entry_t)ntfs_reclaim }, + { &vop_print_desc, (vnodeopv_entry_t)ntfs_print }, + { &vop_pathconf_desc, (vnodeopv_entry_t)ntfs_pathconf }, + + { &vop_islocked_desc, (vnodeopv_entry_t)vop_stdislocked }, + { &vop_unlock_desc, (vnodeopv_entry_t)vop_stdunlock }, + { &vop_lock_desc, (vnodeopv_entry_t)vop_stdlock }, + { &vop_old_lookup_desc, (vnodeopv_entry_t)ntfs_lookup }, + + { &vop_access_desc, (vnodeopv_entry_t)ntfs_access }, + { &vop_close_desc, (vnodeopv_entry_t)ntfs_close }, + { &vop_open_desc, (vnodeopv_entry_t)ntfs_open }, + { &vop_readdir_desc, (vnodeopv_entry_t)ntfs_readdir }, + { &vop_fsync_desc, (vnodeopv_entry_t)ntfs_fsync }, + + { &vop_bmap_desc, (vnodeopv_entry_t)ntfs_bmap }, + { &vop_getpages_desc, (vnodeopv_entry_t)ntfs_getpages }, + { &vop_putpages_desc, (vnodeopv_entry_t)ntfs_putpages }, + { &vop_strategy_desc, (vnodeopv_entry_t)ntfs_strategy }, + { &vop_bwrite_desc, (vnodeopv_entry_t)vop_stdbwrite }, + { &vop_read_desc, (vnodeopv_entry_t)ntfs_read }, + { &vop_write_desc, (vnodeopv_entry_t)ntfs_write }, { NULL, NULL } };