diff options
author | semenu <semenu@FreeBSD.org> | 1999-02-19 12:31:02 +0000 |
---|---|---|
committer | semenu <semenu@FreeBSD.org> | 1999-02-19 12:31:02 +0000 |
commit | 05d36e7aeab6b1f528acb24b6610b4982335afbe (patch) | |
tree | b64fa05911edc2837553bd88e10f4030c470fe1b /sys | |
parent | eb7abf9254a7f2c95d72411f292d032a9a8f14a1 (diff) | |
download | FreeBSD-src-05d36e7aeab6b1f528acb24b6610b4982335afbe.zip FreeBSD-src-05d36e7aeab6b1f528acb24b6610b4982335afbe.tar.gz |
Added limited write ability. Now we can use some kind
of files for swap holders. See mount_ntfs..8 for details.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/fs/ntfs/ntfs.h | 22 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_compr.c | 4 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_compr.h | 4 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_ihash.c | 80 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_ihash.h | 33 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_inode.h | 62 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_subr.c | 621 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_subr.h | 39 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_vfsops.c | 141 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_vfsops.h | 33 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_vnops.c | 387 | ||||
-rw-r--r-- | sys/ntfs/ntfs.h | 22 | ||||
-rw-r--r-- | sys/ntfs/ntfs_compr.c | 4 | ||||
-rw-r--r-- | sys/ntfs/ntfs_compr.h | 4 | ||||
-rw-r--r-- | sys/ntfs/ntfs_extern.h | 2 | ||||
-rw-r--r-- | sys/ntfs/ntfs_ihash.c | 80 | ||||
-rw-r--r-- | sys/ntfs/ntfs_ihash.h | 33 | ||||
-rw-r--r-- | sys/ntfs/ntfs_inode.h | 62 | ||||
-rw-r--r-- | sys/ntfs/ntfs_subr.c | 621 | ||||
-rw-r--r-- | sys/ntfs/ntfs_subr.h | 39 | ||||
-rw-r--r-- | sys/ntfs/ntfs_vfsops.c | 141 | ||||
-rw-r--r-- | sys/ntfs/ntfs_vfsops.h | 33 | ||||
-rw-r--r-- | sys/ntfs/ntfs_vnops.c | 387 |
23 files changed, 1750 insertions, 1104 deletions
diff --git a/sys/fs/ntfs/ntfs.h b/sys/fs/ntfs/ntfs.h index 84bbc77..6552c99 100644 --- a/sys/fs/ntfs/ntfs.h +++ b/sys/fs/ntfs/ntfs.h @@ -182,6 +182,7 @@ struct attr_indexentry { }; #define NTFS_FILEMAGIC (u_int32_t)(0x454C4946) +#define NTFS_FRFLAG_DIR 0x0002 struct filerec { struct fixuphdr fr_fixup; u_int8_t reserved[8]; @@ -195,10 +196,11 @@ struct filerec { u_int16_t fr_attrnum; /* maximum attr number + 1 ??? */ }; +#define NTFS_ATTRNAME_MAXLEN 0x40 #define NTFS_ADFLAG_NONRES 0x0080 /* Attrib can be non resident */ #define NTFS_ADFLAG_INDEX 0x0002 /* Attrib can be indexed */ struct attrdef { - wchar ad_name[0x40]; + wchar ad_name[NTFS_ATTRNAME_MAXLEN]; u_int32_t ad_type; u_int32_t reserved1[2]; u_int32_t ad_flag; @@ -261,8 +263,10 @@ struct ntfsmount { /* Convert mount ptr to ntfsmount ptr. */ #define VFSTONTFS(mp) ((struct ntfsmount *)((mp)->mnt_data)) -#define VTONT(v) ((struct ntnode *)((struct vnode *)(v)->v_data)) -#define NTTOV(i) (i->i_vnode) +#define VTONT(v) FTONT(VTOF(v)) +#define VTOF(v) ((struct fnode *)((v)->v_data)) +#define FTOV(f) ((f)->f_vp) +#define FTONT(f) ((f)->f_ip) #define ntfs_cntobn(cn) (daddr_t)((cn) * (ntmp->ntm_spc)) #define ntfs_cntob(cn) (off_t)((cn) * (ntmp)->ntm_spc * (ntmp)->ntm_bps) #define ntfs_btocn(off) (cn_t)((off) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps)) @@ -274,9 +278,10 @@ struct ntfsmount { #if __FreeBSD_version >= 300000 MALLOC_DECLARE(M_NTFSMNT); -MALLOC_DECLARE(M_NTFSNODE); +MALLOC_DECLARE(M_NTFSNTNODE); +MALLOC_DECLARE(M_NTFSFNODE); MALLOC_DECLARE(M_NTFSDIR); -MALLOC_DECLARE(M_NTFSIHASH); +MALLOC_DECLARE(M_NTFSNTHASH); #endif #if defined(NTFS_DEBUG) @@ -292,10 +297,3 @@ MALLOC_DECLARE(M_NTFSIHASH); #endif extern vop_t **ntfs_vnodeop_p; -struct ntnode; - -void ntfs_ihashinit __P((void)); -struct vnode *ntfs_ihashlookup __P((dev_t, ino_t)); -struct vnode *ntfs_ihashget __P((dev_t, ino_t)); -void ntfs_ihashins __P((struct ntnode *)); -void ntfs_ihashrem __P((register struct ntnode *)); diff --git a/sys/fs/ntfs/ntfs_compr.c b/sys/fs/ntfs/ntfs_compr.c index a096ba6..31558de 100644 --- a/sys/fs/ntfs/ntfs_compr.c +++ b/sys/fs/ntfs/ntfs_compr.c @@ -48,7 +48,7 @@ int ntfs_uncompblock( u_int8_t * buf, - const u_int8_t * cbuf) + u_int8_t * cbuf) { u_int32_t ctag; int len, dshift, lmask; @@ -100,7 +100,7 @@ int ntfs_uncompunit( struct ntfsmount * ntmp, u_int8_t * uup, - const u_int8_t * cup) + u_int8_t * cup) { int i; int off = 0; diff --git a/sys/fs/ntfs/ntfs_compr.h b/sys/fs/ntfs/ntfs_compr.h index b2637c5..ee37e97 100644 --- a/sys/fs/ntfs/ntfs_compr.h +++ b/sys/fs/ntfs/ntfs_compr.h @@ -29,5 +29,5 @@ #define NTFS_COMPBLOCK_SIZE 0x1000 #define NTFS_COMPUNIT_CL 16 -int ntfs_uncompblock(u_int8_t *, const u_int8_t *); -int ntfs_uncompunit(struct ntfsmount *, u_int8_t *, const u_int8_t *); +int ntfs_uncompblock(u_int8_t *, u_int8_t *); +int ntfs_uncompunit(struct ntfsmount *, u_int8_t *, u_int8_t *); diff --git a/sys/fs/ntfs/ntfs_ihash.c b/sys/fs/ntfs/ntfs_ihash.c index 837f478..e75f085 100644 --- a/sys/fs/ntfs/ntfs_ihash.c +++ b/sys/fs/ntfs/ntfs_ihash.c @@ -44,107 +44,75 @@ #include <ntfs/ntfs.h> #include <ntfs/ntfs_inode.h> +#include <ntfs/ntfs_ihash.h> -MALLOC_DEFINE(M_NTFSIHASH, "NTFS ihash", "NTFS Inode hash tables"); +MALLOC_DEFINE(M_NTFSNTHASH, "NTFS nthash", "NTFS ntnode hash tables"); /* * Structures associated with inode cacheing. */ -static LIST_HEAD(ihashhead, ntnode) *ntfs_ihashtbl; -static u_long ntfs_ihash; /* size of hash table - 1 */ -#define NTNOHASH(device, inum) (&ntfs_ihashtbl[((device) + (inum)) & ntfs_ihash]) -static struct simplelock ntfs_ihash_slock; +static LIST_HEAD(nthashhead, ntnode) *ntfs_nthashtbl; +static u_long ntfs_nthash; /* size of hash table - 1 */ +#define NTNOHASH(device, inum) (&ntfs_nthashtbl[((device) + (inum)) & ntfs_nthash]) +#ifndef NULL_SIMPLELOCKS +static struct simplelock ntfs_nthash_slock; +#endif /* * Initialize inode hash table. */ void -ntfs_ihashinit() +ntfs_nthashinit() { - ntfs_ihashtbl = hashinit(desiredvnodes, M_NTFSIHASH, &ntfs_ihash); - simple_lock_init(&ntfs_ihash_slock); + ntfs_nthashtbl = hashinit(desiredvnodes, M_NTFSNTHASH, &ntfs_nthash); + simple_lock_init(&ntfs_nthash_slock); } /* * Use the device/inum pair to find the incore inode, and return a pointer * to it. If it is in core, return it, even if it is locked. */ -struct vnode * -ntfs_ihashlookup(dev, inum) +struct ntnode * +ntfs_nthashlookup(dev, inum) dev_t dev; ino_t inum; { struct ntnode *ip; - simple_lock(&ntfs_ihash_slock); + simple_lock(&ntfs_nthash_slock); for (ip = NTNOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) if (inum == ip->i_number && dev == ip->i_dev) break; - simple_unlock(&ntfs_ihash_slock); + simple_unlock(&ntfs_nthash_slock); - if (ip) - return (NTTOV(ip)); - return (NULLVP); + return (ip); } /* - * Use the device/inum pair to find the incore inode, and return a pointer - * to it. If it is in core, but locked, wait for it. - */ -struct vnode * -ntfs_ihashget(dev, inum) - dev_t dev; - ino_t inum; -{ - struct proc *p = curproc; /* XXX */ - struct ntnode *ip; - struct vnode *vp; - -loop: - simple_lock(&ntfs_ihash_slock); - for (ip = NTNOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) { - if (inum == ip->i_number && dev == ip->i_dev) { - vp = NTTOV(ip); - simple_lock(&vp->v_interlock); - simple_unlock(&ntfs_ihash_slock); - if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) - goto loop; - return (vp); - } - } - simple_unlock(&ntfs_ihash_slock); - return (NULL); -} - -/* - * Insert the inode into the hash table, and return it locked. + * Insert the ntnode into the hash table. */ void -ntfs_ihashins(ip) +ntfs_nthashins(ip) struct ntnode *ip; { - struct proc *p = curproc; /* XXX */ - struct ihashhead *ipp; - - /* lock the inode, then put it on the appropriate hash list */ - lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0, p); + struct nthashhead *ipp; - simple_lock(&ntfs_ihash_slock); + simple_lock(&ntfs_nthash_slock); ipp = NTNOHASH(ip->i_dev, ip->i_number); LIST_INSERT_HEAD(ipp, ip, i_hash); ip->i_flag |= IN_HASHED; - simple_unlock(&ntfs_ihash_slock); + simple_unlock(&ntfs_nthash_slock); } /* * Remove the inode from the hash table. */ void -ntfs_ihashrem(ip) +ntfs_nthashrem(ip) struct ntnode *ip; { - simple_lock(&ntfs_ihash_slock); + simple_lock(&ntfs_nthash_slock); if (ip->i_flag & IN_HASHED) { ip->i_flag &= ~IN_HASHED; LIST_REMOVE(ip, i_hash); @@ -153,5 +121,5 @@ ntfs_ihashrem(ip) ip->i_hash.le_prev = NULL; #endif } - simple_unlock(&ntfs_ihash_slock); + simple_unlock(&ntfs_nthash_slock); } diff --git a/sys/fs/ntfs/ntfs_ihash.h b/sys/fs/ntfs/ntfs_ihash.h new file mode 100644 index 0000000..117bf7b --- /dev/null +++ b/sys/fs/ntfs/ntfs_ihash.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 1998, 1999 Semen Ustimenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: ntfs.h,v 1.9 1999/02/02 01:54:54 semen Exp $ + */ + +void ntfs_nthashinit __P((void)); +struct ntnode *ntfs_nthashlookup __P((dev_t, ino_t)); +struct ntnode *ntfs_nthashget __P((dev_t, ino_t)); +void ntfs_nthashins __P((struct ntnode *)); +void ntfs_nthashrem __P((register struct ntnode *)); diff --git a/sys/fs/ntfs/ntfs_inode.h b/sys/fs/ntfs/ntfs_inode.h index 803ff86..2e6fb78 100644 --- a/sys/fs/ntfs/ntfs_inode.h +++ b/sys/fs/ntfs/ntfs_inode.h @@ -53,48 +53,58 @@ #define IN_LOADED 0x8000 /* ntvattrs loaded */ #define IN_PRELOADED 0x4000 /* loaded from directory entry */ -#define IN_AATTRNAME 0x2000 /* spaec allocated for i_defattrname */ struct ntnode { -#if __FreeBSD_version >= 300000 - struct lock i_lock; /* Must be first */ -#endif LIST_ENTRY(ntnode) i_hash; struct ntnode *i_next; struct ntnode **i_prev; - struct vnode *i_vnode; - struct vnode *i_devvp; struct ntfsmount *i_mp; - enum vtype i_type; - dev_t i_dev; ino_t i_number; + dev_t i_dev; u_int32_t i_flag; + int i_usecount; + + LIST_HEAD(,fnode) i_fnlist; + struct ntvattr *i_vattrp; /* ntvattrs list */ long i_nlink; /* MFR */ ino_t i_mainrec; /* MFR */ u_int32_t i_frflag; /* MFR */ - ntfs_times_t i_times; /* $NAME/dirinfo */ - ino_t i_pnumber; /* $NAME/dirinfo */ - u_int32_t i_fflag; /* $NAME/dirinfo */ - u_int64_t i_size; /* defattr/dirinfo: */ - u_int64_t i_allocated; /* defattr/dirinfo */ - - u_int32_t i_lastdattr; - u_int32_t i_lastdblnum; - u_int32_t i_lastdoff; - u_int32_t i_lastdnum; - caddr_t i_dirblbuf; - u_int32_t i_dirblsz; uid_t i_uid; gid_t i_gid; mode_t i_mode; +}; + +#define FN_PRELOADED 0x0001 +#define FN_DEFAULT 0x0002 +#define FN_AATTRNAME 0x0004 /* space allocated for f_attrname */ +struct fnode { + struct lock f_lock; /* Must be first */ + + LIST_ENTRY(fnode) f_fnlist; + struct vnode *f_vp; /* Associatied vnode */ + struct ntnode *f_ip; + u_long f_flag; + struct vnode *f_devvp; + struct ntfsmount *f_mp; + dev_t f_dev; + enum vtype f_type; + + ntfs_times_t f_times; /* $NAME/dirinfo */ + ino_t f_pnumber; /* $NAME/dirinfo */ + u_int32_t f_fflag; /* $NAME/dirinfo */ + u_int64_t f_size; /* defattr/dirinfo: */ + u_int64_t f_allocated; /* defattr/dirinfo */ - u_int32_t i_defattr; - char *i_defattrname; - struct ntvattr *i_vattrp; + u_int32_t f_attrtype; + char *f_attrname; - int i_lockcount; /* Process lock count (recursion) */ - pid_t i_lockholder; /* DEBUG: holder of ntnode lock. */ - pid_t i_lockwaiter; /* DEBUG: waiter of ntnode lock. */ + /* for ntreaddir */ + u_int32_t f_lastdattr; + u_int32_t f_lastdblnum; + u_int32_t f_lastdoff; + u_int32_t f_lastdnum; + caddr_t f_dirblbuf; + u_int32_t f_dirblsz; }; diff --git a/sys/fs/ntfs/ntfs_subr.c b/sys/fs/ntfs/ntfs_subr.c index 629470f..901ea69 100644 --- a/sys/fs/ntfs/ntfs_subr.c +++ b/sys/fs/ntfs/ntfs_subr.c @@ -27,6 +27,7 @@ */ #include <sys/param.h> +#include <sys/types.h> #include <sys/systm.h> #include <sys/namei.h> #include <sys/proc.h> @@ -44,8 +45,11 @@ #include <ntfs/ntfs.h> #include <ntfs/ntfsmount.h> #include <ntfs/ntfs_inode.h> +#include <ntfs/ntfs_vfsops.h> +#include <ntfs/ntfs_extern.h> #include <ntfs/ntfs_subr.h> #include <ntfs/ntfs_compr.h> +#include <ntfs/ntfs_ihash.h> #if __FreeBSD_version >= 300000 MALLOC_DEFINE(M_NTFSNTVATTR, "NTFS vattr", "NTFS file attribute information"); @@ -61,7 +65,7 @@ ntfs_ntvattrrele( dprintf(("ntfs_ntvattrrele: ino: %d, type: 0x%x\n", vap->va_ip->i_number, vap->va_type)); - vrele(NTTOV(vap->va_ip)); + ntfs_ntrele(vap->va_ip); return (0); } @@ -101,7 +105,7 @@ ntfs_ntvattrget( if((ip->i_flag & IN_LOADED) == 0) { dprintf(("ntfs_ntvattrget: node not loaded, ino: %d\n", ip->i_number)); - error = ntfs_loadnode(ntmp,ip); + error = ntfs_loadntnode(ntmp,ip); if(error) { printf("ntfs_ntvattrget: FAILED TO LOAD INO: %d\n", ip->i_number); @@ -118,17 +122,7 @@ ntfs_ntvattrget( (vap->va_namelen == namelen) && (!strncmp(name, vap->va_name, namelen))) { *vapp = vap; -#if __FreeBSD_version >= 300000 - VREF(NTTOV(vap->va_ip)); -#else - /* - * In RELENG_2_2 vref can call vfs_object_create(...) - * who calls vgetattr, who calls ntfs_getattr, who - * calls ntfs_ntvattrget, who calls vref... :-( This - * hack is to avoid it. XXX - */ - NTTOV(vap->va_ip)->v_usecount++; -#endif + ntfs_ntref(vap->va_ip); return (0); } if (vap->va_type == NTFS_A_ATTRLIST) @@ -144,7 +138,7 @@ ntfs_ntvattrget( /* Scan $ATTRIBUTE_LIST for requested attribute */ len = lvap->va_datalen; MALLOC(alpool, caddr_t, len, M_TEMP, M_WAITOK); - error = ntfs_breadntvattr_plain(ntmp, ip, lvap, 0, len, alpool, &len); + error = ntfs_readntvattr_plain(ntmp, ip, lvap, 0, len, alpool, &len); if (error) goto out; @@ -188,7 +182,7 @@ ntfs_ntvattrget( if(~newip->i_flag & IN_LOADED) { dprintf(("ntfs_ntvattrget: node not loaded," \ " ino: %d\n", newip->i_number)); - error = ntfs_loadnode(ntmp,ip); + error = ntfs_loadntnode(ntmp,ip); if(error) { printf("ntfs_ntvattrget: CAN'T LOAD " \ "INO: %d\n", newip->i_number); @@ -203,12 +197,7 @@ ntfs_ntvattrget( (vap->va_namelen == namelen) && (!strncmp(name, vap->va_name, namelen))) { *vapp = vap; -#if __FreeBSD_version >= 300000 - VREF(NTTOV(vap->va_ip)); -#else - /* See comment above */ - NTTOV(vap->va_ip)->v_usecount++; -#endif + ntfs_ntref(vap->va_ip); vput(newvp); error = 0; goto out; @@ -235,7 +224,7 @@ out: } int -ntfs_loadnode( +ntfs_loadntnode( struct ntfsmount * ntmp, struct ntnode * ip) { @@ -272,11 +261,11 @@ ntfs_loadnode( struct vnode *vp; vp = ntmp->ntm_sysvn[NTFS_MFTINO]; - error = ntfs_breadattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, + error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, ip->i_number * ntfs_bntob(ntmp->ntm_bpmftrec), ntfs_bntob(ntmp->ntm_bpmftrec), mfrp); if (error) { - printf("ntfs_loadnode: ntfs_breadattr failed\n"); + printf("ntfs_loadnode: ntfs_readattr failed\n"); goto out; } } @@ -292,6 +281,9 @@ ntfs_loadnode( dprintf(("ntfs_loadnode: load attrs for ino: %d\n",ip->i_number)); off = mfrp->fr_attroff; ap = (struct attr *) ((caddr_t)mfrp + off); + if (ip->i_vattrp) + printf("ntfs_ntloadnode: WARNING! already loaded?\n"); + vapp = &ip->i_vattrp; while (ap->a_hdr.a_type != -1) { error = ntfs_attrtontvattr(ntmp, vapp, ap); @@ -315,61 +307,13 @@ ntfs_loadnode( ip->i_flag |= IN_LOADED; - if (ip->i_mainrec == 0) { - struct ntvattr *vap; - - if (ntfs_ntvattrget(ntmp, ip, NTFS_A_NAME, NULL, 0, &vap) == 0){ - ip->i_times = vap->va_a_name->n_times; - ip->i_pnumber = vap->va_a_name->n_pnumber; - ip->i_fflag = vap->va_a_name->n_flag; - - ntfs_ntvattrrele(vap); - } - - if ((ip->i_fflag & NTFS_FFLAG_DIR) && (ip->i_defattr == 0)) { - struct ntvattr *irvap; - - ip->i_type = VDIR; - ip->i_defattr = NTFS_A_INDXROOT; - ip->i_defattrname = "$I30"; - error = ntfs_ntvattrget(ntmp, ip, - NTFS_A_INDXROOT, "$I30", - 0, &irvap); - if(error == 0) { - ip->i_dirblsz = irvap->va_a_iroot->ir_size; - MALLOC(ip->i_dirblbuf, caddr_t, - max(irvap->va_datalen,ip->i_dirblsz), - M_NTFSDIR, M_WAITOK); - - ntfs_ntvattrrele(irvap); - } - ip->i_size = 0; - ip->i_allocated = 0; - error = 0; - } else { - ip->i_type = VREG; - if(ip->i_defattr == 0) { - ip->i_defattr = NTFS_A_DATA; - ip->i_defattrname = NULL; - } - - ntfs_filesize(ntmp, ip, &ip->i_size, &ip->i_allocated); - } - } - - if (NTTOV(ip)) { - if (ip->i_number == NTFS_ROOTINO) - NTTOV(ip)->v_flag |= VROOT; - if (ip->i_number < NTFS_SYSNODESNUM) - NTTOV(ip)->v_flag |= VSYSTEM; - NTTOV(ip)->v_type = ip->i_type; - } out: FREE(mfrp, M_TEMP); return (error); } +static int ntfs_ntnode_hash_lock; int ntfs_ntget( struct ntfsmount * ntmp, @@ -378,27 +322,57 @@ ntfs_ntget( { struct ntnode *ip; - dprintf(("ntfs_ntget: allocate ntnode %d\n", ino)); + dprintf(("ntfs_ntget: ntget ntnode %d\n", ino)); *ipp = NULL; +restart: + ip = ntfs_nthashlookup(ntmp->ntm_dev, ino); + if (ip) { + ip->i_usecount++; + *ipp = ip; + dprintf(("ntfs_ntget: ntnode %d: %p, usecount: %d\n", + ino, ip, ip->i_usecount)); + + return (0); + } + + if (ntfs_ntnode_hash_lock) { + printf("waiting for hash_lock to free...\n"); + while(ntfs_ntnode_hash_lock) { + ntfs_ntnode_hash_lock = -1; + tsleep(&ntfs_ntnode_hash_lock, PVM, "ntfsntgt", 0); + } + printf("hash_lock freeed\n"); + goto restart; + } + ntfs_ntnode_hash_lock = 1; + MALLOC(ip, struct ntnode *, sizeof(struct ntnode), - M_NTFSNODE, M_WAITOK); + M_NTFSNTNODE, M_WAITOK); + ddprintf(("ntfs_ntget: allocating ntnode: %d: %p\n", ino, ip)); bzero((caddr_t) ip, sizeof(struct ntnode)); /* Generic initialization */ - ip->i_mp = ntmp; ip->i_number = ino; + ip->i_mp = ntmp; ip->i_dev = ntmp->ntm_dev; ip->i_uid = ntmp->ntm_uid; ip->i_gid = ntmp->ntm_gid; ip->i_mode = ntmp->ntm_mode; + ip->i_usecount++; - /* Setup internal pointers */ - ip->i_vattrp = NULL; - ip->i_devvp = ntmp->ntm_devvp; + LIST_INIT(&ip->i_fnlist); + + ntfs_nthashins(ip); + + if (ntfs_ntnode_hash_lock < 0) + wakeup(&ntfs_ntnode_hash_lock); + ntfs_ntnode_hash_lock = 0; *ipp = ip; - dprintf(("ntfs_ntget: allocated ntnode %d ok\n", ino)); + + dprintf(("ntfs_ntget: ntnode %d: %p, usecount: %d\n", + ino, ip, ip->i_usecount)); return (0); } @@ -409,15 +383,31 @@ ntfs_ntrele( { struct ntvattr *vap; - dprintf(("ntfs_ntrele: rele ntnode %d\n", ip->i_number)); - while (ip->i_vattrp) { - vap = ip->i_vattrp; - ip->i_vattrp = vap->va_nextp; - ntfs_freentvattr(vap); + dprintf(("ntfs_ntrele: rele ntnode %d: %p, usecount: %d\n", + ip->i_number, ip, ip->i_usecount)); + + ip->i_usecount--; + + if (ip->i_usecount < 0) { + panic("ntfs_ntrele: ino: %d usecount: %d \n", + ip->i_number,ip->i_usecount); + } else if (ip->i_usecount == 0) { + dprintf(("ntfs_ntrele: deallocating ntnode: %d\n", + ip->i_number)); + + if (ip->i_fnlist.lh_first) + panic("ntfs_ntrele: ntnode has fnodes\n"); + + ntfs_nthashrem(ip); + + while (ip->i_vattrp) { + vap = ip->i_vattrp; + ip->i_vattrp = vap->va_nextp; + ntfs_freentvattr(vap); + } + FREE(ip, M_NTFSNTNODE); } - if(ip->i_flag & IN_AATTRNAME) FREE(ip->i_defattrname,M_TEMP); - dprintf(("ntfs_ntrele: rele ntnode %d ok\n", ip->i_number)); - FREE(ip, M_NTFSNODE); + dprintf(("ntfs_ntrele: rele ok\n")); } void @@ -448,12 +438,13 @@ ntfs_attrtontvattr( error = 0; *rvapp = NULL; - MALLOC(vap, struct ntvattr *, sizeof(*vap), M_NTFSNTVATTR, M_WAITOK); + MALLOC(vap, struct ntvattr *, sizeof(struct ntvattr), + M_NTFSNTVATTR, M_WAITOK); + bzero(vap, sizeof(struct ntvattr)); vap->va_ip = NULL; vap->va_flag = rap->a_hdr.a_flag; vap->va_type = rap->a_hdr.a_type; vap->va_compression = rap->a_hdr.a_compression; - vap->va_nextp = NULL; vap->va_index = rap->a_hdr.a_index; ddprintf(("type: 0x%x, index: %d", vap->va_type, vap->va_index)); @@ -506,15 +497,16 @@ int ntfs_runtovrun( cn_t ** rcnp, cn_t ** rclp, - u_int32_t * rcntp, + u_long * rcntp, u_int8_t * run) { u_int32_t off; u_int32_t sz, i; cn_t *cn; cn_t *cl; - u_int32_t cnt; - u_int64_t prev; + u_long cnt; + cn_t prev; + cn_t tmp; off = 0; cnt = 0; @@ -530,7 +522,6 @@ ntfs_runtovrun( cnt = 0; prev = 0; while (run[off]) { - u_int64_t tmp; sz = run[off++]; cl[cnt] = 0; @@ -630,11 +621,90 @@ ntfs_uastrcmp( } int +ntfs_fget( + struct ntfsmount *ntmp, + struct ntnode *ip, + int attrtype, + char *attrname, + struct fnode **fpp) +{ + int error; + struct fnode *fp; + + dprintf(("ntfs_fget: ino: %d, attrtype: 0x%x, attrname: %s\n", + ip->i_number,attrtype, attrname?attrname:"")); + *fpp = NULL; + for (fp = ip->i_fnlist.lh_first; fp != NULL; fp = fp->f_fnlist.le_next){ + dprintf(("ntfs_fget: fnode: attrtype: %d, attrname: %s\n", + fp->f_attrtype, fp->f_attrname?fp->f_attrname:"")); + + if ((attrtype == fp->f_attrtype) && + ((!attrname && !fp->f_attrname) || + (attrname && fp->f_attrname && + !strcmp(attrname,fp->f_attrname)))){ + dprintf(("ntfs_fget: found existed: %p\n",fp)); + *fpp = fp; + } + } + + if (*fpp) + return (0); + + MALLOC(fp, struct fnode *, sizeof(struct fnode), M_NTFSFNODE, M_WAITOK); + bzero(fp, sizeof(struct fnode)); + dprintf(("ntfs_fget: allocating fnode: %p\n",fp)); + + fp->f_devvp = ntmp->ntm_devvp; + fp->f_dev = ntmp->ntm_dev; + fp->f_mp = ntmp; + + fp->f_ip = ip; + fp->f_attrname = attrname; + if (fp->f_attrname) fp->f_flag |= FN_AATTRNAME; + fp->f_attrtype = attrtype; + if ((fp->f_attrtype == NTFS_A_DATA) && (fp->f_attrname == NULL)) + fp->f_flag |= FN_DEFAULT; + else { + error = ntfs_filesize(ntmp, fp, &fp->f_size, &fp->f_allocated); + if (error) { + FREE(fp,M_NTFSFNODE); + return (error); + } + } + + ntfs_ntref(ip); + + LIST_INSERT_HEAD(&ip->i_fnlist, fp, f_fnlist); + + *fpp = fp; + + return (0); +} + +void +ntfs_frele( + struct fnode *fp) +{ + struct ntnode *ip = FTONT(fp); + + dprintf(("ntfs_frele: fnode: %p for %d: %p\n", fp, ip->i_number, ip)); + + dprintf(("ntfs_frele: deallocating fnode\n")); + LIST_REMOVE(fp,f_fnlist); + if (fp->f_flag & FN_AATTRNAME) + FREE(fp->f_attrname, M_TEMP); + if (fp->f_dirblbuf) + FREE(fp->f_dirblbuf, M_NTFSDIR); + FREE(fp, M_NTFSFNODE); + ntfs_ntrele(ip); +} + +int ntfs_ntlookupattr( struct ntfsmount * ntmp, char * name, int namelen, - int *type, + int *attrtype, char **attrname) { char *sys; @@ -660,14 +730,13 @@ ntfs_ntlookupattr( for (i = 0; i < ntmp->ntm_adnum; i++){ if((syslen == adp->ad_namelen) && (!strncmp(sys,adp->ad_name,syslen))) { - *type = adp->ad_type; + *attrtype = adp->ad_type; if(namelen) { MALLOC((*attrname), char *, namelen, M_TEMP, M_WAITOK); memcpy((*attrname), name, namelen); (*attrname)[namelen] = '\0'; - }/* else - (*attrname) = NULL;*/ + } return (0); } adp++; @@ -679,20 +748,24 @@ ntfs_ntlookupattr( MALLOC((*attrname), char *, namelen, M_TEMP, M_WAITOK); memcpy((*attrname), name, namelen); (*attrname)[namelen] = '\0'; + *attrtype = NTFS_A_DATA; } return (0); } /* - * Lookup specifed node for filename, matching cnp, return filled ntnode. + * Lookup specifed node for filename, matching cnp, + * return fnode filled. */ int ntfs_ntlookup( struct ntfsmount * ntmp, - struct ntnode * ip, + struct vnode * vp, struct componentname * cnp, - struct ntnode ** ipp) + struct vnode ** vpp) { + struct fnode *fp = VTOF(vp); + struct ntnode *ip = FTONT(fp); struct ntvattr *vap; /* Root attribute */ cn_t cn; /* VCN in current attribute */ caddr_t rdbuf; /* Buffer to read directory's blocks */ @@ -702,7 +775,6 @@ ntfs_ntlookup( int error, res, anamelen, fnamelen; char *fname,*aname; u_int32_t aoff; - struct ntnode *nip; error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap); if (error || (vap->va_flag & NTFS_AF_INRUN)) @@ -727,7 +799,7 @@ ntfs_ntlookup( MALLOC(rdbuf, caddr_t, blsize, M_TEMP, M_WAITOK); - error = ntfs_breadattr(ntmp, ip, NTFS_A_INDXROOT, "$I30", + error = ntfs_readattr(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, rdsize, rdbuf); if (error) goto fail; @@ -754,47 +826,65 @@ ntfs_ntlookup( fname, fnamelen); if (res == 0) { - error = ntfs_ntget(ntmp, - iep->ie_number, - &nip); - if(error) - goto fail; + int attrtype = NTFS_A_DATA; + char *attrname = NULL; + struct fnode *nfp; + struct vnode *nvp; - nip->i_fflag = iep->ie_fflag; - nip->i_pnumber = iep->ie_fpnumber; - nip->i_times = iep->ie_ftimes; - - if(nip->i_fflag & NTFS_FFLAG_DIR) { - nip->i_type = VDIR; - nip->i_defattr = 0; - nip->i_defattrname = NULL; - } else { - nip->i_type = VREG; - nip->i_defattr = NTFS_A_DATA; - nip->i_defattrname = NULL; - } if (aname) { error = ntfs_ntlookupattr(ntmp, aname, anamelen, - &nip->i_defattr, - &nip->i_defattrname); - if (error) { - ntfs_ntrele(nip); + &attrtype, &attrname); + if (error) goto fail; - } + } - nip->i_type = VREG; + /* Check if we've found ourself */ + if ((iep->ie_number == ip->i_number) && + (attrtype == fp->f_attrtype) && + ((!attrname && !fp->f_attrname) || + (attrname && fp->f_attrname && + !strcmp(attrname, fp->f_attrname)))) { + VREF(vp); + *vpp = vp; + goto fail; + } - if (nip->i_defattrname) - nip->i_flag |= IN_AATTRNAME; - } else { + /* vget node, but don't load it */ + error = ntfs_vgetex(ntmp->ntm_mountp, + iep->ie_number, + attrtype, + attrname, + LK_EXCLUSIVE, + VG_DONTLOAD, + curproc, + &nvp); + if(error) + goto fail; + + nfp = VTOF(nvp); + + nfp->f_fflag = iep->ie_fflag; + nfp->f_pnumber = iep->ie_fpnumber; + nfp->f_times = iep->ie_ftimes; + + if((nfp->f_fflag & NTFS_FFLAG_DIR) && + (nfp->f_attrtype == NTFS_A_DATA) && + (nfp->f_attrname == NULL)) + nfp->f_type = VDIR; + else + nfp->f_type = VREG; + + nvp->v_type = nfp->f_type; + + if ((nfp->f_attrtype == NTFS_A_DATA) && + (nfp->f_attrname == NULL)) { /* Opening default attribute */ - nip->i_size = iep->ie_fsize; - nip->i_allocated = - iep->ie_fallocated; - nip->i_flag |= IN_PRELOADED; + nfp->f_size = iep->ie_fsize; + nfp->f_allocated = iep->ie_fallocated; + nfp->f_flag |= FN_PRELOADED; } - *ipp = nip; + *vpp = nvp; goto fail; } } else if (res > 0) @@ -812,7 +902,7 @@ ntfs_ntlookup( iep->reclen - sizeof(cn_t)); rdsize = blsize; - error = ntfs_breadattr(ntmp, ip, NTFS_A_INDX, "$I30", + error = ntfs_readattr(ntmp, ip, NTFS_A_INDX, "$I30", ntfs_cntob(cn), rdsize, rdbuf); if (error) goto fail; @@ -865,16 +955,14 @@ ntfs_isnamepermitted( return 0; } -/* - * #undef dprintf #define dprintf(a) printf a - */ int ntfs_ntreaddir( struct ntfsmount * ntmp, - struct ntnode * ip, + struct fnode * fp, u_int32_t num, struct attr_indexentry ** riepp) { + struct ntnode *ip = FTONT(fp); struct ntvattr *vap = NULL; /* IndexRoot attribute */ struct ntvattr *bmvap = NULL; /* BitMap attribute */ struct ntvattr *iavap = NULL; /* IndexAllocation attribute */ @@ -894,8 +982,14 @@ ntfs_ntreaddir( if (error) return (ENOTDIR); - blsize = ip->i_dirblsz; - rdbuf = ip->i_dirblbuf; + if (fp->f_dirblbuf == NULL) { + fp->f_dirblsz = vap->va_a_iroot->ir_size; + MALLOC(fp->f_dirblbuf, caddr_t, + max(vap->va_datalen,fp->f_dirblsz), M_NTFSDIR, M_WAITOK); + } + + blsize = fp->f_dirblsz; + rdbuf = fp->f_dirblbuf; dprintf(("ntfs_ntreaddir: rdbuf: 0x%p, blsize: %d\n", rdbuf, blsize)); @@ -907,7 +1001,7 @@ ntfs_ntreaddir( goto fail; } MALLOC(bmp, u_char *, bmvap->va_datalen, M_TEMP, M_WAITOK); - error = ntfs_breadattr(ntmp, ip, NTFS_A_INDXBITMAP, "$I30", 0, + error = ntfs_readattr(ntmp, ip, NTFS_A_INDXBITMAP, "$I30", 0, bmvap->va_datalen, bmp); if (error) goto fail; @@ -928,11 +1022,11 @@ ntfs_ntreaddir( } /* Try use previous values */ - if ((ip->i_lastdnum < num) && (ip->i_lastdnum != 0)) { - attrnum = ip->i_lastdattr; - aoff = ip->i_lastdoff; - blnum = ip->i_lastdblnum; - cnum = ip->i_lastdnum; + if ((fp->f_lastdnum < num) && (fp->f_lastdnum != 0)) { + attrnum = fp->f_lastdattr; + aoff = fp->f_lastdoff; + blnum = fp->f_lastdblnum; + cnum = fp->f_lastdnum; } else { attrnum = NTFS_A_INDXROOT; aoff = sizeof(struct attr_indexroot); @@ -944,7 +1038,7 @@ ntfs_ntreaddir( dprintf(("ntfs_ntreaddir: scan: 0x%x, %d, %d, %d, %d\n", attrnum, (u_int32_t) blnum, cnum, num, aoff)); rdsize = (attrnum == NTFS_A_INDXROOT) ? vap->va_datalen : blsize; - error = ntfs_breadattr(ntmp, ip, attrnum, "$I30", + error = ntfs_readattr(ntmp, ip, attrnum, "$I30", ntfs_cntob(blnum * cpbl), rdsize, rdbuf); if (error) goto fail; @@ -964,10 +1058,10 @@ ntfs_ntreaddir( while (!(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff)) { if (ntfs_isnamepermitted(ntmp, iep)) { if (cnum >= num) { - ip->i_lastdnum = cnum; - ip->i_lastdoff = aoff; - ip->i_lastdblnum = blnum; - ip->i_lastdattr = attrnum; + fp->f_lastdnum = cnum; + fp->f_lastdoff = aoff; + fp->f_lastdblnum = blnum; + fp->f_lastdattr = attrnum; *riepp = iep; @@ -1001,7 +1095,7 @@ ntfs_ntreaddir( } while (iavap); *riepp = NULL; - ip->i_lastdnum = 0; + fp->f_lastdnum = 0; fail: if (vap) @@ -1054,17 +1148,23 @@ ntfs_times( int ntfs_filesize( struct ntfsmount * ntmp, - struct ntnode * ip, + struct fnode * fp, u_int64_t * size, u_int64_t * bytes) { struct ntvattr *vap; + struct ntnode *ip = FTONT(fp); u_int64_t sz, bn; int error; dprintf(("ntfs_filesize: ino: %d\n", ip->i_number)); - error = ntfs_ntvattrget(ntmp, ip, ip->i_defattr, ip->i_defattrname, - 0, &vap); + if (fp->f_flag & FN_DEFAULT) { + error = ntfs_ntvattrget(ntmp, ip, + NTFS_A_DATA, NULL, 0, &vap); + } else { + error = ntfs_ntvattrget(ntmp, ip, + fp->f_attrtype, fp->f_attrname, 0, &vap); + } if (error) return (error); bn = vap->va_allocated; @@ -1084,7 +1184,160 @@ ntfs_filesize( } int -ntfs_breadntvattr_plain( +ntfs_writeattr_plain( + struct ntfsmount * ntmp, + struct ntnode * ip, + u_int32_t attrnum, + char *attrname, + off_t roff, + size_t rsize, + void *rdata, + size_t * initp) +{ + size_t init; + int error = 0; + off_t off = roff, left = rsize, towrite; + caddr_t data = rdata; + struct ntvattr *vap; + *initp = 0; + + while (left) { + error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname, + ntfs_btocn(off), &vap); + if (error) + return (error); + towrite = min(left, ntfs_cntob(vap->va_vcnend + 1) - off); + ddprintf(("ntfs_writeattr_plain: o: %d, s: %d (%d - %d)\n", + (u_int32_t) off, (u_int32_t) towrite, + (u_int32_t) vap->va_vcnstart, + (u_int32_t) vap->va_vcnend)); + error = ntfs_writentvattr_plain(ntmp, ip, vap, + off - ntfs_cntob(vap->va_vcnstart), + towrite, data, &init); + if (error) { + printf("ntfs_writeattr_plain: " \ + "ntfs_writentvattr_plain failed: o: %d, s: %d\n", + (u_int32_t) off, (u_int32_t) towrite); + printf("ntfs_writeattr_plain: attrib: %d - %d\n", + (u_int32_t) vap->va_vcnstart, + (u_int32_t) vap->va_vcnend); + ntfs_ntvattrrele(vap); + break; + } + ntfs_ntvattrrele(vap); + left -= towrite; + off += towrite; + data = data + towrite; + *initp += init; + } + + return (error); +} + +int +ntfs_writentvattr_plain( + struct ntfsmount * ntmp, + struct ntnode * ip, + struct ntvattr * vap, + off_t roff, + size_t rsize, + void *rdata, + size_t * initp) +{ + int error = 0; + int off; + + *initp = 0; + if (vap->va_flag & NTFS_AF_INRUN) { + int cnt; + cn_t ccn, ccl, cn, left, cl; + caddr_t data = rdata; + struct buf *bp; + size_t tocopy; + + ddprintf(("ntfs_writentvattr_plain: data in run: %d chains\n", + vap->va_vruncnt)); + + off = roff; + left = rsize; + ccl = 0; + ccn = 0; + cnt = 0; + while (left && (cnt < vap->va_vruncnt)) { + ccn = vap->va_vruncn[cnt]; + ccl = vap->va_vruncl[cnt]; + + ddprintf(("ntfs_writentvattr_plain: " \ + "left %d, cn: 0x%x, cl: %d, off: %d\n", \ + (u_int32_t) left, (u_int32_t) ccn, \ + (u_int32_t) ccl, (u_int32_t) off)); + + if (ntfs_cntob(ccl) < off) { + off -= ntfs_cntob(ccl); + cnt++; + continue; + } + if (ccn || ip->i_number == NTFS_BOOTINO) { /* XXX */ + ccl -= ntfs_btocn(off); + cn = ccn + ntfs_btocn(off); + off = ntfs_btocnoff(off); + + while (left && ccl) { + tocopy = min(left, + min(ntfs_cntob(ccl) - off, + MAXBSIZE - off)); + cl = ntfs_btocl(tocopy + off); + ddprintf(("ntfs_writentvattr_plain: " \ + "write: cn: 0x%x cl: %d, " \ + "off: %d len: %d, left: %d\n", + (u_int32_t) cn, + (u_int32_t) cl, + (u_int32_t) off, + (u_int32_t) tocopy, + (u_int32_t) left)); + if ((off == 0) && + (tocopy == ntfs_cntob(cl))) { + bp = getblk(ntmp->ntm_devvp, + ntfs_cntobn(cn), + ntfs_cntob(cl), + 0, 0); + clrbuf(bp); + } else { + error = bread(ntmp->ntm_devvp, + ntfs_cntobn(cn), + ntfs_cntob(cl), + NOCRED, &bp); + if (error) { + brelse(bp); + return (error); + } + } + memcpy(bp->b_data + off, data, tocopy); + bwrite(bp); + data = data + tocopy; + *initp += tocopy; + off = 0; + left -= tocopy; + cn += cl; + ccl -= cl; + } + } + cnt++; + } + if (left) { + printf("ntfs_writentvattr_plain: POSSIBLE RUN ERROR\n"); + error = EINVAL; + } + } else { + printf("ntfs_writevattr_plain: CAN'T WRITE RES. ATTRIBUTE\n"); + error = ENOTTY; + } + + return (error); +} + +int +ntfs_readntvattr_plain( struct ntfsmount * ntmp, struct ntnode * ip, struct ntvattr * vap, @@ -1104,7 +1357,7 @@ ntfs_breadntvattr_plain( struct buf *bp; size_t tocopy; - ddprintf(("ntfs_breadntvattr_plain: data in run: %d chains\n", + ddprintf(("ntfs_readntvattr_plain: data in run: %d chains\n", vap->va_vruncnt)); off = roff; @@ -1116,7 +1369,7 @@ ntfs_breadntvattr_plain( ccn = vap->va_vruncn[cnt]; ccl = vap->va_vruncl[cnt]; - ddprintf(("ntfs_breadntvattr_plain: " \ + ddprintf(("ntfs_readntvattr_plain: " \ "left %d, cn: 0x%x, cl: %d, off: %d\n", \ (u_int32_t) left, (u_int32_t) ccn, \ (u_int32_t) ccl, (u_int32_t) off)); @@ -1136,7 +1389,7 @@ ntfs_breadntvattr_plain( min(ntfs_cntob(ccl) - off, MAXBSIZE - off)); cl = ntfs_btocl(tocopy + off); - ddprintf(("ntfs_breadntvattr_plain: " \ + ddprintf(("ntfs_readntvattr_plain: " \ "read: cn: 0x%x cl: %d, " \ "off: %d len: %d, left: %d\n", (u_int32_t) cn, @@ -1163,7 +1416,7 @@ ntfs_breadntvattr_plain( } } else { tocopy = min(left, ntfs_cntob(ccl) - off); - ddprintf(("ntfs_breadntvattr_plain: " + ddprintf(("ntfs_readntvattr_plain: " "sparce: ccn: 0x%x ccl: %d, off: %d, " \ " len: %d, left: %d\n", (u_int32_t) ccn, (u_int32_t) ccl, @@ -1177,11 +1430,11 @@ ntfs_breadntvattr_plain( cnt++; } if (left) { - printf("ntfs_breadntvattr_plain: POSSIBLE RUN ERROR\n"); + printf("ntfs_readntvattr_plain: POSSIBLE RUN ERROR\n"); error = E2BIG; } } else { - ddprintf(("ntfs_breadnvattr_plain: data is in mft record\n")); + ddprintf(("ntfs_readnvattr_plain: data is in mft record\n")); memcpy(rdata, vap->va_datap + roff, rsize); *initp += rsize; } @@ -1190,7 +1443,7 @@ ntfs_breadntvattr_plain( } int -ntfs_breadattr_plain( +ntfs_readattr_plain( struct ntfsmount * ntmp, struct ntnode * ip, u_int32_t attrnum, @@ -1213,18 +1466,18 @@ ntfs_breadattr_plain( if (error) return (error); toread = min(left, ntfs_cntob(vap->va_vcnend + 1) - off); - ddprintf(("ntfs_breadattr_plain: o: %d, s: %d (%d - %d)\n", + ddprintf(("ntfs_readattr_plain: o: %d, s: %d (%d - %d)\n", (u_int32_t) off, (u_int32_t) toread, (u_int32_t) vap->va_vcnstart, (u_int32_t) vap->va_vcnend)); - error = ntfs_breadntvattr_plain(ntmp, ip, vap, + error = ntfs_readntvattr_plain(ntmp, ip, vap, off - ntfs_cntob(vap->va_vcnstart), toread, data, &init); if (error) { - printf("ntfs_breadattr_plain: " \ - "ntfs_breadntvattr_plain failed: o: %d, s: %d\n", + printf("ntfs_readattr_plain: " \ + "ntfs_readntvattr_plain failed: o: %d, s: %d\n", (u_int32_t) off, (u_int32_t) toread); - printf("ntfs_breadattr_plain: attrib: %d - %d\n", + printf("ntfs_readattr_plain: attrib: %d - %d\n", (u_int32_t) vap->va_vcnstart, (u_int32_t) vap->va_vcnend); ntfs_ntvattrrele(vap); @@ -1241,7 +1494,7 @@ ntfs_breadattr_plain( } int -ntfs_breadattr( +ntfs_readattr( struct ntfsmount * ntmp, struct ntnode * ip, u_int32_t attrnum, @@ -1254,7 +1507,7 @@ ntfs_breadattr( struct ntvattr *vap; size_t init; - ddprintf(("ntfs_breadattr: reading %d: 0x%x, from %d size %d bytes\n", + ddprintf(("ntfs_readattr: reading %d: 0x%x, from %d size %d bytes\n", ip->i_number, attrnum, (u_int32_t) roff, (u_int32_t) rsize)); error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname, 0, &vap); @@ -1263,7 +1516,7 @@ ntfs_breadattr( if ((roff > vap->va_datalen) || (roff + rsize > vap->va_datalen)) { - ddprintf(("ntfs_breadattr: offset too big\n")); + ddprintf(("ntfs_readattr: offset too big\n")); ntfs_ntvattrrele(vap); return (E2BIG); } @@ -1286,7 +1539,7 @@ ntfs_breadattr( off = roff - ntfs_cntob(cn); while (left) { - error = ntfs_breadattr_plain(ntmp, ip, attrnum, + error = ntfs_readattr_plain(ntmp, ip, attrnum, attrname, ntfs_cntob(cn), ntfs_cntob(NTFS_COMPUNIT_CL), cup, &init); @@ -1315,7 +1568,7 @@ ntfs_breadattr( FREE(uup, M_NTFSDECOMP); FREE(cup, M_NTFSDECOMP); } else - error = ntfs_breadattr_plain(ntmp, ip, attrnum, attrname, + error = ntfs_readattr_plain(ntmp, ip, attrnum, attrname, roff, rsize, rdata, &init); ntfs_ntvattrrele(vap); return (error); @@ -1326,14 +1579,14 @@ ntfs_parserun( cn_t * cn, cn_t * cl, u_int8_t * run, - size_t len, - int *off) + u_long len, + u_long *off) { u_int8_t sz; int i; if (NULL == run) { - printf("ntfs_runtocn: run == NULL\n"); + printf("ntfs_parsetun: run == NULL\n"); return (EINVAL); } sz = run[(*off)++]; @@ -1344,7 +1597,7 @@ ntfs_parserun( *cl = 0; if ((sz & 0xF) > 8 || (*off) + (sz & 0xF) > len) { printf("ntfs_parserun: " \ - "bad run: length too big: %02x (%x < %x + sz)\n", + "bad run: length too big: sz: 0x%02x (%ld < %ld + sz)\n", sz, len, *off); return (EINVAL); } @@ -1354,7 +1607,7 @@ ntfs_parserun( sz >>= 4; if ((sz & 0xF) > 8 || (*off) + (sz & 0xF) > len) { printf("ntfs_parserun: " \ - "bad run: offset too big: %02x (%x < %x + sz)\n", + "bad run: length too big: sz: 0x%02x (%ld < %ld + sz)\n", sz, len, *off); return (EINVAL); } @@ -1411,18 +1664,18 @@ ntfs_runtocn( cn_t * cn, struct ntfsmount * ntmp, u_int8_t * run, - size_t len, + u_long len, cn_t vcn) { cn_t ccn = 0; cn_t ccl = 0; - int off = 0; + u_long off = 0; int error = 0; #if NTFS_DEBUG int i; - printf("ntfs_runtocn: " \ - "run: 0x%p, %d bytes, vcn:%d\n", run, len, (u_int32_t) vcn); + printf("ntfs_runtocn: run: 0x%p, %ld bytes, vcn:%ld\n", + run, len, (u_long) vcn); printf("ntfs_runtocn: run: "); for (i = 0; i < len; i++) printf("0x%02x ", run[i]); diff --git a/sys/fs/ntfs/ntfs_subr.h b/sys/fs/ntfs/ntfs_subr.h index 94cef19..692bb54 100644 --- a/sys/fs/ntfs/ntfs_subr.h +++ b/sys/fs/ntfs/ntfs_subr.h @@ -26,10 +26,14 @@ * $Id: ntfs_subr.h,v 1.3 1999/02/02 01:54:54 semen Exp $ */ +#define VA_LOADED 0x0001 +#define VA_PRELOADED 0x0002 + struct ntvattr { struct ntvattr *va_nextp; u_int32_t va_vflag; + struct vnode *va_vp; struct ntnode *va_ip; u_int32_t va_flag; @@ -48,7 +52,7 @@ struct ntvattr { struct { cn_t * cn; cn_t * cl; - u_int32_t cnt; + u_long cnt; } vrun; caddr_t datap; struct attr_name *name; @@ -67,30 +71,41 @@ struct ntvattr { #define uastrcmp(a,b,c,d) ntfs_uastrcmp(ntmp,a,b,c,d) +#ifndef NTFS_DEBUG +#define ntfs_ntref(i) (i)->i_usecount++ +#else +#define ntfs_ntref(i) { \ + printf("ntfs_ntref: ino %d, usecount: %d\n", \ + (i)->i_number, (i)->i_usecount++); \ +} +#endif + int ntfs_procfixups __P(( struct ntfsmount *, u_int32_t, caddr_t, size_t )); -int ntfs_parserun __P(( cn_t *, cn_t *, u_int8_t *, size_t, int *)); -int ntfs_runtocn __P(( cn_t *, struct ntfsmount *, u_int8_t *, size_t, cn_t)); -int ntfs_breadntvattr_plain __P(( struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *,size_t *)); -int ntfs_breadattr_plain __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *,size_t *)); -int ntfs_breadattr __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *)); -int ntfs_filesize __P(( struct ntfsmount *, struct ntnode *, u_int64_t *, u_int64_t *)); +int ntfs_parserun __P(( cn_t *, cn_t *, u_int8_t *, u_long, u_long *)); +int ntfs_runtocn __P(( cn_t *, struct ntfsmount *, u_int8_t *, u_long, cn_t)); +int ntfs_readntvattr_plain __P(( struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *,size_t *)); +int ntfs_readattr_plain __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *,size_t *)); +int ntfs_readattr __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *)); +int ntfs_filesize __P(( struct ntfsmount *, struct fnode *, u_int64_t *, u_int64_t *)); int ntfs_times __P(( struct ntfsmount *, struct ntnode *, ntfs_times_t *)); struct timespec ntfs_nttimetounix __P(( u_int64_t )); -int ntfs_ntreaddir __P(( struct ntfsmount *, struct ntnode *, u_int32_t, struct attr_indexentry **)); +int ntfs_ntreaddir __P(( struct ntfsmount *, struct fnode *, u_int32_t, struct attr_indexentry **)); wchar ntfs_toupper __P(( struct ntfsmount *, wchar )); int ntfs_uustricmp __P(( struct ntfsmount *, wchar *, int, wchar *, int )); int ntfs_uastricmp __P(( struct ntfsmount *, wchar *, int, char *, int )); int ntfs_uastrcmp __P(( struct ntfsmount *, wchar *, int, char *, int )); -int ntfs_runtovrun __P(( cn_t **, cn_t **, u_int32_t *, u_int8_t *)); +int ntfs_runtovrun __P(( cn_t **, cn_t **, u_long *, u_int8_t *)); int ntfs_attrtontvattr __P(( struct ntfsmount *, struct ntvattr **, struct attr * )); void ntfs_freentvattr __P(( struct ntvattr * )); int ntfs_loadntvattrs __P(( struct ntfsmount *, struct vnode *, caddr_t, struct ntvattr **)); struct ntvattr * ntfs_findntvattr __P(( struct ntfsmount *, struct ntnode *, u_int32_t, cn_t )); -int ntfs_ntlookup __P(( struct ntfsmount *, struct ntnode *, struct componentname *, struct ntnode **)); +int ntfs_ntlookup __P(( struct ntfsmount *, struct vnode *, struct componentname *, struct vnode **)); int ntfs_isnamepermitted __P(( struct ntfsmount *, struct attr_indexentry * )); int ntfs_ntvattrrele __P(( struct ntvattr * )); int ntfs_ntvattrget __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, cn_t , struct ntvattr **)); int ntfs_ntget __P(( struct ntfsmount *, ino_t, struct ntnode **)); void ntfs_ntrele __P(( struct ntnode *)); -int ntfs_loadnode __P(( struct ntfsmount *, struct ntnode * )); -int ntfs_ntlookupattr __P(( struct ntfsmount *, char *, int, int *, char **)); +int ntfs_loadntnode __P(( struct ntfsmount *, struct ntnode * )); +int ntfs_ntlookupattr(struct ntfsmount *, char *, int, int *, char **); +int ntfs_writentvattr_plain(struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *, size_t *); +int ntfs_writeattr_plain(struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *, size_t *); diff --git a/sys/fs/ntfs/ntfs_vfsops.c b/sys/fs/ntfs/ntfs_vfsops.c index b3ccf0a..a371319 100644 --- a/sys/fs/ntfs/ntfs_vfsops.c +++ b/sys/fs/ntfs/ntfs_vfsops.c @@ -52,12 +52,15 @@ #include <ntfs/ntfs.h> #include <ntfs/ntfs_inode.h> #include <ntfs/ntfs_subr.h> +#include <ntfs/ntfs_vfsops.h> +#include <ntfs/ntfs_ihash.h> #include <ntfs/ntfs_extern.h> #include <ntfs/ntfsmount.h> #if __FreeBSD_version >= 300000 MALLOC_DEFINE(M_NTFSMNT, "NTFS mount", "NTFS mount structure"); -MALLOC_DEFINE(M_NTFSNODE,"NTFS node", "NTFS node information"); +MALLOC_DEFINE(M_NTFSNTNODE,"NTFS ntnode", "NTFS ntnode information"); +MALLOC_DEFINE(M_NTFSFNODE,"NTFS fnode", "NTFS fnode information"); MALLOC_DEFINE(M_NTFSDIR,"NTFS dir", "NTFS dir buffer"); #endif @@ -106,7 +109,7 @@ ntfs_init () printf("ntfs_init(): \n"); - ntfs_ihashinit(); + ntfs_nthashinit(); return 0; } @@ -411,7 +414,13 @@ ntfs_mountfs(devvp, mp, argsp, p) printf("ntfs_mountfs(): reading system nodes...\n"); { i = NTFS_MFTINO; - error = VFS_VGET(mp, i, &ntmp->ntm_sysvn[i]); + error = VFS_VGET(mp, i, &(ntmp->ntm_sysvn[i])); + if(error) + goto out1; + VREF(ntmp->ntm_sysvn[i]); + vput(ntmp->ntm_sysvn[i]); + i = NTFS_ROOTINO; + error = VFS_VGET(mp, i, &(ntmp->ntm_sysvn[i])); if(error) goto out1; VREF(ntmp->ntm_sysvn[i]); @@ -426,7 +435,7 @@ ntfs_mountfs(devvp, mp, argsp, p) if(error) goto out1; printf("ntfs_mountfs(): reading $UpCase\n"); - error = ntfs_breadattr( ntmp, VTONT(vp), NTFS_A_DATA, NULL, + error = ntfs_readattr( ntmp, VTONT(vp), NTFS_A_DATA, NULL, 0, 65536*sizeof(wchar), ntmp->ntm_upcase); printf("ntfs_mountfs(): closing $UpCase\n"); vput(vp); @@ -443,7 +452,7 @@ ntfs_mountfs(devvp, mp, argsp, p) goto out1; for(num=0;;num++) { - error = ntfs_breadattr(ntmp, VTONT(vp), + error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, num * sizeof(ad), sizeof(ad), &ad); @@ -461,7 +470,7 @@ ntfs_mountfs(devvp, mp, argsp, p) ntmp->ntm_adnum = num; for(i=0;i<num;i++){ - error = ntfs_breadattr(ntmp, VTONT(vp), + error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, i * sizeof(ad), sizeof(ad), &ad); @@ -537,13 +546,16 @@ ntfs_unmount( flags |= FORCECLOSE; printf("ntfs_unmount: vflushing...\n"); - for(i=0;i<NTFS_SYSNODESNUM;i++) - if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); - error = vflush(mp,NULLVP,flags); + error = vflush(mp,NULLVP,flags | SKIPSYSTEM); if (error) { printf("ntfs_unmount: vflush failed: %d\n",error); return (error); } + for(i=0;i<NTFS_SYSNODESNUM;i++) + if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); + error = vflush(mp,NULLVP,flags); + if (error) + printf("ntfs_unmount: vflush failed: %d\n",error); #if __FreeBSD_version >= 300000 ntmp->ntm_devvp->v_specmountpoint = NULL; @@ -578,7 +590,8 @@ ntfs_root( struct vnode *nvp; int error = 0; - dprintf(("ntfs_root():\n")); + dprintf(("ntfs_root(): sysvn: %p\n", + VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO])); error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, &nvp); if(error) { printf("ntfs_root: VFS_VGET failed: %d\n",error); @@ -615,18 +628,18 @@ ntfs_statfs( dprintf(("ntfs_statfs():")); - ntfs_filesize(ntmp, VTONT(ntmp->ntm_sysvn[NTFS_MFTINO]), + ntfs_filesize(ntmp, VTOF(ntmp->ntm_sysvn[NTFS_MFTINO]), &mftsize, &mftallocated); error = VFS_VGET(mp, NTFS_BITMAPINO, &vp); if(error) return (error); - ntfs_filesize(ntmp, VTONT(vp), &bmsize, &bmallocated); + ntfs_filesize(ntmp, VTOF(vp), &bmsize, &bmallocated); MALLOC(tmp, u_int8_t *, bmsize,M_TEMP, M_WAITOK); - error = ntfs_breadattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, + error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, 0, bmsize, tmp); if(error) { FREE(tmp, M_TEMP); @@ -660,6 +673,7 @@ ntfs_statfs( bcopy((caddr_t)mp->mnt_stat.f_mntfromname, (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); } + sbp->f_flags = mp->mnt_flag; return (0); } @@ -708,58 +722,107 @@ ntfs_vptofh( return EOPNOTSUPP; } -static int -ntfs_vget( +int +ntfs_vgetex( struct mount *mp, ino_t ino, + u_int32_t attrtype, + char *attrname, + u_long lkflags, + u_long flags, + struct proc *p, struct vnode **vpp) { - int error=0; - struct vnode *vp; + int error; register struct ntfsmount *ntmp; struct ntnode *ip; + struct fnode *fp; + struct vnode *vp; - dprintf(("ntfs_vget: ino: %d\n",ino)); + dprintf(("ntfs_vgetex: ino: %d, attr: 0x%x:%s, lkf: 0x%x, f: 0x%x\n", + ino, attrtype, attrname?attrname:"", lkflags, flags )); ntmp = VFSTONTFS(mp); + *vpp = NULL; - *vpp = NULL; - - dprintf(("ntfs_ntvget: ihashlookup\n")); - if( (*vpp = ntfs_ihashget(ntmp->ntm_dev, ino)) != NULL ) - return (0); - - error = ntfs_ntget(ntmp,ino,&ip); - if(error) { + /* Get ntnode */ + error = ntfs_ntget(ntmp, ino, &ip); + if (error) { printf("ntfs_vget: ntfs_ntget failed\n"); return (error); } - error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, &vp); - if(error) { - /* XXX */ + error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp); + if (error) { + printf("ntfs_vget: ntfs_fget failed\n"); ntfs_ntrele(ip); return (error); } - ip->i_vnode = vp; - vp->v_data = ip; - vp->v_type = ip->i_type; - ntfs_ihashins(ip); + if (FTOV(fp)) { + vget(FTOV(fp), lkflags, p); + *vpp = FTOV(fp); + ntfs_ntrele(ip); + return (0); + } - VREF(ip->i_devvp); + /* It may be not initialized fully, so force load it */ + if (!(flags & VG_DONTLOAD) && !(ip->i_flag & IN_LOADED)) { + error = ntfs_loadntnode(ntmp, ip); + if(error) { + printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n", + ip->i_number); + ntfs_ntrele(ip); + return (error); + } + } - error = ntfs_loadnode(ntmp, ip); + error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, &vp); if(error) { - printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n", - ip->i_number); - vput(vp); + ntfs_frele(fp); + ntfs_ntrele(ip); return (error); } + dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino)); - *vpp = vp; + lockinit(&fp->f_lock, PINOD, "fnode", 0, 0); + fp->f_vp = vp; + vp->v_data = fp; + + if (ip->i_frflag & NTFS_FRFLAG_DIR) + vp->v_type = fp->f_type = VDIR; + else + vp->v_type = fp->f_type = VREG; + if (ino == NTFS_ROOTINO) + vp->v_flag |= VROOT; + if (ino < NTFS_SYSNODESNUM) + vp->v_flag |= VSYSTEM; + + ntfs_ntrele(ip); + + if (lkflags & LK_TYPE_MASK) { + error = vn_lock(vp, lkflags, p); + if (error) { + vput(vp); + return (error); + } + } + + VREF(fp->f_devvp); + *vpp = vp; return (0); + +} + +static int +ntfs_vget( + struct mount *mp, + ino_t ino, + struct vnode **vpp) +{ + return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL, + LK_EXCLUSIVE, 0, curproc, vpp); } #if __FreeBSD_version >= 300000 diff --git a/sys/fs/ntfs/ntfs_vfsops.h b/sys/fs/ntfs/ntfs_vfsops.h new file mode 100644 index 0000000..c8788c4 --- /dev/null +++ b/sys/fs/ntfs/ntfs_vfsops.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: ntfs_vfsops.h,v 1.1 1999/02/02 01:54:54 semen Exp $ + */ +#define VG_DONTLOAD 0x0001 /* Tells ntfs_vgetex to do not call */ + /* ntfs_loadnode on ntnode, even if */ + /* ntnode not loaded */ + +int ntfs_vgetex(struct mount *, ino_t, u_int32_t, char *, u_long, u_long, + struct proc *, struct vnode **); diff --git a/sys/fs/ntfs/ntfs_vnops.c b/sys/fs/ntfs/ntfs_vnops.c index b5394fe..f1a822a 100644 --- a/sys/fs/ntfs/ntfs_vnops.c +++ b/sys/fs/ntfs/ntfs_vnops.c @@ -33,7 +33,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ntfs_vnops.c,v 1.9 1999/02/02 01:54:55 semen Exp $ + * $Id: ntfs_vnops.c,v 1.10 1999/02/02 03:15:13 semen Exp $ * */ @@ -66,11 +66,12 @@ #include <ntfs/ntfs.h> #include <ntfs/ntfs_inode.h> #include <ntfs/ntfs_subr.h> +#include <ntfs/ntfs_extern.h> #include <miscfs/specfs/specdev.h> static int ntfs_bypass __P((struct vop_generic_args *ap)); static int ntfs_read __P((struct vop_read_args *)); -static int ntfs_bwrite __P((struct vop_bwrite_args *ap)); +static int ntfs_write __P((struct vop_write_args *ap)); static int ntfs_getattr __P((struct vop_getattr_args *ap)); static int ntfs_inactive __P((struct vop_inactive_args *ap)); static int ntfs_print __P((struct vop_print_args *ap)); @@ -88,120 +89,25 @@ static int ntfs_readdir __P((struct vop_readdir_args *ap)); static int ntfs_lookup __P((struct vop_lookup_args *ap)); static int ntfs_bmap __P((struct vop_bmap_args *ap)); static int ntfs_getpages __P((struct vop_getpages_args *ap)); +static int ntfs_putpages __P((struct vop_putpages_args *)); static int ntfs_fsync __P((struct vop_fsync_args *ap)); int ntfs_prtactive = 1; /* 1 => print out reclaim of active vnodes */ -/* - * Vnode op for VM getpages. - */ int ntfs_getpages(ap) struct vop_getpages_args *ap; { - int i, error, nextoff, size, toff, npages, count; - struct uio uio; - struct iovec iov; - vm_offset_t kva; - struct buf *bp; - struct vnode *vp; - struct proc *p; - struct ucred *cred; - struct ntfsmount *ntmp; - vm_page_t *pages; - - vp = ap->a_vp; - p = curproc; /* XXX */ - cred = curproc->p_ucred; /* XXX */ - ntmp = VFSTONTFS(vp->v_mount); - pages = ap->a_m; - count = ap->a_count; - - if (vp->v_object == NULL) { - printf("ntfs_getpages: called with non-merged cache vnode??\n"); - return VM_PAGER_ERROR; - } - - /* - * We use only the kva address for the buffer, but this is extremely - * convienient and fast. - */ -#if __FreeBSD_version >= 400000 - bp = getpbuf(NULL); -#else - bp = getpbuf(); -#endif - - npages = btoc(count); - kva = (vm_offset_t) bp->b_data; - pmap_qenter(kva, pages, npages); - - iov.iov_base = (caddr_t) kva; - iov.iov_len = count; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = IDX_TO_OFF(pages[0]->pindex); - uio.uio_resid = count; - uio.uio_segflg = UIO_SYSSPACE; - uio.uio_rw = UIO_READ; - uio.uio_procp = p; - - error = VOP_READ(vp, &uio, 0, cred); - pmap_qremove(kva, npages); - -#if __FreeBSD_version >= 400000 - relpbuf(bp,NULL); -#else - relpbuf(bp); -#endif - - if (error && (uio.uio_resid == count)) - return VM_PAGER_ERROR; - - size = count - uio.uio_resid; - - for (i = 0, toff = 0; i < npages; i++, toff = nextoff) { - vm_page_t m; - nextoff = toff + PAGE_SIZE; - m = pages[i]; - - m->flags &= ~PG_ZERO; + return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count, + ap->a_reqpage); +} - if (nextoff <= size) { - m->valid = VM_PAGE_BITS_ALL; - m->dirty = 0; - } else { - int nvalid = ((size + DEV_BSIZE - 1) - toff) & ~(DEV_BSIZE - 1); - vm_page_set_validclean(m, 0, nvalid); - } - - if (i != ap->a_reqpage) { - /* - * Whether or not to leave the page activated is up in - * the air, but we should put the page on a page queue - * somewhere (it already is in the object). Result: - * It appears that emperical results show that - * deactivating pages is best. - */ - - /* - * Just in case someone was asking for this page we - * now tell them that it is ok to use. - */ - if (!error) { - if (m->flags & PG_WANTED) - vm_page_activate(m); - else - vm_page_deactivate(m); -#if __FreeBSD_version >= 300000 - vm_page_wakeup(m); -#endif - } else { - vnode_pager_freepage(m); - } - } - } - return 0; +int +ntfs_putpages(ap) + struct vop_putpages_args *ap; +{ + return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count, + ap->a_sync, ap->a_rtvals); } /* @@ -218,6 +124,7 @@ ntfs_bmap(ap) int *a_runb; } */ *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) @@ -239,7 +146,8 @@ ntfs_read(ap) } */ *ap; { register struct vnode *vp = ap->a_vp; - register struct ntnode *ip = VTONT(vp); + register struct fnode *fp = VTOF(vp); + register struct ntnode *ip = FTONT(fp); struct uio *uio = ap->a_uio; struct ntfsmount *ntmp = ip->i_mp; u_int8_t *data; @@ -248,7 +156,7 @@ ntfs_read(ap) dprintf(("ntfs_read: ino: %d, off: %d resid: %d, segflg: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg)); - ntfs_filesize( ntmp, ip, &toread, NULL ); + ntfs_filesize(ntmp, fp, &toread, NULL); dprintf(("ntfs_read: filesize: %d",(u_int32_t)toread)); toread = min( uio->uio_resid, toread - uio->uio_offset ); @@ -257,16 +165,17 @@ ntfs_read(ap) MALLOC(data, u_int8_t *, toread, M_TEMP,M_WAITOK); - error = ntfs_breadattr( ntmp, ip, ip->i_defattr, ip->i_defattrname, - uio->uio_offset, toread, data ); + error = ntfs_readattr( ntmp, ip, fp->f_attrtype, + fp->f_attrname, uio->uio_offset, toread, data); if(error) { - printf("ntfs_read: ntfs_breadattr failed: %d\n",error); + printf("ntfs_read: ntfs_readattr failed: %d\n",error); FREE(data, M_TEMP); return (error); } error = uiomove(data, (int) toread, uio); if(error) { + printf("ntfs_read: uiomove failed: %d\n",error); FREE(data, M_TEMP); return (error); } @@ -284,7 +193,7 @@ ntfs_bypass(ap) } */ *ap; { int error = ENOTTY; - dprintf (("ntfs_bypass: %s\n", ap->a_desc->vdesc_name)); + dprintf(("ntfs_bypass: %s\n", ap->a_desc->vdesc_name)); return (error); } @@ -299,33 +208,28 @@ ntfs_getattr(ap) } */ *ap; { register struct vnode *vp = ap->a_vp; - register struct ntnode *ip = VTONT(vp); + register struct fnode *fp = VTOF(vp); + register struct ntnode *ip = FTONT(fp); register struct vattr *vap = ap->a_vap; - int error; dprintf(("ntfs_getattr: %d, flags: %d\n",ip->i_number,ip->i_flag)); - if ((ip->i_flag & (IN_LOADED | IN_PRELOADED)) == 0) { - error = ntfs_loadnode(ip->i_mp,ip); - if (error) - return error; - } - vap->va_fsid = ip->i_dev; + vap->va_fsid = fp->f_dev; vap->va_fileid = ip->i_number; vap->va_mode = ip->i_mode; vap->va_nlink = ip->i_nlink; vap->va_uid = ip->i_uid; vap->va_gid = ip->i_gid; vap->va_rdev = (dev_t)0; - vap->va_size = ip->i_size; - vap->va_bytes = ip->i_allocated; - vap->va_atime = ntfs_nttimetounix(ip->i_times.t_access); - vap->va_mtime = ntfs_nttimetounix(ip->i_times.t_write); - vap->va_ctime = ntfs_nttimetounix(ip->i_times.t_create); + vap->va_size = fp->f_size; + vap->va_bytes = fp->f_allocated; + vap->va_atime = ntfs_nttimetounix(fp->f_times.t_access); + vap->va_mtime = ntfs_nttimetounix(fp->f_times.t_write); + vap->va_ctime = ntfs_nttimetounix(fp->f_times.t_create); vap->va_flags = ip->i_flag; vap->va_gen = 0; vap->va_blocksize = ip->i_mp->ntm_spc * ip->i_mp->ntm_bps; - vap->va_type = ip->i_type; + vap->va_type = fp->f_type; vap->va_filerev = 0; return (0); } @@ -346,8 +250,7 @@ ntfs_inactive(ap) #endif int error; - dprintf(("ntfs_inactive: %d (%d locks)\n", - ip->i_number,ip->i_lockcount)); + dprintf(("ntfs_inactive: vnode: %p, ntnode: %d\n", vp, ip->i_number)); if (ntfs_prtactive && vp->v_usecount != 0) vprint("ntfs_inactive: pushing active", vp); @@ -391,34 +294,25 @@ ntfs_reclaim(ap) } */ *ap; { register struct vnode *vp = ap->a_vp; - register struct ntnode *ip = VTONT(vp); + register struct fnode *fp = VTOF(vp); +#if NTFS_DEBUG + register struct ntnode *ip = FTONT(fp); +#endif - dprintf(("ntfs_reclaim: reclaim: %d\n",ip->i_number)); + dprintf(("ntfs_reclaim: vnode: %p, ntnode: %d\n", vp, ip->i_number)); #if __FreeBSD_version >= 300000 VOP_UNLOCK(vp,0,ap->a_p); #endif - if(ip->i_dirblbuf) { - FREE(ip->i_dirblbuf, M_NTFSDIR); - ip->i_dirblbuf = NULL; - } - - /* - * Remove the inode from its hash chain. - */ - ntfs_ihashrem(ip); - - /* - * Purge old data structures associated with the inode. - */ + /* Purge old data structures associated with the inode. */ cache_purge(vp); - if (ip->i_devvp) { - vrele(ip->i_devvp); - ip->i_devvp = 0; + if (fp->f_devvp) { + vrele(fp->f_devvp); + fp->f_devvp = NULL; } - ntfs_ntrele(ip); + ntfs_frele(fp); vp->v_data = NULL; @@ -447,47 +341,126 @@ ntfs_strategy(ap) } */ *ap; { register struct buf *bp = ap->a_bp; - struct ucred *cr; - struct proc *p; - int error = 0; - - dprintf(("strategy: data: %p, npages: %d,dirty: %d\n",bp->b_data,bp->b_npages,bp->b_dirtyend)); - if (bp->b_flags & B_PHYS) - panic("ntfs physio"); - if (bp->b_flags & B_ASYNC) - p = (struct proc *)0; - else - p = curproc; /* XXX */ - if (bp->b_flags & B_READ) - cr = bp->b_rcred; - else - cr = bp->b_wcred; - /* - * If the op is asynchronous and an i/o daemon is waiting - * queue the request, wake it up and wait for completion - * otherwise just do it ourselves. - */ -/* - if ((bp->b_flags & B_ASYNC) == 0 || - nfs_asyncio(bp, NOCRED)) - error = nfs_doio(bp, cr, p); -*/ + register struct vnode *vp = bp->b_vp; + register struct fnode *fp = VTOF(vp); + register struct ntnode *ip = FTONT(fp); + struct ntfsmount *ntmp = ip->i_mp; + int error; + + 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)); + dprintf(("strategy: bcount: %d flags: 0x%x\n", + (u_int32_t)bp->b_bcount,bp->b_flags)); + + if (bp->b_flags & B_READ) { + u_int32_t toread; + + if (ntfs_cntob(bp->b_blkno) >= fp->f_size) { + clrbuf(bp); + error = 0; + } else { + toread = min(bp->b_bcount, + fp->f_size-ntfs_cntob(bp->b_blkno)); + 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), + toread, bp->b_data); + + if (error) { + printf("ntfs_strategy: ntfs_readattr failed\n"); + bp->b_error = error; + bp->b_flags |= B_ERROR; + } + + bzero(bp->b_data + toread, bp->b_bcount - toread); + } + } else { + size_t tmp; + u_int32_t towrite; - return (ENOTTY); + if (ntfs_cntob(bp->b_blkno) + 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)); + 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, + bp->b_data, &tmp); + + if (error) { + printf("ntfs_strategy: ntfs_writeattr fail\n"); + bp->b_error = error; + bp->b_flags |= B_ERROR; + } + } + } + biodone(bp); return (error); } static int -ntfs_bwrite(ap) - struct vop_bwrite_args /* { - struct buf *a_bp; +ntfs_write(ap) + struct vop_write_args /* { + struct vnode *a_vp; + struct uio *a_uio; + int a_ioflag; + struct ucred *a_cred; } */ *ap; { - int error = ENOTTY; + register struct vnode *vp = ap->a_vp; + register struct fnode *fp = VTOF(vp); + register struct ntnode *ip = FTONT(fp); + struct uio *uio = ap->a_uio; + struct ntfsmount *ntmp = ip->i_mp; + u_int8_t *data; + u_int64_t towrite; + off_t off; + size_t written; + int error; - printf("ntfs_bwrite: \n"); + dprintf(("ntfs_write: ino: %d, off: %d resid: %d, segflg: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg)); - return (error); + ntfs_filesize(ntmp, fp, &towrite, NULL); + + if (uio->uio_resid + uio->uio_offset > towrite) { + printf("ntfs_write: CAN'T WRITE BEYOND OF FILE\n"); + return (EFBIG); + } + + dprintf(("ntfs_write: filesize: %d",(u_int32_t)towrite)); + + towrite = min(uio->uio_resid, towrite - uio->uio_offset); + off = uio->uio_offset; + + dprintf((", towrite: %d\n",(u_int32_t)towrite)); + + MALLOC(data, u_int8_t *, towrite, M_TEMP,M_WAITOK); + + error = uiomove(data, (int) towrite, uio); + if(error) { + FREE(data, M_TEMP); + return (error); + } + + error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype, + fp->f_attrname, off, towrite, data, &written); + if(error) { + printf("ntfs_write: ntfs_writeattr failed: %d\n",error); + FREE(data, M_TEMP); + return (error); + } + + FREE(data, M_TEMP); + + return (0); } #if __FreeBSD_version < 300000 @@ -502,7 +475,7 @@ ntfs_islocked(ap) { register struct ntnode *ip = VTONT(ap->a_vp); - dprintf(("ntfs_islocked %d (%d locks)\n",ip->i_number,ip->i_lockcount)); + dprintf(("ntfs_islocked %d\n",ip->i_number)); if (ip->i_flag & IN_LOCKED) return (1); @@ -522,7 +495,7 @@ ntfs_unlock(ap) register struct ntnode *ip = VTONT(ap->a_vp); struct proc *p = curproc; - dprintf(("ntfs_unlock %d (%d locks)\n",ip->i_number,ip->i_lockcount)); + dprintf(("ntfs_unlock %d\n",ip->i_number)); #ifdef DIAGNOSTIC @@ -639,7 +612,7 @@ ntfs_access(ap) * character device resident on the file system. */ if (mode & VWRITE) { - switch (vp->v_type) { + switch ((int)vp->v_type) { case VDIR: case VLNK: case VREG: @@ -717,7 +690,7 @@ ntfs_open(ap) register struct vnode *vp = ap->a_vp; register struct ntnode *ip = VTONT(vp); - printf("ntfs_open: %d (%d locks)\n",ip->i_number,ip->i_lockcount); + printf("ntfs_open: %d\n",ip->i_number); #endif /* @@ -746,7 +719,7 @@ ntfs_close(ap) register struct vnode *vp = ap->a_vp; register struct ntnode *ip = VTONT(vp); - printf("ntfs_close: %d (%d locks)\n",ip->i_number,ip->i_lockcount); + printf("ntfs_close: %d\n",ip->i_number); #endif return (0); @@ -767,7 +740,8 @@ ntfs_readdir(ap) } */ *ap; { register struct vnode *vp = ap->a_vp; - register struct ntnode *ip = VTONT(vp); + register struct fnode *fp = VTOF(vp); + register struct ntnode *ip = FTONT(fp); struct uio *uio = ap->a_uio; struct ntfsmount *ntmp = ip->i_mp; int i, error = 0; @@ -813,7 +787,7 @@ ntfs_readdir(ap) while( uio->uio_resid >= sizeof(struct dirent) ) { struct attr_indexentry *iep; - error = ntfs_ntreaddir(ntmp, ip, num, &iep); + error = ntfs_ntreaddir(ntmp, fp, num, &iep); if(error) return (error); @@ -919,7 +893,7 @@ ntfs_lookup(ap) cnp->cn_nameptr, cnp->cn_namelen, dip->i_number,lockparent, wantparent)); - error = VOP_ACCESS(dvp,VEXEC, cred, cnp->cn_proc); + error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_proc); if(error) return (error); @@ -974,39 +948,12 @@ ntfs_lookup(ap) } return (error); } else { - struct ntnode * nip; - - error = ntfs_ntlookup(ntmp, dip, cnp, &nip); + error = ntfs_ntlookup(ntmp, dvp, cnp, ap->a_vpp); if(error) return (error); - dprintf(("ntfs_lookup: found ino: %d\n", nip->i_number)); - if( nip->i_number == dip->i_number ) { - ntfs_ntrele(nip); - VREF(dvp); - *ap->a_vpp = dvp; - return (0); - } - - *ap->a_vpp = ntfs_ihashget(ntmp->ntm_dev, nip->i_number); - if(*ap->a_vpp == NULL) { - error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, - ntfs_vnodeop_p, ap->a_vpp); - if(error) { - ntfs_ntrele(nip); - return (error); - } - nip->i_vnode = *(ap->a_vpp); - (*ap->a_vpp)->v_data = nip; - (*ap->a_vpp)->v_type = nip->i_type; - - ntfs_ihashins(nip); - - VREF(nip->i_devvp); - } else { - printf("found in cache\n"); - ntfs_ntrele(nip); - } + dprintf(("ntfs_lookup: found ino: %d\n", + VTONT(*ap->a_vpp)->i_number)); if(!lockparent || !(cnp->cn_flags & ISLASTCN)) #if __FreeBSD_version >= 300000 @@ -1070,10 +1017,12 @@ static struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = { { &vop_bmap_desc, (vop_t *)ntfs_bmap }, { &vop_getpages_desc, (vop_t *)ntfs_getpages }, + { &vop_putpages_desc, (vop_t *) ntfs_putpages }, { &vop_strategy_desc, (vop_t *)ntfs_strategy }, - { &vop_bwrite_desc, (vop_t *)ntfs_bwrite }, + { &vop_bwrite_desc, (vop_t *)vop_stdbwrite }, { &vop_read_desc, (vop_t *)ntfs_read }, + { &vop_write_desc, (vop_t *)ntfs_write }, { NULL, NULL } }; diff --git a/sys/ntfs/ntfs.h b/sys/ntfs/ntfs.h index 84bbc77..6552c99 100644 --- a/sys/ntfs/ntfs.h +++ b/sys/ntfs/ntfs.h @@ -182,6 +182,7 @@ struct attr_indexentry { }; #define NTFS_FILEMAGIC (u_int32_t)(0x454C4946) +#define NTFS_FRFLAG_DIR 0x0002 struct filerec { struct fixuphdr fr_fixup; u_int8_t reserved[8]; @@ -195,10 +196,11 @@ struct filerec { u_int16_t fr_attrnum; /* maximum attr number + 1 ??? */ }; +#define NTFS_ATTRNAME_MAXLEN 0x40 #define NTFS_ADFLAG_NONRES 0x0080 /* Attrib can be non resident */ #define NTFS_ADFLAG_INDEX 0x0002 /* Attrib can be indexed */ struct attrdef { - wchar ad_name[0x40]; + wchar ad_name[NTFS_ATTRNAME_MAXLEN]; u_int32_t ad_type; u_int32_t reserved1[2]; u_int32_t ad_flag; @@ -261,8 +263,10 @@ struct ntfsmount { /* Convert mount ptr to ntfsmount ptr. */ #define VFSTONTFS(mp) ((struct ntfsmount *)((mp)->mnt_data)) -#define VTONT(v) ((struct ntnode *)((struct vnode *)(v)->v_data)) -#define NTTOV(i) (i->i_vnode) +#define VTONT(v) FTONT(VTOF(v)) +#define VTOF(v) ((struct fnode *)((v)->v_data)) +#define FTOV(f) ((f)->f_vp) +#define FTONT(f) ((f)->f_ip) #define ntfs_cntobn(cn) (daddr_t)((cn) * (ntmp->ntm_spc)) #define ntfs_cntob(cn) (off_t)((cn) * (ntmp)->ntm_spc * (ntmp)->ntm_bps) #define ntfs_btocn(off) (cn_t)((off) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps)) @@ -274,9 +278,10 @@ struct ntfsmount { #if __FreeBSD_version >= 300000 MALLOC_DECLARE(M_NTFSMNT); -MALLOC_DECLARE(M_NTFSNODE); +MALLOC_DECLARE(M_NTFSNTNODE); +MALLOC_DECLARE(M_NTFSFNODE); MALLOC_DECLARE(M_NTFSDIR); -MALLOC_DECLARE(M_NTFSIHASH); +MALLOC_DECLARE(M_NTFSNTHASH); #endif #if defined(NTFS_DEBUG) @@ -292,10 +297,3 @@ MALLOC_DECLARE(M_NTFSIHASH); #endif extern vop_t **ntfs_vnodeop_p; -struct ntnode; - -void ntfs_ihashinit __P((void)); -struct vnode *ntfs_ihashlookup __P((dev_t, ino_t)); -struct vnode *ntfs_ihashget __P((dev_t, ino_t)); -void ntfs_ihashins __P((struct ntnode *)); -void ntfs_ihashrem __P((register struct ntnode *)); diff --git a/sys/ntfs/ntfs_compr.c b/sys/ntfs/ntfs_compr.c index a096ba6..31558de 100644 --- a/sys/ntfs/ntfs_compr.c +++ b/sys/ntfs/ntfs_compr.c @@ -48,7 +48,7 @@ int ntfs_uncompblock( u_int8_t * buf, - const u_int8_t * cbuf) + u_int8_t * cbuf) { u_int32_t ctag; int len, dshift, lmask; @@ -100,7 +100,7 @@ int ntfs_uncompunit( struct ntfsmount * ntmp, u_int8_t * uup, - const u_int8_t * cup) + u_int8_t * cup) { int i; int off = 0; diff --git a/sys/ntfs/ntfs_compr.h b/sys/ntfs/ntfs_compr.h index b2637c5..ee37e97 100644 --- a/sys/ntfs/ntfs_compr.h +++ b/sys/ntfs/ntfs_compr.h @@ -29,5 +29,5 @@ #define NTFS_COMPBLOCK_SIZE 0x1000 #define NTFS_COMPUNIT_CL 16 -int ntfs_uncompblock(u_int8_t *, const u_int8_t *); -int ntfs_uncompunit(struct ntfsmount *, u_int8_t *, const u_int8_t *); +int ntfs_uncompblock(u_int8_t *, u_int8_t *); +int ntfs_uncompunit(struct ntfsmount *, u_int8_t *, u_int8_t *); diff --git a/sys/ntfs/ntfs_extern.h b/sys/ntfs/ntfs_extern.h index b88ae7f..28039e9 100644 --- a/sys/ntfs/ntfs_extern.h +++ b/sys/ntfs/ntfs_extern.h @@ -27,3 +27,5 @@ */ struct sockaddr; +int ntfs_fget(struct ntfsmount *, struct ntnode *, int, char *, struct fnode **); +void ntfs_frele(struct fnode *); diff --git a/sys/ntfs/ntfs_ihash.c b/sys/ntfs/ntfs_ihash.c index 837f478..e75f085 100644 --- a/sys/ntfs/ntfs_ihash.c +++ b/sys/ntfs/ntfs_ihash.c @@ -44,107 +44,75 @@ #include <ntfs/ntfs.h> #include <ntfs/ntfs_inode.h> +#include <ntfs/ntfs_ihash.h> -MALLOC_DEFINE(M_NTFSIHASH, "NTFS ihash", "NTFS Inode hash tables"); +MALLOC_DEFINE(M_NTFSNTHASH, "NTFS nthash", "NTFS ntnode hash tables"); /* * Structures associated with inode cacheing. */ -static LIST_HEAD(ihashhead, ntnode) *ntfs_ihashtbl; -static u_long ntfs_ihash; /* size of hash table - 1 */ -#define NTNOHASH(device, inum) (&ntfs_ihashtbl[((device) + (inum)) & ntfs_ihash]) -static struct simplelock ntfs_ihash_slock; +static LIST_HEAD(nthashhead, ntnode) *ntfs_nthashtbl; +static u_long ntfs_nthash; /* size of hash table - 1 */ +#define NTNOHASH(device, inum) (&ntfs_nthashtbl[((device) + (inum)) & ntfs_nthash]) +#ifndef NULL_SIMPLELOCKS +static struct simplelock ntfs_nthash_slock; +#endif /* * Initialize inode hash table. */ void -ntfs_ihashinit() +ntfs_nthashinit() { - ntfs_ihashtbl = hashinit(desiredvnodes, M_NTFSIHASH, &ntfs_ihash); - simple_lock_init(&ntfs_ihash_slock); + ntfs_nthashtbl = hashinit(desiredvnodes, M_NTFSNTHASH, &ntfs_nthash); + simple_lock_init(&ntfs_nthash_slock); } /* * Use the device/inum pair to find the incore inode, and return a pointer * to it. If it is in core, return it, even if it is locked. */ -struct vnode * -ntfs_ihashlookup(dev, inum) +struct ntnode * +ntfs_nthashlookup(dev, inum) dev_t dev; ino_t inum; { struct ntnode *ip; - simple_lock(&ntfs_ihash_slock); + simple_lock(&ntfs_nthash_slock); for (ip = NTNOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) if (inum == ip->i_number && dev == ip->i_dev) break; - simple_unlock(&ntfs_ihash_slock); + simple_unlock(&ntfs_nthash_slock); - if (ip) - return (NTTOV(ip)); - return (NULLVP); + return (ip); } /* - * Use the device/inum pair to find the incore inode, and return a pointer - * to it. If it is in core, but locked, wait for it. - */ -struct vnode * -ntfs_ihashget(dev, inum) - dev_t dev; - ino_t inum; -{ - struct proc *p = curproc; /* XXX */ - struct ntnode *ip; - struct vnode *vp; - -loop: - simple_lock(&ntfs_ihash_slock); - for (ip = NTNOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) { - if (inum == ip->i_number && dev == ip->i_dev) { - vp = NTTOV(ip); - simple_lock(&vp->v_interlock); - simple_unlock(&ntfs_ihash_slock); - if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) - goto loop; - return (vp); - } - } - simple_unlock(&ntfs_ihash_slock); - return (NULL); -} - -/* - * Insert the inode into the hash table, and return it locked. + * Insert the ntnode into the hash table. */ void -ntfs_ihashins(ip) +ntfs_nthashins(ip) struct ntnode *ip; { - struct proc *p = curproc; /* XXX */ - struct ihashhead *ipp; - - /* lock the inode, then put it on the appropriate hash list */ - lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0, p); + struct nthashhead *ipp; - simple_lock(&ntfs_ihash_slock); + simple_lock(&ntfs_nthash_slock); ipp = NTNOHASH(ip->i_dev, ip->i_number); LIST_INSERT_HEAD(ipp, ip, i_hash); ip->i_flag |= IN_HASHED; - simple_unlock(&ntfs_ihash_slock); + simple_unlock(&ntfs_nthash_slock); } /* * Remove the inode from the hash table. */ void -ntfs_ihashrem(ip) +ntfs_nthashrem(ip) struct ntnode *ip; { - simple_lock(&ntfs_ihash_slock); + simple_lock(&ntfs_nthash_slock); if (ip->i_flag & IN_HASHED) { ip->i_flag &= ~IN_HASHED; LIST_REMOVE(ip, i_hash); @@ -153,5 +121,5 @@ ntfs_ihashrem(ip) ip->i_hash.le_prev = NULL; #endif } - simple_unlock(&ntfs_ihash_slock); + simple_unlock(&ntfs_nthash_slock); } diff --git a/sys/ntfs/ntfs_ihash.h b/sys/ntfs/ntfs_ihash.h new file mode 100644 index 0000000..117bf7b --- /dev/null +++ b/sys/ntfs/ntfs_ihash.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 1998, 1999 Semen Ustimenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: ntfs.h,v 1.9 1999/02/02 01:54:54 semen Exp $ + */ + +void ntfs_nthashinit __P((void)); +struct ntnode *ntfs_nthashlookup __P((dev_t, ino_t)); +struct ntnode *ntfs_nthashget __P((dev_t, ino_t)); +void ntfs_nthashins __P((struct ntnode *)); +void ntfs_nthashrem __P((register struct ntnode *)); diff --git a/sys/ntfs/ntfs_inode.h b/sys/ntfs/ntfs_inode.h index 803ff86..2e6fb78 100644 --- a/sys/ntfs/ntfs_inode.h +++ b/sys/ntfs/ntfs_inode.h @@ -53,48 +53,58 @@ #define IN_LOADED 0x8000 /* ntvattrs loaded */ #define IN_PRELOADED 0x4000 /* loaded from directory entry */ -#define IN_AATTRNAME 0x2000 /* spaec allocated for i_defattrname */ struct ntnode { -#if __FreeBSD_version >= 300000 - struct lock i_lock; /* Must be first */ -#endif LIST_ENTRY(ntnode) i_hash; struct ntnode *i_next; struct ntnode **i_prev; - struct vnode *i_vnode; - struct vnode *i_devvp; struct ntfsmount *i_mp; - enum vtype i_type; - dev_t i_dev; ino_t i_number; + dev_t i_dev; u_int32_t i_flag; + int i_usecount; + + LIST_HEAD(,fnode) i_fnlist; + struct ntvattr *i_vattrp; /* ntvattrs list */ long i_nlink; /* MFR */ ino_t i_mainrec; /* MFR */ u_int32_t i_frflag; /* MFR */ - ntfs_times_t i_times; /* $NAME/dirinfo */ - ino_t i_pnumber; /* $NAME/dirinfo */ - u_int32_t i_fflag; /* $NAME/dirinfo */ - u_int64_t i_size; /* defattr/dirinfo: */ - u_int64_t i_allocated; /* defattr/dirinfo */ - - u_int32_t i_lastdattr; - u_int32_t i_lastdblnum; - u_int32_t i_lastdoff; - u_int32_t i_lastdnum; - caddr_t i_dirblbuf; - u_int32_t i_dirblsz; uid_t i_uid; gid_t i_gid; mode_t i_mode; +}; + +#define FN_PRELOADED 0x0001 +#define FN_DEFAULT 0x0002 +#define FN_AATTRNAME 0x0004 /* space allocated for f_attrname */ +struct fnode { + struct lock f_lock; /* Must be first */ + + LIST_ENTRY(fnode) f_fnlist; + struct vnode *f_vp; /* Associatied vnode */ + struct ntnode *f_ip; + u_long f_flag; + struct vnode *f_devvp; + struct ntfsmount *f_mp; + dev_t f_dev; + enum vtype f_type; + + ntfs_times_t f_times; /* $NAME/dirinfo */ + ino_t f_pnumber; /* $NAME/dirinfo */ + u_int32_t f_fflag; /* $NAME/dirinfo */ + u_int64_t f_size; /* defattr/dirinfo: */ + u_int64_t f_allocated; /* defattr/dirinfo */ - u_int32_t i_defattr; - char *i_defattrname; - struct ntvattr *i_vattrp; + u_int32_t f_attrtype; + char *f_attrname; - int i_lockcount; /* Process lock count (recursion) */ - pid_t i_lockholder; /* DEBUG: holder of ntnode lock. */ - pid_t i_lockwaiter; /* DEBUG: waiter of ntnode lock. */ + /* for ntreaddir */ + u_int32_t f_lastdattr; + u_int32_t f_lastdblnum; + u_int32_t f_lastdoff; + u_int32_t f_lastdnum; + caddr_t f_dirblbuf; + u_int32_t f_dirblsz; }; diff --git a/sys/ntfs/ntfs_subr.c b/sys/ntfs/ntfs_subr.c index 629470f..901ea69 100644 --- a/sys/ntfs/ntfs_subr.c +++ b/sys/ntfs/ntfs_subr.c @@ -27,6 +27,7 @@ */ #include <sys/param.h> +#include <sys/types.h> #include <sys/systm.h> #include <sys/namei.h> #include <sys/proc.h> @@ -44,8 +45,11 @@ #include <ntfs/ntfs.h> #include <ntfs/ntfsmount.h> #include <ntfs/ntfs_inode.h> +#include <ntfs/ntfs_vfsops.h> +#include <ntfs/ntfs_extern.h> #include <ntfs/ntfs_subr.h> #include <ntfs/ntfs_compr.h> +#include <ntfs/ntfs_ihash.h> #if __FreeBSD_version >= 300000 MALLOC_DEFINE(M_NTFSNTVATTR, "NTFS vattr", "NTFS file attribute information"); @@ -61,7 +65,7 @@ ntfs_ntvattrrele( dprintf(("ntfs_ntvattrrele: ino: %d, type: 0x%x\n", vap->va_ip->i_number, vap->va_type)); - vrele(NTTOV(vap->va_ip)); + ntfs_ntrele(vap->va_ip); return (0); } @@ -101,7 +105,7 @@ ntfs_ntvattrget( if((ip->i_flag & IN_LOADED) == 0) { dprintf(("ntfs_ntvattrget: node not loaded, ino: %d\n", ip->i_number)); - error = ntfs_loadnode(ntmp,ip); + error = ntfs_loadntnode(ntmp,ip); if(error) { printf("ntfs_ntvattrget: FAILED TO LOAD INO: %d\n", ip->i_number); @@ -118,17 +122,7 @@ ntfs_ntvattrget( (vap->va_namelen == namelen) && (!strncmp(name, vap->va_name, namelen))) { *vapp = vap; -#if __FreeBSD_version >= 300000 - VREF(NTTOV(vap->va_ip)); -#else - /* - * In RELENG_2_2 vref can call vfs_object_create(...) - * who calls vgetattr, who calls ntfs_getattr, who - * calls ntfs_ntvattrget, who calls vref... :-( This - * hack is to avoid it. XXX - */ - NTTOV(vap->va_ip)->v_usecount++; -#endif + ntfs_ntref(vap->va_ip); return (0); } if (vap->va_type == NTFS_A_ATTRLIST) @@ -144,7 +138,7 @@ ntfs_ntvattrget( /* Scan $ATTRIBUTE_LIST for requested attribute */ len = lvap->va_datalen; MALLOC(alpool, caddr_t, len, M_TEMP, M_WAITOK); - error = ntfs_breadntvattr_plain(ntmp, ip, lvap, 0, len, alpool, &len); + error = ntfs_readntvattr_plain(ntmp, ip, lvap, 0, len, alpool, &len); if (error) goto out; @@ -188,7 +182,7 @@ ntfs_ntvattrget( if(~newip->i_flag & IN_LOADED) { dprintf(("ntfs_ntvattrget: node not loaded," \ " ino: %d\n", newip->i_number)); - error = ntfs_loadnode(ntmp,ip); + error = ntfs_loadntnode(ntmp,ip); if(error) { printf("ntfs_ntvattrget: CAN'T LOAD " \ "INO: %d\n", newip->i_number); @@ -203,12 +197,7 @@ ntfs_ntvattrget( (vap->va_namelen == namelen) && (!strncmp(name, vap->va_name, namelen))) { *vapp = vap; -#if __FreeBSD_version >= 300000 - VREF(NTTOV(vap->va_ip)); -#else - /* See comment above */ - NTTOV(vap->va_ip)->v_usecount++; -#endif + ntfs_ntref(vap->va_ip); vput(newvp); error = 0; goto out; @@ -235,7 +224,7 @@ out: } int -ntfs_loadnode( +ntfs_loadntnode( struct ntfsmount * ntmp, struct ntnode * ip) { @@ -272,11 +261,11 @@ ntfs_loadnode( struct vnode *vp; vp = ntmp->ntm_sysvn[NTFS_MFTINO]; - error = ntfs_breadattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, + error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, ip->i_number * ntfs_bntob(ntmp->ntm_bpmftrec), ntfs_bntob(ntmp->ntm_bpmftrec), mfrp); if (error) { - printf("ntfs_loadnode: ntfs_breadattr failed\n"); + printf("ntfs_loadnode: ntfs_readattr failed\n"); goto out; } } @@ -292,6 +281,9 @@ ntfs_loadnode( dprintf(("ntfs_loadnode: load attrs for ino: %d\n",ip->i_number)); off = mfrp->fr_attroff; ap = (struct attr *) ((caddr_t)mfrp + off); + if (ip->i_vattrp) + printf("ntfs_ntloadnode: WARNING! already loaded?\n"); + vapp = &ip->i_vattrp; while (ap->a_hdr.a_type != -1) { error = ntfs_attrtontvattr(ntmp, vapp, ap); @@ -315,61 +307,13 @@ ntfs_loadnode( ip->i_flag |= IN_LOADED; - if (ip->i_mainrec == 0) { - struct ntvattr *vap; - - if (ntfs_ntvattrget(ntmp, ip, NTFS_A_NAME, NULL, 0, &vap) == 0){ - ip->i_times = vap->va_a_name->n_times; - ip->i_pnumber = vap->va_a_name->n_pnumber; - ip->i_fflag = vap->va_a_name->n_flag; - - ntfs_ntvattrrele(vap); - } - - if ((ip->i_fflag & NTFS_FFLAG_DIR) && (ip->i_defattr == 0)) { - struct ntvattr *irvap; - - ip->i_type = VDIR; - ip->i_defattr = NTFS_A_INDXROOT; - ip->i_defattrname = "$I30"; - error = ntfs_ntvattrget(ntmp, ip, - NTFS_A_INDXROOT, "$I30", - 0, &irvap); - if(error == 0) { - ip->i_dirblsz = irvap->va_a_iroot->ir_size; - MALLOC(ip->i_dirblbuf, caddr_t, - max(irvap->va_datalen,ip->i_dirblsz), - M_NTFSDIR, M_WAITOK); - - ntfs_ntvattrrele(irvap); - } - ip->i_size = 0; - ip->i_allocated = 0; - error = 0; - } else { - ip->i_type = VREG; - if(ip->i_defattr == 0) { - ip->i_defattr = NTFS_A_DATA; - ip->i_defattrname = NULL; - } - - ntfs_filesize(ntmp, ip, &ip->i_size, &ip->i_allocated); - } - } - - if (NTTOV(ip)) { - if (ip->i_number == NTFS_ROOTINO) - NTTOV(ip)->v_flag |= VROOT; - if (ip->i_number < NTFS_SYSNODESNUM) - NTTOV(ip)->v_flag |= VSYSTEM; - NTTOV(ip)->v_type = ip->i_type; - } out: FREE(mfrp, M_TEMP); return (error); } +static int ntfs_ntnode_hash_lock; int ntfs_ntget( struct ntfsmount * ntmp, @@ -378,27 +322,57 @@ ntfs_ntget( { struct ntnode *ip; - dprintf(("ntfs_ntget: allocate ntnode %d\n", ino)); + dprintf(("ntfs_ntget: ntget ntnode %d\n", ino)); *ipp = NULL; +restart: + ip = ntfs_nthashlookup(ntmp->ntm_dev, ino); + if (ip) { + ip->i_usecount++; + *ipp = ip; + dprintf(("ntfs_ntget: ntnode %d: %p, usecount: %d\n", + ino, ip, ip->i_usecount)); + + return (0); + } + + if (ntfs_ntnode_hash_lock) { + printf("waiting for hash_lock to free...\n"); + while(ntfs_ntnode_hash_lock) { + ntfs_ntnode_hash_lock = -1; + tsleep(&ntfs_ntnode_hash_lock, PVM, "ntfsntgt", 0); + } + printf("hash_lock freeed\n"); + goto restart; + } + ntfs_ntnode_hash_lock = 1; + MALLOC(ip, struct ntnode *, sizeof(struct ntnode), - M_NTFSNODE, M_WAITOK); + M_NTFSNTNODE, M_WAITOK); + ddprintf(("ntfs_ntget: allocating ntnode: %d: %p\n", ino, ip)); bzero((caddr_t) ip, sizeof(struct ntnode)); /* Generic initialization */ - ip->i_mp = ntmp; ip->i_number = ino; + ip->i_mp = ntmp; ip->i_dev = ntmp->ntm_dev; ip->i_uid = ntmp->ntm_uid; ip->i_gid = ntmp->ntm_gid; ip->i_mode = ntmp->ntm_mode; + ip->i_usecount++; - /* Setup internal pointers */ - ip->i_vattrp = NULL; - ip->i_devvp = ntmp->ntm_devvp; + LIST_INIT(&ip->i_fnlist); + + ntfs_nthashins(ip); + + if (ntfs_ntnode_hash_lock < 0) + wakeup(&ntfs_ntnode_hash_lock); + ntfs_ntnode_hash_lock = 0; *ipp = ip; - dprintf(("ntfs_ntget: allocated ntnode %d ok\n", ino)); + + dprintf(("ntfs_ntget: ntnode %d: %p, usecount: %d\n", + ino, ip, ip->i_usecount)); return (0); } @@ -409,15 +383,31 @@ ntfs_ntrele( { struct ntvattr *vap; - dprintf(("ntfs_ntrele: rele ntnode %d\n", ip->i_number)); - while (ip->i_vattrp) { - vap = ip->i_vattrp; - ip->i_vattrp = vap->va_nextp; - ntfs_freentvattr(vap); + dprintf(("ntfs_ntrele: rele ntnode %d: %p, usecount: %d\n", + ip->i_number, ip, ip->i_usecount)); + + ip->i_usecount--; + + if (ip->i_usecount < 0) { + panic("ntfs_ntrele: ino: %d usecount: %d \n", + ip->i_number,ip->i_usecount); + } else if (ip->i_usecount == 0) { + dprintf(("ntfs_ntrele: deallocating ntnode: %d\n", + ip->i_number)); + + if (ip->i_fnlist.lh_first) + panic("ntfs_ntrele: ntnode has fnodes\n"); + + ntfs_nthashrem(ip); + + while (ip->i_vattrp) { + vap = ip->i_vattrp; + ip->i_vattrp = vap->va_nextp; + ntfs_freentvattr(vap); + } + FREE(ip, M_NTFSNTNODE); } - if(ip->i_flag & IN_AATTRNAME) FREE(ip->i_defattrname,M_TEMP); - dprintf(("ntfs_ntrele: rele ntnode %d ok\n", ip->i_number)); - FREE(ip, M_NTFSNODE); + dprintf(("ntfs_ntrele: rele ok\n")); } void @@ -448,12 +438,13 @@ ntfs_attrtontvattr( error = 0; *rvapp = NULL; - MALLOC(vap, struct ntvattr *, sizeof(*vap), M_NTFSNTVATTR, M_WAITOK); + MALLOC(vap, struct ntvattr *, sizeof(struct ntvattr), + M_NTFSNTVATTR, M_WAITOK); + bzero(vap, sizeof(struct ntvattr)); vap->va_ip = NULL; vap->va_flag = rap->a_hdr.a_flag; vap->va_type = rap->a_hdr.a_type; vap->va_compression = rap->a_hdr.a_compression; - vap->va_nextp = NULL; vap->va_index = rap->a_hdr.a_index; ddprintf(("type: 0x%x, index: %d", vap->va_type, vap->va_index)); @@ -506,15 +497,16 @@ int ntfs_runtovrun( cn_t ** rcnp, cn_t ** rclp, - u_int32_t * rcntp, + u_long * rcntp, u_int8_t * run) { u_int32_t off; u_int32_t sz, i; cn_t *cn; cn_t *cl; - u_int32_t cnt; - u_int64_t prev; + u_long cnt; + cn_t prev; + cn_t tmp; off = 0; cnt = 0; @@ -530,7 +522,6 @@ ntfs_runtovrun( cnt = 0; prev = 0; while (run[off]) { - u_int64_t tmp; sz = run[off++]; cl[cnt] = 0; @@ -630,11 +621,90 @@ ntfs_uastrcmp( } int +ntfs_fget( + struct ntfsmount *ntmp, + struct ntnode *ip, + int attrtype, + char *attrname, + struct fnode **fpp) +{ + int error; + struct fnode *fp; + + dprintf(("ntfs_fget: ino: %d, attrtype: 0x%x, attrname: %s\n", + ip->i_number,attrtype, attrname?attrname:"")); + *fpp = NULL; + for (fp = ip->i_fnlist.lh_first; fp != NULL; fp = fp->f_fnlist.le_next){ + dprintf(("ntfs_fget: fnode: attrtype: %d, attrname: %s\n", + fp->f_attrtype, fp->f_attrname?fp->f_attrname:"")); + + if ((attrtype == fp->f_attrtype) && + ((!attrname && !fp->f_attrname) || + (attrname && fp->f_attrname && + !strcmp(attrname,fp->f_attrname)))){ + dprintf(("ntfs_fget: found existed: %p\n",fp)); + *fpp = fp; + } + } + + if (*fpp) + return (0); + + MALLOC(fp, struct fnode *, sizeof(struct fnode), M_NTFSFNODE, M_WAITOK); + bzero(fp, sizeof(struct fnode)); + dprintf(("ntfs_fget: allocating fnode: %p\n",fp)); + + fp->f_devvp = ntmp->ntm_devvp; + fp->f_dev = ntmp->ntm_dev; + fp->f_mp = ntmp; + + fp->f_ip = ip; + fp->f_attrname = attrname; + if (fp->f_attrname) fp->f_flag |= FN_AATTRNAME; + fp->f_attrtype = attrtype; + if ((fp->f_attrtype == NTFS_A_DATA) && (fp->f_attrname == NULL)) + fp->f_flag |= FN_DEFAULT; + else { + error = ntfs_filesize(ntmp, fp, &fp->f_size, &fp->f_allocated); + if (error) { + FREE(fp,M_NTFSFNODE); + return (error); + } + } + + ntfs_ntref(ip); + + LIST_INSERT_HEAD(&ip->i_fnlist, fp, f_fnlist); + + *fpp = fp; + + return (0); +} + +void +ntfs_frele( + struct fnode *fp) +{ + struct ntnode *ip = FTONT(fp); + + dprintf(("ntfs_frele: fnode: %p for %d: %p\n", fp, ip->i_number, ip)); + + dprintf(("ntfs_frele: deallocating fnode\n")); + LIST_REMOVE(fp,f_fnlist); + if (fp->f_flag & FN_AATTRNAME) + FREE(fp->f_attrname, M_TEMP); + if (fp->f_dirblbuf) + FREE(fp->f_dirblbuf, M_NTFSDIR); + FREE(fp, M_NTFSFNODE); + ntfs_ntrele(ip); +} + +int ntfs_ntlookupattr( struct ntfsmount * ntmp, char * name, int namelen, - int *type, + int *attrtype, char **attrname) { char *sys; @@ -660,14 +730,13 @@ ntfs_ntlookupattr( for (i = 0; i < ntmp->ntm_adnum; i++){ if((syslen == adp->ad_namelen) && (!strncmp(sys,adp->ad_name,syslen))) { - *type = adp->ad_type; + *attrtype = adp->ad_type; if(namelen) { MALLOC((*attrname), char *, namelen, M_TEMP, M_WAITOK); memcpy((*attrname), name, namelen); (*attrname)[namelen] = '\0'; - }/* else - (*attrname) = NULL;*/ + } return (0); } adp++; @@ -679,20 +748,24 @@ ntfs_ntlookupattr( MALLOC((*attrname), char *, namelen, M_TEMP, M_WAITOK); memcpy((*attrname), name, namelen); (*attrname)[namelen] = '\0'; + *attrtype = NTFS_A_DATA; } return (0); } /* - * Lookup specifed node for filename, matching cnp, return filled ntnode. + * Lookup specifed node for filename, matching cnp, + * return fnode filled. */ int ntfs_ntlookup( struct ntfsmount * ntmp, - struct ntnode * ip, + struct vnode * vp, struct componentname * cnp, - struct ntnode ** ipp) + struct vnode ** vpp) { + struct fnode *fp = VTOF(vp); + struct ntnode *ip = FTONT(fp); struct ntvattr *vap; /* Root attribute */ cn_t cn; /* VCN in current attribute */ caddr_t rdbuf; /* Buffer to read directory's blocks */ @@ -702,7 +775,6 @@ ntfs_ntlookup( int error, res, anamelen, fnamelen; char *fname,*aname; u_int32_t aoff; - struct ntnode *nip; error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap); if (error || (vap->va_flag & NTFS_AF_INRUN)) @@ -727,7 +799,7 @@ ntfs_ntlookup( MALLOC(rdbuf, caddr_t, blsize, M_TEMP, M_WAITOK); - error = ntfs_breadattr(ntmp, ip, NTFS_A_INDXROOT, "$I30", + error = ntfs_readattr(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, rdsize, rdbuf); if (error) goto fail; @@ -754,47 +826,65 @@ ntfs_ntlookup( fname, fnamelen); if (res == 0) { - error = ntfs_ntget(ntmp, - iep->ie_number, - &nip); - if(error) - goto fail; + int attrtype = NTFS_A_DATA; + char *attrname = NULL; + struct fnode *nfp; + struct vnode *nvp; - nip->i_fflag = iep->ie_fflag; - nip->i_pnumber = iep->ie_fpnumber; - nip->i_times = iep->ie_ftimes; - - if(nip->i_fflag & NTFS_FFLAG_DIR) { - nip->i_type = VDIR; - nip->i_defattr = 0; - nip->i_defattrname = NULL; - } else { - nip->i_type = VREG; - nip->i_defattr = NTFS_A_DATA; - nip->i_defattrname = NULL; - } if (aname) { error = ntfs_ntlookupattr(ntmp, aname, anamelen, - &nip->i_defattr, - &nip->i_defattrname); - if (error) { - ntfs_ntrele(nip); + &attrtype, &attrname); + if (error) goto fail; - } + } - nip->i_type = VREG; + /* Check if we've found ourself */ + if ((iep->ie_number == ip->i_number) && + (attrtype == fp->f_attrtype) && + ((!attrname && !fp->f_attrname) || + (attrname && fp->f_attrname && + !strcmp(attrname, fp->f_attrname)))) { + VREF(vp); + *vpp = vp; + goto fail; + } - if (nip->i_defattrname) - nip->i_flag |= IN_AATTRNAME; - } else { + /* vget node, but don't load it */ + error = ntfs_vgetex(ntmp->ntm_mountp, + iep->ie_number, + attrtype, + attrname, + LK_EXCLUSIVE, + VG_DONTLOAD, + curproc, + &nvp); + if(error) + goto fail; + + nfp = VTOF(nvp); + + nfp->f_fflag = iep->ie_fflag; + nfp->f_pnumber = iep->ie_fpnumber; + nfp->f_times = iep->ie_ftimes; + + if((nfp->f_fflag & NTFS_FFLAG_DIR) && + (nfp->f_attrtype == NTFS_A_DATA) && + (nfp->f_attrname == NULL)) + nfp->f_type = VDIR; + else + nfp->f_type = VREG; + + nvp->v_type = nfp->f_type; + + if ((nfp->f_attrtype == NTFS_A_DATA) && + (nfp->f_attrname == NULL)) { /* Opening default attribute */ - nip->i_size = iep->ie_fsize; - nip->i_allocated = - iep->ie_fallocated; - nip->i_flag |= IN_PRELOADED; + nfp->f_size = iep->ie_fsize; + nfp->f_allocated = iep->ie_fallocated; + nfp->f_flag |= FN_PRELOADED; } - *ipp = nip; + *vpp = nvp; goto fail; } } else if (res > 0) @@ -812,7 +902,7 @@ ntfs_ntlookup( iep->reclen - sizeof(cn_t)); rdsize = blsize; - error = ntfs_breadattr(ntmp, ip, NTFS_A_INDX, "$I30", + error = ntfs_readattr(ntmp, ip, NTFS_A_INDX, "$I30", ntfs_cntob(cn), rdsize, rdbuf); if (error) goto fail; @@ -865,16 +955,14 @@ ntfs_isnamepermitted( return 0; } -/* - * #undef dprintf #define dprintf(a) printf a - */ int ntfs_ntreaddir( struct ntfsmount * ntmp, - struct ntnode * ip, + struct fnode * fp, u_int32_t num, struct attr_indexentry ** riepp) { + struct ntnode *ip = FTONT(fp); struct ntvattr *vap = NULL; /* IndexRoot attribute */ struct ntvattr *bmvap = NULL; /* BitMap attribute */ struct ntvattr *iavap = NULL; /* IndexAllocation attribute */ @@ -894,8 +982,14 @@ ntfs_ntreaddir( if (error) return (ENOTDIR); - blsize = ip->i_dirblsz; - rdbuf = ip->i_dirblbuf; + if (fp->f_dirblbuf == NULL) { + fp->f_dirblsz = vap->va_a_iroot->ir_size; + MALLOC(fp->f_dirblbuf, caddr_t, + max(vap->va_datalen,fp->f_dirblsz), M_NTFSDIR, M_WAITOK); + } + + blsize = fp->f_dirblsz; + rdbuf = fp->f_dirblbuf; dprintf(("ntfs_ntreaddir: rdbuf: 0x%p, blsize: %d\n", rdbuf, blsize)); @@ -907,7 +1001,7 @@ ntfs_ntreaddir( goto fail; } MALLOC(bmp, u_char *, bmvap->va_datalen, M_TEMP, M_WAITOK); - error = ntfs_breadattr(ntmp, ip, NTFS_A_INDXBITMAP, "$I30", 0, + error = ntfs_readattr(ntmp, ip, NTFS_A_INDXBITMAP, "$I30", 0, bmvap->va_datalen, bmp); if (error) goto fail; @@ -928,11 +1022,11 @@ ntfs_ntreaddir( } /* Try use previous values */ - if ((ip->i_lastdnum < num) && (ip->i_lastdnum != 0)) { - attrnum = ip->i_lastdattr; - aoff = ip->i_lastdoff; - blnum = ip->i_lastdblnum; - cnum = ip->i_lastdnum; + if ((fp->f_lastdnum < num) && (fp->f_lastdnum != 0)) { + attrnum = fp->f_lastdattr; + aoff = fp->f_lastdoff; + blnum = fp->f_lastdblnum; + cnum = fp->f_lastdnum; } else { attrnum = NTFS_A_INDXROOT; aoff = sizeof(struct attr_indexroot); @@ -944,7 +1038,7 @@ ntfs_ntreaddir( dprintf(("ntfs_ntreaddir: scan: 0x%x, %d, %d, %d, %d\n", attrnum, (u_int32_t) blnum, cnum, num, aoff)); rdsize = (attrnum == NTFS_A_INDXROOT) ? vap->va_datalen : blsize; - error = ntfs_breadattr(ntmp, ip, attrnum, "$I30", + error = ntfs_readattr(ntmp, ip, attrnum, "$I30", ntfs_cntob(blnum * cpbl), rdsize, rdbuf); if (error) goto fail; @@ -964,10 +1058,10 @@ ntfs_ntreaddir( while (!(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff)) { if (ntfs_isnamepermitted(ntmp, iep)) { if (cnum >= num) { - ip->i_lastdnum = cnum; - ip->i_lastdoff = aoff; - ip->i_lastdblnum = blnum; - ip->i_lastdattr = attrnum; + fp->f_lastdnum = cnum; + fp->f_lastdoff = aoff; + fp->f_lastdblnum = blnum; + fp->f_lastdattr = attrnum; *riepp = iep; @@ -1001,7 +1095,7 @@ ntfs_ntreaddir( } while (iavap); *riepp = NULL; - ip->i_lastdnum = 0; + fp->f_lastdnum = 0; fail: if (vap) @@ -1054,17 +1148,23 @@ ntfs_times( int ntfs_filesize( struct ntfsmount * ntmp, - struct ntnode * ip, + struct fnode * fp, u_int64_t * size, u_int64_t * bytes) { struct ntvattr *vap; + struct ntnode *ip = FTONT(fp); u_int64_t sz, bn; int error; dprintf(("ntfs_filesize: ino: %d\n", ip->i_number)); - error = ntfs_ntvattrget(ntmp, ip, ip->i_defattr, ip->i_defattrname, - 0, &vap); + if (fp->f_flag & FN_DEFAULT) { + error = ntfs_ntvattrget(ntmp, ip, + NTFS_A_DATA, NULL, 0, &vap); + } else { + error = ntfs_ntvattrget(ntmp, ip, + fp->f_attrtype, fp->f_attrname, 0, &vap); + } if (error) return (error); bn = vap->va_allocated; @@ -1084,7 +1184,160 @@ ntfs_filesize( } int -ntfs_breadntvattr_plain( +ntfs_writeattr_plain( + struct ntfsmount * ntmp, + struct ntnode * ip, + u_int32_t attrnum, + char *attrname, + off_t roff, + size_t rsize, + void *rdata, + size_t * initp) +{ + size_t init; + int error = 0; + off_t off = roff, left = rsize, towrite; + caddr_t data = rdata; + struct ntvattr *vap; + *initp = 0; + + while (left) { + error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname, + ntfs_btocn(off), &vap); + if (error) + return (error); + towrite = min(left, ntfs_cntob(vap->va_vcnend + 1) - off); + ddprintf(("ntfs_writeattr_plain: o: %d, s: %d (%d - %d)\n", + (u_int32_t) off, (u_int32_t) towrite, + (u_int32_t) vap->va_vcnstart, + (u_int32_t) vap->va_vcnend)); + error = ntfs_writentvattr_plain(ntmp, ip, vap, + off - ntfs_cntob(vap->va_vcnstart), + towrite, data, &init); + if (error) { + printf("ntfs_writeattr_plain: " \ + "ntfs_writentvattr_plain failed: o: %d, s: %d\n", + (u_int32_t) off, (u_int32_t) towrite); + printf("ntfs_writeattr_plain: attrib: %d - %d\n", + (u_int32_t) vap->va_vcnstart, + (u_int32_t) vap->va_vcnend); + ntfs_ntvattrrele(vap); + break; + } + ntfs_ntvattrrele(vap); + left -= towrite; + off += towrite; + data = data + towrite; + *initp += init; + } + + return (error); +} + +int +ntfs_writentvattr_plain( + struct ntfsmount * ntmp, + struct ntnode * ip, + struct ntvattr * vap, + off_t roff, + size_t rsize, + void *rdata, + size_t * initp) +{ + int error = 0; + int off; + + *initp = 0; + if (vap->va_flag & NTFS_AF_INRUN) { + int cnt; + cn_t ccn, ccl, cn, left, cl; + caddr_t data = rdata; + struct buf *bp; + size_t tocopy; + + ddprintf(("ntfs_writentvattr_plain: data in run: %d chains\n", + vap->va_vruncnt)); + + off = roff; + left = rsize; + ccl = 0; + ccn = 0; + cnt = 0; + while (left && (cnt < vap->va_vruncnt)) { + ccn = vap->va_vruncn[cnt]; + ccl = vap->va_vruncl[cnt]; + + ddprintf(("ntfs_writentvattr_plain: " \ + "left %d, cn: 0x%x, cl: %d, off: %d\n", \ + (u_int32_t) left, (u_int32_t) ccn, \ + (u_int32_t) ccl, (u_int32_t) off)); + + if (ntfs_cntob(ccl) < off) { + off -= ntfs_cntob(ccl); + cnt++; + continue; + } + if (ccn || ip->i_number == NTFS_BOOTINO) { /* XXX */ + ccl -= ntfs_btocn(off); + cn = ccn + ntfs_btocn(off); + off = ntfs_btocnoff(off); + + while (left && ccl) { + tocopy = min(left, + min(ntfs_cntob(ccl) - off, + MAXBSIZE - off)); + cl = ntfs_btocl(tocopy + off); + ddprintf(("ntfs_writentvattr_plain: " \ + "write: cn: 0x%x cl: %d, " \ + "off: %d len: %d, left: %d\n", + (u_int32_t) cn, + (u_int32_t) cl, + (u_int32_t) off, + (u_int32_t) tocopy, + (u_int32_t) left)); + if ((off == 0) && + (tocopy == ntfs_cntob(cl))) { + bp = getblk(ntmp->ntm_devvp, + ntfs_cntobn(cn), + ntfs_cntob(cl), + 0, 0); + clrbuf(bp); + } else { + error = bread(ntmp->ntm_devvp, + ntfs_cntobn(cn), + ntfs_cntob(cl), + NOCRED, &bp); + if (error) { + brelse(bp); + return (error); + } + } + memcpy(bp->b_data + off, data, tocopy); + bwrite(bp); + data = data + tocopy; + *initp += tocopy; + off = 0; + left -= tocopy; + cn += cl; + ccl -= cl; + } + } + cnt++; + } + if (left) { + printf("ntfs_writentvattr_plain: POSSIBLE RUN ERROR\n"); + error = EINVAL; + } + } else { + printf("ntfs_writevattr_plain: CAN'T WRITE RES. ATTRIBUTE\n"); + error = ENOTTY; + } + + return (error); +} + +int +ntfs_readntvattr_plain( struct ntfsmount * ntmp, struct ntnode * ip, struct ntvattr * vap, @@ -1104,7 +1357,7 @@ ntfs_breadntvattr_plain( struct buf *bp; size_t tocopy; - ddprintf(("ntfs_breadntvattr_plain: data in run: %d chains\n", + ddprintf(("ntfs_readntvattr_plain: data in run: %d chains\n", vap->va_vruncnt)); off = roff; @@ -1116,7 +1369,7 @@ ntfs_breadntvattr_plain( ccn = vap->va_vruncn[cnt]; ccl = vap->va_vruncl[cnt]; - ddprintf(("ntfs_breadntvattr_plain: " \ + ddprintf(("ntfs_readntvattr_plain: " \ "left %d, cn: 0x%x, cl: %d, off: %d\n", \ (u_int32_t) left, (u_int32_t) ccn, \ (u_int32_t) ccl, (u_int32_t) off)); @@ -1136,7 +1389,7 @@ ntfs_breadntvattr_plain( min(ntfs_cntob(ccl) - off, MAXBSIZE - off)); cl = ntfs_btocl(tocopy + off); - ddprintf(("ntfs_breadntvattr_plain: " \ + ddprintf(("ntfs_readntvattr_plain: " \ "read: cn: 0x%x cl: %d, " \ "off: %d len: %d, left: %d\n", (u_int32_t) cn, @@ -1163,7 +1416,7 @@ ntfs_breadntvattr_plain( } } else { tocopy = min(left, ntfs_cntob(ccl) - off); - ddprintf(("ntfs_breadntvattr_plain: " + ddprintf(("ntfs_readntvattr_plain: " "sparce: ccn: 0x%x ccl: %d, off: %d, " \ " len: %d, left: %d\n", (u_int32_t) ccn, (u_int32_t) ccl, @@ -1177,11 +1430,11 @@ ntfs_breadntvattr_plain( cnt++; } if (left) { - printf("ntfs_breadntvattr_plain: POSSIBLE RUN ERROR\n"); + printf("ntfs_readntvattr_plain: POSSIBLE RUN ERROR\n"); error = E2BIG; } } else { - ddprintf(("ntfs_breadnvattr_plain: data is in mft record\n")); + ddprintf(("ntfs_readnvattr_plain: data is in mft record\n")); memcpy(rdata, vap->va_datap + roff, rsize); *initp += rsize; } @@ -1190,7 +1443,7 @@ ntfs_breadntvattr_plain( } int -ntfs_breadattr_plain( +ntfs_readattr_plain( struct ntfsmount * ntmp, struct ntnode * ip, u_int32_t attrnum, @@ -1213,18 +1466,18 @@ ntfs_breadattr_plain( if (error) return (error); toread = min(left, ntfs_cntob(vap->va_vcnend + 1) - off); - ddprintf(("ntfs_breadattr_plain: o: %d, s: %d (%d - %d)\n", + ddprintf(("ntfs_readattr_plain: o: %d, s: %d (%d - %d)\n", (u_int32_t) off, (u_int32_t) toread, (u_int32_t) vap->va_vcnstart, (u_int32_t) vap->va_vcnend)); - error = ntfs_breadntvattr_plain(ntmp, ip, vap, + error = ntfs_readntvattr_plain(ntmp, ip, vap, off - ntfs_cntob(vap->va_vcnstart), toread, data, &init); if (error) { - printf("ntfs_breadattr_plain: " \ - "ntfs_breadntvattr_plain failed: o: %d, s: %d\n", + printf("ntfs_readattr_plain: " \ + "ntfs_readntvattr_plain failed: o: %d, s: %d\n", (u_int32_t) off, (u_int32_t) toread); - printf("ntfs_breadattr_plain: attrib: %d - %d\n", + printf("ntfs_readattr_plain: attrib: %d - %d\n", (u_int32_t) vap->va_vcnstart, (u_int32_t) vap->va_vcnend); ntfs_ntvattrrele(vap); @@ -1241,7 +1494,7 @@ ntfs_breadattr_plain( } int -ntfs_breadattr( +ntfs_readattr( struct ntfsmount * ntmp, struct ntnode * ip, u_int32_t attrnum, @@ -1254,7 +1507,7 @@ ntfs_breadattr( struct ntvattr *vap; size_t init; - ddprintf(("ntfs_breadattr: reading %d: 0x%x, from %d size %d bytes\n", + ddprintf(("ntfs_readattr: reading %d: 0x%x, from %d size %d bytes\n", ip->i_number, attrnum, (u_int32_t) roff, (u_int32_t) rsize)); error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname, 0, &vap); @@ -1263,7 +1516,7 @@ ntfs_breadattr( if ((roff > vap->va_datalen) || (roff + rsize > vap->va_datalen)) { - ddprintf(("ntfs_breadattr: offset too big\n")); + ddprintf(("ntfs_readattr: offset too big\n")); ntfs_ntvattrrele(vap); return (E2BIG); } @@ -1286,7 +1539,7 @@ ntfs_breadattr( off = roff - ntfs_cntob(cn); while (left) { - error = ntfs_breadattr_plain(ntmp, ip, attrnum, + error = ntfs_readattr_plain(ntmp, ip, attrnum, attrname, ntfs_cntob(cn), ntfs_cntob(NTFS_COMPUNIT_CL), cup, &init); @@ -1315,7 +1568,7 @@ ntfs_breadattr( FREE(uup, M_NTFSDECOMP); FREE(cup, M_NTFSDECOMP); } else - error = ntfs_breadattr_plain(ntmp, ip, attrnum, attrname, + error = ntfs_readattr_plain(ntmp, ip, attrnum, attrname, roff, rsize, rdata, &init); ntfs_ntvattrrele(vap); return (error); @@ -1326,14 +1579,14 @@ ntfs_parserun( cn_t * cn, cn_t * cl, u_int8_t * run, - size_t len, - int *off) + u_long len, + u_long *off) { u_int8_t sz; int i; if (NULL == run) { - printf("ntfs_runtocn: run == NULL\n"); + printf("ntfs_parsetun: run == NULL\n"); return (EINVAL); } sz = run[(*off)++]; @@ -1344,7 +1597,7 @@ ntfs_parserun( *cl = 0; if ((sz & 0xF) > 8 || (*off) + (sz & 0xF) > len) { printf("ntfs_parserun: " \ - "bad run: length too big: %02x (%x < %x + sz)\n", + "bad run: length too big: sz: 0x%02x (%ld < %ld + sz)\n", sz, len, *off); return (EINVAL); } @@ -1354,7 +1607,7 @@ ntfs_parserun( sz >>= 4; if ((sz & 0xF) > 8 || (*off) + (sz & 0xF) > len) { printf("ntfs_parserun: " \ - "bad run: offset too big: %02x (%x < %x + sz)\n", + "bad run: length too big: sz: 0x%02x (%ld < %ld + sz)\n", sz, len, *off); return (EINVAL); } @@ -1411,18 +1664,18 @@ ntfs_runtocn( cn_t * cn, struct ntfsmount * ntmp, u_int8_t * run, - size_t len, + u_long len, cn_t vcn) { cn_t ccn = 0; cn_t ccl = 0; - int off = 0; + u_long off = 0; int error = 0; #if NTFS_DEBUG int i; - printf("ntfs_runtocn: " \ - "run: 0x%p, %d bytes, vcn:%d\n", run, len, (u_int32_t) vcn); + printf("ntfs_runtocn: run: 0x%p, %ld bytes, vcn:%ld\n", + run, len, (u_long) vcn); printf("ntfs_runtocn: run: "); for (i = 0; i < len; i++) printf("0x%02x ", run[i]); diff --git a/sys/ntfs/ntfs_subr.h b/sys/ntfs/ntfs_subr.h index 94cef19..692bb54 100644 --- a/sys/ntfs/ntfs_subr.h +++ b/sys/ntfs/ntfs_subr.h @@ -26,10 +26,14 @@ * $Id: ntfs_subr.h,v 1.3 1999/02/02 01:54:54 semen Exp $ */ +#define VA_LOADED 0x0001 +#define VA_PRELOADED 0x0002 + struct ntvattr { struct ntvattr *va_nextp; u_int32_t va_vflag; + struct vnode *va_vp; struct ntnode *va_ip; u_int32_t va_flag; @@ -48,7 +52,7 @@ struct ntvattr { struct { cn_t * cn; cn_t * cl; - u_int32_t cnt; + u_long cnt; } vrun; caddr_t datap; struct attr_name *name; @@ -67,30 +71,41 @@ struct ntvattr { #define uastrcmp(a,b,c,d) ntfs_uastrcmp(ntmp,a,b,c,d) +#ifndef NTFS_DEBUG +#define ntfs_ntref(i) (i)->i_usecount++ +#else +#define ntfs_ntref(i) { \ + printf("ntfs_ntref: ino %d, usecount: %d\n", \ + (i)->i_number, (i)->i_usecount++); \ +} +#endif + int ntfs_procfixups __P(( struct ntfsmount *, u_int32_t, caddr_t, size_t )); -int ntfs_parserun __P(( cn_t *, cn_t *, u_int8_t *, size_t, int *)); -int ntfs_runtocn __P(( cn_t *, struct ntfsmount *, u_int8_t *, size_t, cn_t)); -int ntfs_breadntvattr_plain __P(( struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *,size_t *)); -int ntfs_breadattr_plain __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *,size_t *)); -int ntfs_breadattr __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *)); -int ntfs_filesize __P(( struct ntfsmount *, struct ntnode *, u_int64_t *, u_int64_t *)); +int ntfs_parserun __P(( cn_t *, cn_t *, u_int8_t *, u_long, u_long *)); +int ntfs_runtocn __P(( cn_t *, struct ntfsmount *, u_int8_t *, u_long, cn_t)); +int ntfs_readntvattr_plain __P(( struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *,size_t *)); +int ntfs_readattr_plain __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *,size_t *)); +int ntfs_readattr __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *)); +int ntfs_filesize __P(( struct ntfsmount *, struct fnode *, u_int64_t *, u_int64_t *)); int ntfs_times __P(( struct ntfsmount *, struct ntnode *, ntfs_times_t *)); struct timespec ntfs_nttimetounix __P(( u_int64_t )); -int ntfs_ntreaddir __P(( struct ntfsmount *, struct ntnode *, u_int32_t, struct attr_indexentry **)); +int ntfs_ntreaddir __P(( struct ntfsmount *, struct fnode *, u_int32_t, struct attr_indexentry **)); wchar ntfs_toupper __P(( struct ntfsmount *, wchar )); int ntfs_uustricmp __P(( struct ntfsmount *, wchar *, int, wchar *, int )); int ntfs_uastricmp __P(( struct ntfsmount *, wchar *, int, char *, int )); int ntfs_uastrcmp __P(( struct ntfsmount *, wchar *, int, char *, int )); -int ntfs_runtovrun __P(( cn_t **, cn_t **, u_int32_t *, u_int8_t *)); +int ntfs_runtovrun __P(( cn_t **, cn_t **, u_long *, u_int8_t *)); int ntfs_attrtontvattr __P(( struct ntfsmount *, struct ntvattr **, struct attr * )); void ntfs_freentvattr __P(( struct ntvattr * )); int ntfs_loadntvattrs __P(( struct ntfsmount *, struct vnode *, caddr_t, struct ntvattr **)); struct ntvattr * ntfs_findntvattr __P(( struct ntfsmount *, struct ntnode *, u_int32_t, cn_t )); -int ntfs_ntlookup __P(( struct ntfsmount *, struct ntnode *, struct componentname *, struct ntnode **)); +int ntfs_ntlookup __P(( struct ntfsmount *, struct vnode *, struct componentname *, struct vnode **)); int ntfs_isnamepermitted __P(( struct ntfsmount *, struct attr_indexentry * )); int ntfs_ntvattrrele __P(( struct ntvattr * )); int ntfs_ntvattrget __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, cn_t , struct ntvattr **)); int ntfs_ntget __P(( struct ntfsmount *, ino_t, struct ntnode **)); void ntfs_ntrele __P(( struct ntnode *)); -int ntfs_loadnode __P(( struct ntfsmount *, struct ntnode * )); -int ntfs_ntlookupattr __P(( struct ntfsmount *, char *, int, int *, char **)); +int ntfs_loadntnode __P(( struct ntfsmount *, struct ntnode * )); +int ntfs_ntlookupattr(struct ntfsmount *, char *, int, int *, char **); +int ntfs_writentvattr_plain(struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *, size_t *); +int ntfs_writeattr_plain(struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *, size_t *); diff --git a/sys/ntfs/ntfs_vfsops.c b/sys/ntfs/ntfs_vfsops.c index b3ccf0a..a371319 100644 --- a/sys/ntfs/ntfs_vfsops.c +++ b/sys/ntfs/ntfs_vfsops.c @@ -52,12 +52,15 @@ #include <ntfs/ntfs.h> #include <ntfs/ntfs_inode.h> #include <ntfs/ntfs_subr.h> +#include <ntfs/ntfs_vfsops.h> +#include <ntfs/ntfs_ihash.h> #include <ntfs/ntfs_extern.h> #include <ntfs/ntfsmount.h> #if __FreeBSD_version >= 300000 MALLOC_DEFINE(M_NTFSMNT, "NTFS mount", "NTFS mount structure"); -MALLOC_DEFINE(M_NTFSNODE,"NTFS node", "NTFS node information"); +MALLOC_DEFINE(M_NTFSNTNODE,"NTFS ntnode", "NTFS ntnode information"); +MALLOC_DEFINE(M_NTFSFNODE,"NTFS fnode", "NTFS fnode information"); MALLOC_DEFINE(M_NTFSDIR,"NTFS dir", "NTFS dir buffer"); #endif @@ -106,7 +109,7 @@ ntfs_init () printf("ntfs_init(): \n"); - ntfs_ihashinit(); + ntfs_nthashinit(); return 0; } @@ -411,7 +414,13 @@ ntfs_mountfs(devvp, mp, argsp, p) printf("ntfs_mountfs(): reading system nodes...\n"); { i = NTFS_MFTINO; - error = VFS_VGET(mp, i, &ntmp->ntm_sysvn[i]); + error = VFS_VGET(mp, i, &(ntmp->ntm_sysvn[i])); + if(error) + goto out1; + VREF(ntmp->ntm_sysvn[i]); + vput(ntmp->ntm_sysvn[i]); + i = NTFS_ROOTINO; + error = VFS_VGET(mp, i, &(ntmp->ntm_sysvn[i])); if(error) goto out1; VREF(ntmp->ntm_sysvn[i]); @@ -426,7 +435,7 @@ ntfs_mountfs(devvp, mp, argsp, p) if(error) goto out1; printf("ntfs_mountfs(): reading $UpCase\n"); - error = ntfs_breadattr( ntmp, VTONT(vp), NTFS_A_DATA, NULL, + error = ntfs_readattr( ntmp, VTONT(vp), NTFS_A_DATA, NULL, 0, 65536*sizeof(wchar), ntmp->ntm_upcase); printf("ntfs_mountfs(): closing $UpCase\n"); vput(vp); @@ -443,7 +452,7 @@ ntfs_mountfs(devvp, mp, argsp, p) goto out1; for(num=0;;num++) { - error = ntfs_breadattr(ntmp, VTONT(vp), + error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, num * sizeof(ad), sizeof(ad), &ad); @@ -461,7 +470,7 @@ ntfs_mountfs(devvp, mp, argsp, p) ntmp->ntm_adnum = num; for(i=0;i<num;i++){ - error = ntfs_breadattr(ntmp, VTONT(vp), + error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, i * sizeof(ad), sizeof(ad), &ad); @@ -537,13 +546,16 @@ ntfs_unmount( flags |= FORCECLOSE; printf("ntfs_unmount: vflushing...\n"); - for(i=0;i<NTFS_SYSNODESNUM;i++) - if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); - error = vflush(mp,NULLVP,flags); + error = vflush(mp,NULLVP,flags | SKIPSYSTEM); if (error) { printf("ntfs_unmount: vflush failed: %d\n",error); return (error); } + for(i=0;i<NTFS_SYSNODESNUM;i++) + if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); + error = vflush(mp,NULLVP,flags); + if (error) + printf("ntfs_unmount: vflush failed: %d\n",error); #if __FreeBSD_version >= 300000 ntmp->ntm_devvp->v_specmountpoint = NULL; @@ -578,7 +590,8 @@ ntfs_root( struct vnode *nvp; int error = 0; - dprintf(("ntfs_root():\n")); + dprintf(("ntfs_root(): sysvn: %p\n", + VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO])); error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, &nvp); if(error) { printf("ntfs_root: VFS_VGET failed: %d\n",error); @@ -615,18 +628,18 @@ ntfs_statfs( dprintf(("ntfs_statfs():")); - ntfs_filesize(ntmp, VTONT(ntmp->ntm_sysvn[NTFS_MFTINO]), + ntfs_filesize(ntmp, VTOF(ntmp->ntm_sysvn[NTFS_MFTINO]), &mftsize, &mftallocated); error = VFS_VGET(mp, NTFS_BITMAPINO, &vp); if(error) return (error); - ntfs_filesize(ntmp, VTONT(vp), &bmsize, &bmallocated); + ntfs_filesize(ntmp, VTOF(vp), &bmsize, &bmallocated); MALLOC(tmp, u_int8_t *, bmsize,M_TEMP, M_WAITOK); - error = ntfs_breadattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, + error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, 0, bmsize, tmp); if(error) { FREE(tmp, M_TEMP); @@ -660,6 +673,7 @@ ntfs_statfs( bcopy((caddr_t)mp->mnt_stat.f_mntfromname, (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); } + sbp->f_flags = mp->mnt_flag; return (0); } @@ -708,58 +722,107 @@ ntfs_vptofh( return EOPNOTSUPP; } -static int -ntfs_vget( +int +ntfs_vgetex( struct mount *mp, ino_t ino, + u_int32_t attrtype, + char *attrname, + u_long lkflags, + u_long flags, + struct proc *p, struct vnode **vpp) { - int error=0; - struct vnode *vp; + int error; register struct ntfsmount *ntmp; struct ntnode *ip; + struct fnode *fp; + struct vnode *vp; - dprintf(("ntfs_vget: ino: %d\n",ino)); + dprintf(("ntfs_vgetex: ino: %d, attr: 0x%x:%s, lkf: 0x%x, f: 0x%x\n", + ino, attrtype, attrname?attrname:"", lkflags, flags )); ntmp = VFSTONTFS(mp); + *vpp = NULL; - *vpp = NULL; - - dprintf(("ntfs_ntvget: ihashlookup\n")); - if( (*vpp = ntfs_ihashget(ntmp->ntm_dev, ino)) != NULL ) - return (0); - - error = ntfs_ntget(ntmp,ino,&ip); - if(error) { + /* Get ntnode */ + error = ntfs_ntget(ntmp, ino, &ip); + if (error) { printf("ntfs_vget: ntfs_ntget failed\n"); return (error); } - error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, &vp); - if(error) { - /* XXX */ + error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp); + if (error) { + printf("ntfs_vget: ntfs_fget failed\n"); ntfs_ntrele(ip); return (error); } - ip->i_vnode = vp; - vp->v_data = ip; - vp->v_type = ip->i_type; - ntfs_ihashins(ip); + if (FTOV(fp)) { + vget(FTOV(fp), lkflags, p); + *vpp = FTOV(fp); + ntfs_ntrele(ip); + return (0); + } - VREF(ip->i_devvp); + /* It may be not initialized fully, so force load it */ + if (!(flags & VG_DONTLOAD) && !(ip->i_flag & IN_LOADED)) { + error = ntfs_loadntnode(ntmp, ip); + if(error) { + printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n", + ip->i_number); + ntfs_ntrele(ip); + return (error); + } + } - error = ntfs_loadnode(ntmp, ip); + error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, &vp); if(error) { - printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n", - ip->i_number); - vput(vp); + ntfs_frele(fp); + ntfs_ntrele(ip); return (error); } + dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino)); - *vpp = vp; + lockinit(&fp->f_lock, PINOD, "fnode", 0, 0); + fp->f_vp = vp; + vp->v_data = fp; + + if (ip->i_frflag & NTFS_FRFLAG_DIR) + vp->v_type = fp->f_type = VDIR; + else + vp->v_type = fp->f_type = VREG; + if (ino == NTFS_ROOTINO) + vp->v_flag |= VROOT; + if (ino < NTFS_SYSNODESNUM) + vp->v_flag |= VSYSTEM; + + ntfs_ntrele(ip); + + if (lkflags & LK_TYPE_MASK) { + error = vn_lock(vp, lkflags, p); + if (error) { + vput(vp); + return (error); + } + } + + VREF(fp->f_devvp); + *vpp = vp; return (0); + +} + +static int +ntfs_vget( + struct mount *mp, + ino_t ino, + struct vnode **vpp) +{ + return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL, + LK_EXCLUSIVE, 0, curproc, vpp); } #if __FreeBSD_version >= 300000 diff --git a/sys/ntfs/ntfs_vfsops.h b/sys/ntfs/ntfs_vfsops.h new file mode 100644 index 0000000..c8788c4 --- /dev/null +++ b/sys/ntfs/ntfs_vfsops.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: ntfs_vfsops.h,v 1.1 1999/02/02 01:54:54 semen Exp $ + */ +#define VG_DONTLOAD 0x0001 /* Tells ntfs_vgetex to do not call */ + /* ntfs_loadnode on ntnode, even if */ + /* ntnode not loaded */ + +int ntfs_vgetex(struct mount *, ino_t, u_int32_t, char *, u_long, u_long, + struct proc *, struct vnode **); diff --git a/sys/ntfs/ntfs_vnops.c b/sys/ntfs/ntfs_vnops.c index b5394fe..f1a822a 100644 --- a/sys/ntfs/ntfs_vnops.c +++ b/sys/ntfs/ntfs_vnops.c @@ -33,7 +33,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ntfs_vnops.c,v 1.9 1999/02/02 01:54:55 semen Exp $ + * $Id: ntfs_vnops.c,v 1.10 1999/02/02 03:15:13 semen Exp $ * */ @@ -66,11 +66,12 @@ #include <ntfs/ntfs.h> #include <ntfs/ntfs_inode.h> #include <ntfs/ntfs_subr.h> +#include <ntfs/ntfs_extern.h> #include <miscfs/specfs/specdev.h> static int ntfs_bypass __P((struct vop_generic_args *ap)); static int ntfs_read __P((struct vop_read_args *)); -static int ntfs_bwrite __P((struct vop_bwrite_args *ap)); +static int ntfs_write __P((struct vop_write_args *ap)); static int ntfs_getattr __P((struct vop_getattr_args *ap)); static int ntfs_inactive __P((struct vop_inactive_args *ap)); static int ntfs_print __P((struct vop_print_args *ap)); @@ -88,120 +89,25 @@ static int ntfs_readdir __P((struct vop_readdir_args *ap)); static int ntfs_lookup __P((struct vop_lookup_args *ap)); static int ntfs_bmap __P((struct vop_bmap_args *ap)); static int ntfs_getpages __P((struct vop_getpages_args *ap)); +static int ntfs_putpages __P((struct vop_putpages_args *)); static int ntfs_fsync __P((struct vop_fsync_args *ap)); int ntfs_prtactive = 1; /* 1 => print out reclaim of active vnodes */ -/* - * Vnode op for VM getpages. - */ int ntfs_getpages(ap) struct vop_getpages_args *ap; { - int i, error, nextoff, size, toff, npages, count; - struct uio uio; - struct iovec iov; - vm_offset_t kva; - struct buf *bp; - struct vnode *vp; - struct proc *p; - struct ucred *cred; - struct ntfsmount *ntmp; - vm_page_t *pages; - - vp = ap->a_vp; - p = curproc; /* XXX */ - cred = curproc->p_ucred; /* XXX */ - ntmp = VFSTONTFS(vp->v_mount); - pages = ap->a_m; - count = ap->a_count; - - if (vp->v_object == NULL) { - printf("ntfs_getpages: called with non-merged cache vnode??\n"); - return VM_PAGER_ERROR; - } - - /* - * We use only the kva address for the buffer, but this is extremely - * convienient and fast. - */ -#if __FreeBSD_version >= 400000 - bp = getpbuf(NULL); -#else - bp = getpbuf(); -#endif - - npages = btoc(count); - kva = (vm_offset_t) bp->b_data; - pmap_qenter(kva, pages, npages); - - iov.iov_base = (caddr_t) kva; - iov.iov_len = count; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = IDX_TO_OFF(pages[0]->pindex); - uio.uio_resid = count; - uio.uio_segflg = UIO_SYSSPACE; - uio.uio_rw = UIO_READ; - uio.uio_procp = p; - - error = VOP_READ(vp, &uio, 0, cred); - pmap_qremove(kva, npages); - -#if __FreeBSD_version >= 400000 - relpbuf(bp,NULL); -#else - relpbuf(bp); -#endif - - if (error && (uio.uio_resid == count)) - return VM_PAGER_ERROR; - - size = count - uio.uio_resid; - - for (i = 0, toff = 0; i < npages; i++, toff = nextoff) { - vm_page_t m; - nextoff = toff + PAGE_SIZE; - m = pages[i]; - - m->flags &= ~PG_ZERO; + return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count, + ap->a_reqpage); +} - if (nextoff <= size) { - m->valid = VM_PAGE_BITS_ALL; - m->dirty = 0; - } else { - int nvalid = ((size + DEV_BSIZE - 1) - toff) & ~(DEV_BSIZE - 1); - vm_page_set_validclean(m, 0, nvalid); - } - - if (i != ap->a_reqpage) { - /* - * Whether or not to leave the page activated is up in - * the air, but we should put the page on a page queue - * somewhere (it already is in the object). Result: - * It appears that emperical results show that - * deactivating pages is best. - */ - - /* - * Just in case someone was asking for this page we - * now tell them that it is ok to use. - */ - if (!error) { - if (m->flags & PG_WANTED) - vm_page_activate(m); - else - vm_page_deactivate(m); -#if __FreeBSD_version >= 300000 - vm_page_wakeup(m); -#endif - } else { - vnode_pager_freepage(m); - } - } - } - return 0; +int +ntfs_putpages(ap) + struct vop_putpages_args *ap; +{ + return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count, + ap->a_sync, ap->a_rtvals); } /* @@ -218,6 +124,7 @@ ntfs_bmap(ap) int *a_runb; } */ *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) @@ -239,7 +146,8 @@ ntfs_read(ap) } */ *ap; { register struct vnode *vp = ap->a_vp; - register struct ntnode *ip = VTONT(vp); + register struct fnode *fp = VTOF(vp); + register struct ntnode *ip = FTONT(fp); struct uio *uio = ap->a_uio; struct ntfsmount *ntmp = ip->i_mp; u_int8_t *data; @@ -248,7 +156,7 @@ ntfs_read(ap) dprintf(("ntfs_read: ino: %d, off: %d resid: %d, segflg: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg)); - ntfs_filesize( ntmp, ip, &toread, NULL ); + ntfs_filesize(ntmp, fp, &toread, NULL); dprintf(("ntfs_read: filesize: %d",(u_int32_t)toread)); toread = min( uio->uio_resid, toread - uio->uio_offset ); @@ -257,16 +165,17 @@ ntfs_read(ap) MALLOC(data, u_int8_t *, toread, M_TEMP,M_WAITOK); - error = ntfs_breadattr( ntmp, ip, ip->i_defattr, ip->i_defattrname, - uio->uio_offset, toread, data ); + error = ntfs_readattr( ntmp, ip, fp->f_attrtype, + fp->f_attrname, uio->uio_offset, toread, data); if(error) { - printf("ntfs_read: ntfs_breadattr failed: %d\n",error); + printf("ntfs_read: ntfs_readattr failed: %d\n",error); FREE(data, M_TEMP); return (error); } error = uiomove(data, (int) toread, uio); if(error) { + printf("ntfs_read: uiomove failed: %d\n",error); FREE(data, M_TEMP); return (error); } @@ -284,7 +193,7 @@ ntfs_bypass(ap) } */ *ap; { int error = ENOTTY; - dprintf (("ntfs_bypass: %s\n", ap->a_desc->vdesc_name)); + dprintf(("ntfs_bypass: %s\n", ap->a_desc->vdesc_name)); return (error); } @@ -299,33 +208,28 @@ ntfs_getattr(ap) } */ *ap; { register struct vnode *vp = ap->a_vp; - register struct ntnode *ip = VTONT(vp); + register struct fnode *fp = VTOF(vp); + register struct ntnode *ip = FTONT(fp); register struct vattr *vap = ap->a_vap; - int error; dprintf(("ntfs_getattr: %d, flags: %d\n",ip->i_number,ip->i_flag)); - if ((ip->i_flag & (IN_LOADED | IN_PRELOADED)) == 0) { - error = ntfs_loadnode(ip->i_mp,ip); - if (error) - return error; - } - vap->va_fsid = ip->i_dev; + vap->va_fsid = fp->f_dev; vap->va_fileid = ip->i_number; vap->va_mode = ip->i_mode; vap->va_nlink = ip->i_nlink; vap->va_uid = ip->i_uid; vap->va_gid = ip->i_gid; vap->va_rdev = (dev_t)0; - vap->va_size = ip->i_size; - vap->va_bytes = ip->i_allocated; - vap->va_atime = ntfs_nttimetounix(ip->i_times.t_access); - vap->va_mtime = ntfs_nttimetounix(ip->i_times.t_write); - vap->va_ctime = ntfs_nttimetounix(ip->i_times.t_create); + vap->va_size = fp->f_size; + vap->va_bytes = fp->f_allocated; + vap->va_atime = ntfs_nttimetounix(fp->f_times.t_access); + vap->va_mtime = ntfs_nttimetounix(fp->f_times.t_write); + vap->va_ctime = ntfs_nttimetounix(fp->f_times.t_create); vap->va_flags = ip->i_flag; vap->va_gen = 0; vap->va_blocksize = ip->i_mp->ntm_spc * ip->i_mp->ntm_bps; - vap->va_type = ip->i_type; + vap->va_type = fp->f_type; vap->va_filerev = 0; return (0); } @@ -346,8 +250,7 @@ ntfs_inactive(ap) #endif int error; - dprintf(("ntfs_inactive: %d (%d locks)\n", - ip->i_number,ip->i_lockcount)); + dprintf(("ntfs_inactive: vnode: %p, ntnode: %d\n", vp, ip->i_number)); if (ntfs_prtactive && vp->v_usecount != 0) vprint("ntfs_inactive: pushing active", vp); @@ -391,34 +294,25 @@ ntfs_reclaim(ap) } */ *ap; { register struct vnode *vp = ap->a_vp; - register struct ntnode *ip = VTONT(vp); + register struct fnode *fp = VTOF(vp); +#if NTFS_DEBUG + register struct ntnode *ip = FTONT(fp); +#endif - dprintf(("ntfs_reclaim: reclaim: %d\n",ip->i_number)); + dprintf(("ntfs_reclaim: vnode: %p, ntnode: %d\n", vp, ip->i_number)); #if __FreeBSD_version >= 300000 VOP_UNLOCK(vp,0,ap->a_p); #endif - if(ip->i_dirblbuf) { - FREE(ip->i_dirblbuf, M_NTFSDIR); - ip->i_dirblbuf = NULL; - } - - /* - * Remove the inode from its hash chain. - */ - ntfs_ihashrem(ip); - - /* - * Purge old data structures associated with the inode. - */ + /* Purge old data structures associated with the inode. */ cache_purge(vp); - if (ip->i_devvp) { - vrele(ip->i_devvp); - ip->i_devvp = 0; + if (fp->f_devvp) { + vrele(fp->f_devvp); + fp->f_devvp = NULL; } - ntfs_ntrele(ip); + ntfs_frele(fp); vp->v_data = NULL; @@ -447,47 +341,126 @@ ntfs_strategy(ap) } */ *ap; { register struct buf *bp = ap->a_bp; - struct ucred *cr; - struct proc *p; - int error = 0; - - dprintf(("strategy: data: %p, npages: %d,dirty: %d\n",bp->b_data,bp->b_npages,bp->b_dirtyend)); - if (bp->b_flags & B_PHYS) - panic("ntfs physio"); - if (bp->b_flags & B_ASYNC) - p = (struct proc *)0; - else - p = curproc; /* XXX */ - if (bp->b_flags & B_READ) - cr = bp->b_rcred; - else - cr = bp->b_wcred; - /* - * If the op is asynchronous and an i/o daemon is waiting - * queue the request, wake it up and wait for completion - * otherwise just do it ourselves. - */ -/* - if ((bp->b_flags & B_ASYNC) == 0 || - nfs_asyncio(bp, NOCRED)) - error = nfs_doio(bp, cr, p); -*/ + register struct vnode *vp = bp->b_vp; + register struct fnode *fp = VTOF(vp); + register struct ntnode *ip = FTONT(fp); + struct ntfsmount *ntmp = ip->i_mp; + int error; + + 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)); + dprintf(("strategy: bcount: %d flags: 0x%x\n", + (u_int32_t)bp->b_bcount,bp->b_flags)); + + if (bp->b_flags & B_READ) { + u_int32_t toread; + + if (ntfs_cntob(bp->b_blkno) >= fp->f_size) { + clrbuf(bp); + error = 0; + } else { + toread = min(bp->b_bcount, + fp->f_size-ntfs_cntob(bp->b_blkno)); + 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), + toread, bp->b_data); + + if (error) { + printf("ntfs_strategy: ntfs_readattr failed\n"); + bp->b_error = error; + bp->b_flags |= B_ERROR; + } + + bzero(bp->b_data + toread, bp->b_bcount - toread); + } + } else { + size_t tmp; + u_int32_t towrite; - return (ENOTTY); + if (ntfs_cntob(bp->b_blkno) + 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)); + 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, + bp->b_data, &tmp); + + if (error) { + printf("ntfs_strategy: ntfs_writeattr fail\n"); + bp->b_error = error; + bp->b_flags |= B_ERROR; + } + } + } + biodone(bp); return (error); } static int -ntfs_bwrite(ap) - struct vop_bwrite_args /* { - struct buf *a_bp; +ntfs_write(ap) + struct vop_write_args /* { + struct vnode *a_vp; + struct uio *a_uio; + int a_ioflag; + struct ucred *a_cred; } */ *ap; { - int error = ENOTTY; + register struct vnode *vp = ap->a_vp; + register struct fnode *fp = VTOF(vp); + register struct ntnode *ip = FTONT(fp); + struct uio *uio = ap->a_uio; + struct ntfsmount *ntmp = ip->i_mp; + u_int8_t *data; + u_int64_t towrite; + off_t off; + size_t written; + int error; - printf("ntfs_bwrite: \n"); + dprintf(("ntfs_write: ino: %d, off: %d resid: %d, segflg: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg)); - return (error); + ntfs_filesize(ntmp, fp, &towrite, NULL); + + if (uio->uio_resid + uio->uio_offset > towrite) { + printf("ntfs_write: CAN'T WRITE BEYOND OF FILE\n"); + return (EFBIG); + } + + dprintf(("ntfs_write: filesize: %d",(u_int32_t)towrite)); + + towrite = min(uio->uio_resid, towrite - uio->uio_offset); + off = uio->uio_offset; + + dprintf((", towrite: %d\n",(u_int32_t)towrite)); + + MALLOC(data, u_int8_t *, towrite, M_TEMP,M_WAITOK); + + error = uiomove(data, (int) towrite, uio); + if(error) { + FREE(data, M_TEMP); + return (error); + } + + error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype, + fp->f_attrname, off, towrite, data, &written); + if(error) { + printf("ntfs_write: ntfs_writeattr failed: %d\n",error); + FREE(data, M_TEMP); + return (error); + } + + FREE(data, M_TEMP); + + return (0); } #if __FreeBSD_version < 300000 @@ -502,7 +475,7 @@ ntfs_islocked(ap) { register struct ntnode *ip = VTONT(ap->a_vp); - dprintf(("ntfs_islocked %d (%d locks)\n",ip->i_number,ip->i_lockcount)); + dprintf(("ntfs_islocked %d\n",ip->i_number)); if (ip->i_flag & IN_LOCKED) return (1); @@ -522,7 +495,7 @@ ntfs_unlock(ap) register struct ntnode *ip = VTONT(ap->a_vp); struct proc *p = curproc; - dprintf(("ntfs_unlock %d (%d locks)\n",ip->i_number,ip->i_lockcount)); + dprintf(("ntfs_unlock %d\n",ip->i_number)); #ifdef DIAGNOSTIC @@ -639,7 +612,7 @@ ntfs_access(ap) * character device resident on the file system. */ if (mode & VWRITE) { - switch (vp->v_type) { + switch ((int)vp->v_type) { case VDIR: case VLNK: case VREG: @@ -717,7 +690,7 @@ ntfs_open(ap) register struct vnode *vp = ap->a_vp; register struct ntnode *ip = VTONT(vp); - printf("ntfs_open: %d (%d locks)\n",ip->i_number,ip->i_lockcount); + printf("ntfs_open: %d\n",ip->i_number); #endif /* @@ -746,7 +719,7 @@ ntfs_close(ap) register struct vnode *vp = ap->a_vp; register struct ntnode *ip = VTONT(vp); - printf("ntfs_close: %d (%d locks)\n",ip->i_number,ip->i_lockcount); + printf("ntfs_close: %d\n",ip->i_number); #endif return (0); @@ -767,7 +740,8 @@ ntfs_readdir(ap) } */ *ap; { register struct vnode *vp = ap->a_vp; - register struct ntnode *ip = VTONT(vp); + register struct fnode *fp = VTOF(vp); + register struct ntnode *ip = FTONT(fp); struct uio *uio = ap->a_uio; struct ntfsmount *ntmp = ip->i_mp; int i, error = 0; @@ -813,7 +787,7 @@ ntfs_readdir(ap) while( uio->uio_resid >= sizeof(struct dirent) ) { struct attr_indexentry *iep; - error = ntfs_ntreaddir(ntmp, ip, num, &iep); + error = ntfs_ntreaddir(ntmp, fp, num, &iep); if(error) return (error); @@ -919,7 +893,7 @@ ntfs_lookup(ap) cnp->cn_nameptr, cnp->cn_namelen, dip->i_number,lockparent, wantparent)); - error = VOP_ACCESS(dvp,VEXEC, cred, cnp->cn_proc); + error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_proc); if(error) return (error); @@ -974,39 +948,12 @@ ntfs_lookup(ap) } return (error); } else { - struct ntnode * nip; - - error = ntfs_ntlookup(ntmp, dip, cnp, &nip); + error = ntfs_ntlookup(ntmp, dvp, cnp, ap->a_vpp); if(error) return (error); - dprintf(("ntfs_lookup: found ino: %d\n", nip->i_number)); - if( nip->i_number == dip->i_number ) { - ntfs_ntrele(nip); - VREF(dvp); - *ap->a_vpp = dvp; - return (0); - } - - *ap->a_vpp = ntfs_ihashget(ntmp->ntm_dev, nip->i_number); - if(*ap->a_vpp == NULL) { - error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, - ntfs_vnodeop_p, ap->a_vpp); - if(error) { - ntfs_ntrele(nip); - return (error); - } - nip->i_vnode = *(ap->a_vpp); - (*ap->a_vpp)->v_data = nip; - (*ap->a_vpp)->v_type = nip->i_type; - - ntfs_ihashins(nip); - - VREF(nip->i_devvp); - } else { - printf("found in cache\n"); - ntfs_ntrele(nip); - } + dprintf(("ntfs_lookup: found ino: %d\n", + VTONT(*ap->a_vpp)->i_number)); if(!lockparent || !(cnp->cn_flags & ISLASTCN)) #if __FreeBSD_version >= 300000 @@ -1070,10 +1017,12 @@ static struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = { { &vop_bmap_desc, (vop_t *)ntfs_bmap }, { &vop_getpages_desc, (vop_t *)ntfs_getpages }, + { &vop_putpages_desc, (vop_t *) ntfs_putpages }, { &vop_strategy_desc, (vop_t *)ntfs_strategy }, - { &vop_bwrite_desc, (vop_t *)ntfs_bwrite }, + { &vop_bwrite_desc, (vop_t *)vop_stdbwrite }, { &vop_read_desc, (vop_t *)ntfs_read }, + { &vop_write_desc, (vop_t *)ntfs_write }, { NULL, NULL } }; |