summaryrefslogtreecommitdiffstats
path: root/sys/ntfs
diff options
context:
space:
mode:
authorsemenu <semenu@FreeBSD.org>1999-02-19 12:31:02 +0000
committersemenu <semenu@FreeBSD.org>1999-02-19 12:31:02 +0000
commit05d36e7aeab6b1f528acb24b6610b4982335afbe (patch)
treeb64fa05911edc2837553bd88e10f4030c470fe1b /sys/ntfs
parenteb7abf9254a7f2c95d72411f292d032a9a8f14a1 (diff)
downloadFreeBSD-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/ntfs')
-rw-r--r--sys/ntfs/ntfs.h22
-rw-r--r--sys/ntfs/ntfs_compr.c4
-rw-r--r--sys/ntfs/ntfs_compr.h4
-rw-r--r--sys/ntfs/ntfs_extern.h2
-rw-r--r--sys/ntfs/ntfs_ihash.c80
-rw-r--r--sys/ntfs/ntfs_ihash.h33
-rw-r--r--sys/ntfs/ntfs_inode.h62
-rw-r--r--sys/ntfs/ntfs_subr.c621
-rw-r--r--sys/ntfs/ntfs_subr.h39
-rw-r--r--sys/ntfs/ntfs_vfsops.c141
-rw-r--r--sys/ntfs/ntfs_vfsops.h33
-rw-r--r--sys/ntfs/ntfs_vnops.c387
12 files changed, 876 insertions, 552 deletions
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 }
};
OpenPOWER on IntegriCloud