diff options
author | semenu <semenu@FreeBSD.org> | 1999-12-03 20:37:40 +0000 |
---|---|---|
committer | semenu <semenu@FreeBSD.org> | 1999-12-03 20:37:40 +0000 |
commit | 39d5a6d9a112c694b6ddfe314cd3fabd50842d57 (patch) | |
tree | 9ce5b1cd13e28d4820c42a103ec4056e6905350a /sys/fs/ntfs | |
parent | 97f1907fc7b23a0430fdd2761931127aee747ad5 (diff) | |
download | FreeBSD-src-39d5a6d9a112c694b6ddfe314cd3fabd50842d57.zip FreeBSD-src-39d5a6d9a112c694b6ddfe314cd3fabd50842d57.tar.gz |
Merged NetBSD version, as they have done improvements:
1. ntfs_read*attr*() functions now accept
uio structure to eliminate one data copying.
2. found and removed deadlock caused
by 6 concurent ls -lR.
3. started implementation of nromal
Unicode<->unix recodeing.
Obtained from: NetBSD
Diffstat (limited to 'sys/fs/ntfs')
-rw-r--r-- | sys/fs/ntfs/ntfs.h | 49 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_compr.c | 7 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_compr.h | 2 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_ihash.c | 6 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_ihash.h | 3 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_inode.h | 39 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_subr.c | 1048 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_subr.h | 40 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_vfsops.c | 398 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_vfsops.h | 4 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfs_vnops.c | 527 | ||||
-rw-r--r-- | sys/fs/ntfs/ntfsmount.h | 2 |
12 files changed, 1111 insertions, 1014 deletions
diff --git a/sys/fs/ntfs/ntfs.h b/sys/fs/ntfs/ntfs.h index 7aa6528..42b17e4 100644 --- a/sys/fs/ntfs/ntfs.h +++ b/sys/fs/ntfs/ntfs.h @@ -1,4 +1,4 @@ -/* $NetBSD: ntfs.h,v 1.2 1999/05/06 15:43:17 christos Exp $ */ +/* $NetBSD: ntfs.h,v 1.9 1999/10/31 19:45:26 jdolecek Exp $ */ /*- * Copyright (c) 1998, 1999 Semen Ustimenko @@ -29,6 +29,9 @@ */ /*#define NTFS_DEBUG 1*/ +#if defined(__NetBSD__) && defined(_KERNEL) && !defined(_LKM) +#include "opt_ntfs.h" +#endif typedef u_int64_t cn_t; typedef u_int16_t wchar; @@ -239,12 +242,11 @@ struct bootfile { #define NTFS_SYSNODESNUM 0x0B struct ntfsmount { - struct mount *ntm_mountp; + struct mount *ntm_mountp; /* filesystem vfs structure */ struct bootfile ntm_bootfile; - dev_t ntm_dev; - struct vnode *ntm_devvp; + dev_t ntm_dev; /* device mounted */ + struct vnode *ntm_devvp; /* block device mounted vnode */ struct vnode *ntm_sysvn[NTFS_SYSNODESNUM]; - wchar *ntm_upcase; u_int32_t ntm_bpmftrec; uid_t ntm_uid; gid_t ntm_gid; @@ -253,6 +255,7 @@ struct ntfsmount { cn_t ntm_cfree; struct ntvattrdef *ntm_ad; int ntm_adnum; + struct netexport ntm_export; /* export information */ }; #define ntm_mftcn ntm_bootfile.bf_mftcn @@ -290,29 +293,33 @@ MALLOC_DECLARE(M_NTFSNTHASH); #ifdef __NetBSD__ #define MALLOC_DEFINE(a, b, c) -#define M_NTFSNTHASH M_TEMP -#define M_NTFSNTVATTR M_TEMP -#define M_NTFSRDATA M_TEMP -#define M_NTFSRUN M_TEMP -#define M_NTFSDECOMP M_TEMP -#define M_NTFSMNT M_TEMP -#define M_NTFSNTNODE M_TEMP -#define M_NTFSFNODE M_TEMP -#define M_NTFSDIR M_TEMP +#define M_NTFSNTHASH M_NTFS +#define M_NTFSNTVATTR M_NTFS +#define M_NTFSRDATA M_NTFS +#define M_NTFSRUN M_NTFS +#define M_NTFSDECOMP M_NTFS +#define M_NTFSMNT M_NTFS +#define M_NTFSNTNODE M_NTFS +#define M_NTFSFNODE M_NTFS +#define M_NTFSDIR M_NTFS typedef int (vop_t) __P((void *)); #define HASHINIT(a, b, c, d) hashinit((a), (b), (c), (d)) #define bqrelse(bp) brelse(bp) -#define VOP__LOCK(a, b, c) VOP_LOCK((a), (b) ? LK_EXCLUSIVE : LK_SHARED) -#define VOP__UNLOCK(a, b, c) VOP_UNLOCK((a), 0) -#define VGET(a, b, c) vget((a), LK_EXCLUSIVE) -#define VN_LOCK(a, b, c) vn_lock((a), LK_EXCLUSIVE) -#else +#define VOP__UNLOCK(a, b, c) VOP_UNLOCK((a), (b)) +#define VGET(a, b, c) vget((a), (b)) +#define VN_LOCK(a, b, c) vn_lock((a), (b)) +#define LOCKMGR(a, b, c) lockmgr((a), (b), (c)) +#else /* !NetBSD */ #define HASHINIT(a, b, c, d) hashinit((a), (b), (d)) -#define VOP__LOCK(a, b, c) VOP_LOCK((a), (b), (c)) #define VOP__UNLOCK(a, b, c) VOP_UNLOCK((a), (b), (c)) #define VGET(a, b, c) vget((a), (b), (c)) #define VN_LOCK(a, b, c) vn_lock((a), (b), (c)) -#endif +#define LOCKMGR(a, b, c) lockmgr((a), (b), (c), NULL) + +/* PDIRUNLOCK is used by NetBSD to mark if vfs_lookup() unlocked parent dir; + * on FreeBSD, it's not defined and nothing similar exists */ +#define PDIRUNLOCK 0 +#endif /* NetBSD */ #if defined(NTFS_DEBUG) #define dprintf(a) printf a diff --git a/sys/fs/ntfs/ntfs_compr.c b/sys/fs/ntfs/ntfs_compr.c index 412047b..114a6af 100644 --- a/sys/fs/ntfs/ntfs_compr.c +++ b/sys/fs/ntfs/ntfs_compr.c @@ -1,4 +1,4 @@ -/* $NetBSD: ntfs_compr.c,v 1.2 1999/05/06 15:43:18 christos Exp $ */ +/* $NetBSD: ntfs_compr.c,v 1.3 1999/07/26 14:02:31 jdolecek Exp $ */ /*- * Copyright (c) 1998, 1999 Semen Ustimenko @@ -38,8 +38,9 @@ #include <sys/buf.h> #include <sys/file.h> #include <sys/malloc.h> -#ifdef __FreeBSD__ -#include <machine/clock.h> + +#if defined(__NetBSD__) +#include <miscfs/specfs/specdev.h> #endif #include <ntfs/ntfs.h> diff --git a/sys/fs/ntfs/ntfs_compr.h b/sys/fs/ntfs/ntfs_compr.h index bdec08c..e51bc09 100644 --- a/sys/fs/ntfs/ntfs_compr.h +++ b/sys/fs/ntfs/ntfs_compr.h @@ -1,4 +1,4 @@ -/* $NetBSD: ntfs_compr.h,v 1.2 1999/05/06 15:43:18 christos Exp $ */ +/* $NetBSD: ntfs_compr.h,v 1.3 1999/07/26 14:02:31 jdolecek Exp $ */ /*- * Copyright (c) 1998, 1999 Semen Ustimenko diff --git a/sys/fs/ntfs/ntfs_ihash.c b/sys/fs/ntfs/ntfs_ihash.c index 50ee7ac..0deecff 100644 --- a/sys/fs/ntfs/ntfs_ihash.c +++ b/sys/fs/ntfs/ntfs_ihash.c @@ -1,4 +1,4 @@ -/* $NetBSD: ntfs_ihash.c,v 1.2 1999/05/06 15:43:19 christos Exp $ */ +/* $NetBSD: ntfs_ihash.c,v 1.5 1999/09/30 16:56:40 jdolecek Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995 @@ -43,6 +43,7 @@ #include <sys/vnode.h> #include <sys/malloc.h> #include <sys/proc.h> +#include <sys/mount.h> #include <ntfs/ntfs.h> #include <ntfs/ntfs_inode.h> @@ -59,6 +60,7 @@ static u_long ntfs_nthash; /* size of hash table - 1 */ #ifndef NULL_SIMPLELOCKS static struct simplelock ntfs_nthash_slock; #endif +struct lock ntfs_hashlock; /* * Initialize inode hash table. @@ -66,7 +68,7 @@ static struct simplelock ntfs_nthash_slock; void ntfs_nthashinit() { - + lockinit(&ntfs_hashlock, PINOD, "ntfs_nthashlock", 0, 0); ntfs_nthashtbl = HASHINIT(desiredvnodes, M_NTFSNTHASH, M_WAITOK, &ntfs_nthash); simple_lock_init(&ntfs_nthash_slock); diff --git a/sys/fs/ntfs/ntfs_ihash.h b/sys/fs/ntfs/ntfs_ihash.h index 16132a9..7b7143f 100644 --- a/sys/fs/ntfs/ntfs_ihash.h +++ b/sys/fs/ntfs/ntfs_ihash.h @@ -1,4 +1,4 @@ -/* $NetBSD: ntfs_ihash.h,v 1.2 1999/05/06 15:43:19 christos Exp $ */ +/* $NetBSD: ntfs_ihash.h,v 1.4 1999/09/30 16:56:40 jdolecek Exp $ */ /*- * Copyright (c) 1998, 1999 Semen Ustimenko @@ -28,6 +28,7 @@ * $FreeBSD$ */ +extern struct lock ntfs_hashlock; void ntfs_nthashinit __P((void)); struct ntnode *ntfs_nthashlookup __P((dev_t, ino_t)); struct ntnode *ntfs_nthashget __P((dev_t, ino_t)); diff --git a/sys/fs/ntfs/ntfs_inode.h b/sys/fs/ntfs/ntfs_inode.h index a613385..a86d5f7 100644 --- a/sys/fs/ntfs/ntfs_inode.h +++ b/sys/fs/ntfs/ntfs_inode.h @@ -1,4 +1,4 @@ -/* $NetBSD: ntfs_inode.h,v 1.2 1999/05/06 15:43:19 christos Exp $ */ +/* $NetBSD: ntfs_inode.h,v 1.8 1999/10/31 19:45:26 jdolecek Exp $ */ /*- * Copyright (c) 1998, 1999 Semen Ustimenko @@ -57,46 +57,41 @@ #define IN_PRELOADED 0x4000 /* loaded from directory entry */ struct ntnode { + struct vnode *i_devvp; /* vnode of blk dev we live on */ + dev_t i_dev; /* Device associated with the inode. */ + LIST_ENTRY(ntnode) i_hash; struct ntnode *i_next; struct ntnode **i_prev; struct ntfsmount *i_mp; ino_t i_number; - dev_t i_dev; u_int32_t i_flag; - int i_lock; + + /* locking */ + struct lock i_lock; + struct simplelock i_interlock; int i_usecount; -#if defined(__NetBSD__) - pid_t i_lockholder; - pid_t i_lockwaiter; - int i_lockcount; -#endif + LIST_HEAD(,fnode) i_fnlist; LIST_HEAD(,ntvattr) i_valist; long i_nlink; /* MFR */ ino_t i_mainrec; /* MFR */ u_int32_t i_frflag; /* MFR */ - - uid_t i_uid; - gid_t i_gid; - mode_t i_mode; }; #define FN_PRELOADED 0x0001 #define FN_VALID 0x0002 #define FN_AATTRNAME 0x0004 /* space allocated for f_attrname */ struct fnode { - struct lock f_lock; /* Must be first */ +#ifdef __FreeBSD__ + struct lock f_lock; /* fnode lock >Keep this first< */ +#endif LIST_ENTRY(fnode) f_fnlist; struct vnode *f_vp; /* Associatied vnode */ - struct ntnode *f_ip; + struct ntnode *f_ip; /* Associated ntnode */ 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 */ @@ -115,3 +110,11 @@ struct fnode { caddr_t f_dirblbuf; u_int32_t f_dirblsz; }; + +/* This overlays the fid structure (see <sys/mount.h>) */ +struct ntfid { + u_int16_t ntfid_len; /* Length of structure. */ + u_int16_t ntfid_pad; /* Force 32-bit alignment. */ + ino_t ntfid_ino; /* File number (ino). */ + int32_t ntfid_gen; /* Generation number. */ +}; diff --git a/sys/fs/ntfs/ntfs_subr.c b/sys/fs/ntfs/ntfs_subr.c index b3e75b3..7a75972 100644 --- a/sys/fs/ntfs/ntfs_subr.c +++ b/sys/fs/ntfs/ntfs_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: ntfs_subr.c,v 1.2 1999/05/06 15:43:19 christos Exp $ */ +/* $NetBSD: ntfs_subr.c,v 1.23 1999/10/31 19:45:26 jdolecek Exp $ */ /*- * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) @@ -39,8 +39,10 @@ #include <sys/buf.h> #include <sys/file.h> #include <sys/malloc.h> -#if defined(__FreeBSD__) -#include <machine/clock.h> +#include <sys/lock.h> + +#if defined(__NetBSD__) +#include <miscfs/specfs/specdev.h> #endif /* #define NTFS_DEBUG 1 */ @@ -48,7 +50,6 @@ #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> @@ -60,12 +61,30 @@ MALLOC_DEFINE(M_NTFSRUN, "NTFS vrun", "NTFS vrun storage"); MALLOC_DEFINE(M_NTFSDECOMP, "NTFS decomp", "NTFS decompression temporary"); #endif +static int ntfs_ntlookupattr __P((struct ntfsmount *, const char *, int, int *, char **)); +static int ntfs_findvattr __P((struct ntfsmount *, struct ntnode *, struct ntvattr **, struct ntvattr **, u_int32_t, const char *, size_t, cn_t)); +static int ntfs_uastricmp __P((const wchar *, size_t, const char *, size_t)); +static int ntfs_uastrcmp __P((const wchar *, size_t, const char *, size_t)); + +/* table for mapping Unicode chars into uppercase; it's filled upon first + * ntfs mount, freed upon last ntfs umount */ +static wchar *ntfs_toupper_tab; +#define NTFS_U28(ch) ((((ch) & 0xFF) == 0) ? '_' : (ch) & 0xFF) +#define NTFS_TOUPPER(ch) (ntfs_toupper_tab[(unsigned char)(ch)]) +static struct lock ntfs_toupper_lock; +static signed int ntfs_toupper_usecount; + +/* support macro for ntfs_ntvattrget() */ +#define NTFS_AALPCMP(aalp,type,name,namelen) ( \ + (aalp->al_type == type) && (aalp->al_namelen == namelen) && \ + !ntfs_uastrcmp(aalp->al_name,aalp->al_namelen,name,namelen) ) + /* * */ int -ntfs_ntvattrrele( - struct ntvattr * vap) +ntfs_ntvattrrele(vap) + struct ntvattr * vap; { dprintf(("ntfs_ntvattrrele: ino: %d, type: 0x%x\n", vap->va_ip->i_number, vap->va_type)); @@ -76,6 +95,54 @@ ntfs_ntvattrrele( } /* + * find the attribute in the ntnode + */ +static int +ntfs_findvattr(ntmp, ip, lvapp, vapp, type, name, namelen, vcn) + struct ntfsmount *ntmp; + struct ntnode *ip; + struct ntvattr **lvapp, **vapp; + u_int32_t type; + const char *name; + size_t namelen; + cn_t vcn; +{ + int error; + struct ntvattr *vap; + + if((ip->i_flag & IN_LOADED) == 0) { + dprintf(("ntfs_findvattr: node not loaded, ino: %d\n", + ip->i_number)); + error = ntfs_loadntnode(ntmp,ip); + if (error) { + printf("ntfs_findvattr: FAILED TO LOAD INO: %d\n", + ip->i_number); + return (error); + } + } + + *lvapp = NULL; + *vapp = NULL; + for (vap = ip->i_valist.lh_first; vap; vap = vap->va_list.le_next) { + ddprintf(("ntfs_findvattr: type: 0x%x, vcn: %d - %d\n", \ + vap->va_type, (u_int32_t) vap->va_vcnstart, \ + (u_int32_t) vap->va_vcnend)); + if ((vap->va_type == type) && + (vap->va_vcnstart <= vcn) && (vap->va_vcnend >= vcn) && + (vap->va_namelen == namelen) && + (strncmp(name, vap->va_name, namelen) == 0)) { + *vapp = vap; + ntfs_ntref(vap->va_ip); + return (0); + } + if (vap->va_type == NTFS_A_ATTRLIST) + *lvapp = vap; + } + + return (-1); +} + +/* * Search attribute specifed in ntnode (load ntnode if nessecary). * If not found but ATTR_A_ATTRLIST present, read it in and search throught. * VOP_VGET node needed, and lookup througth it's ntnode (load if nessesary). @@ -87,17 +154,18 @@ ntfs_ntvattrget( struct ntfsmount * ntmp, struct ntnode * ip, u_int32_t type, - char *name, + const char *name, cn_t vcn, struct ntvattr ** vapp) { - int error; - struct ntvattr *vap; struct ntvattr *lvap = NULL; struct attr_attrlist *aalp; struct attr_attrlist *nextaalp; + struct vnode *newvp; + struct ntnode *newip; caddr_t alpool; - int len, namelen; + size_t namelen, len; + int error; *vapp = NULL; @@ -114,32 +182,9 @@ ntfs_ntvattrget( namelen = 0; } - if((ip->i_flag & IN_LOADED) == 0) { - dprintf(("ntfs_ntvattrget: node not loaded, ino: %d\n", - ip->i_number)); - error = ntfs_loadntnode(ntmp,ip); - if(error) { - printf("ntfs_ntvattrget: FAILED TO LOAD INO: %d\n", - ip->i_number); - return (error); - } - } - - for (vap = ip->i_valist.lh_first; vap; vap = vap->va_list.le_next) { - ddprintf(("type: 0x%x, vcn: %d - %d\n", \ - vap->va_type, (u_int32_t) vap->va_vcnstart, \ - (u_int32_t) vap->va_vcnend)); - if ((vap->va_type == type) && - (vap->va_vcnstart <= vcn) && (vap->va_vcnend >= vcn) && - (vap->va_namelen == namelen) && - (!strncmp(name, vap->va_name, namelen))) { - *vapp = vap; - ntfs_ntref(vap->va_ip); - return (0); - } - if (vap->va_type == NTFS_A_ATTRLIST) - lvap = vap; - } + error = ntfs_findvattr(ntmp, ip, &lvap, vapp, type, name, namelen, vcn); + if (error >= 0) + return (error); if (!lvap) { dprintf(("ntfs_ntvattrget: UNEXISTED ATTRIBUTE: " \ @@ -150,14 +195,15 @@ ntfs_ntvattrget( /* Scan $ATTRIBUTE_LIST for requested attribute */ len = lvap->va_datalen; MALLOC(alpool, caddr_t, len, M_TEMP, M_WAITOK); - error = ntfs_readntvattr_plain(ntmp, ip, lvap, 0, len, alpool, &len); + error = ntfs_readntvattr_plain(ntmp, ip, lvap, 0, len, alpool, &len, + NULL); if (error) goto out; aalp = (struct attr_attrlist *) alpool; nextaalp = NULL; - while (len > 0) { + for(; len > 0; aalp = nextaalp) { dprintf(("ntfs_ntvattrget: " \ "attrlist: ino: %d, attr: 0x%x, vcn: %d\n", \ aalp->al_inumber, aalp->al_type, \ @@ -170,71 +216,39 @@ ntfs_ntvattrget( } len -= aalp->reclen; -#define AALPCMP(aalp,type,name,namelen) ( \ - (aalp->al_type == type) && (aalp->al_namelen == namelen) && \ - !uastrcmp(aalp->al_name,aalp->al_namelen,name,namelen) ) + if (!NTFS_AALPCMP(aalp, type, name, namelen) || + (nextaalp && (nextaalp->al_vcnstart <= vcn) && + NTFS_AALPCMP(nextaalp, type, name, namelen))) + continue; - if (AALPCMP(aalp, type, name, namelen) && - (!nextaalp || (nextaalp->al_vcnstart > vcn) || - !AALPCMP(nextaalp, type, name, namelen))) { - struct vnode *newvp; - struct ntnode *newip; - - dprintf(("ntfs_ntvattrget: attrbute in ino: %d\n", + dprintf(("ntfs_ntvattrget: attribute in ino: %d\n", aalp->al_inumber)); -/* - error = VFS_VGET(ntmp->ntm_mountp, aalp->al_inumber, - &newvp); -*/ - error = ntfs_vgetex(ntmp->ntm_mountp, aalp->al_inumber, - NTFS_A_DATA, NULL, LK_EXCLUSIVE, - VG_EXT, curproc, &newvp); - if (error) { - printf("ntfs_ntvattrget: CAN'T VGET INO: %d\n", - aalp->al_inumber); - goto out; - } - newip = VTONT(newvp); - /* XXX have to lock ntnode */ - if(~newip->i_flag & IN_LOADED) { - dprintf(("ntfs_ntvattrget: node not loaded," \ - " ino: %d\n", newip->i_number)); - error = ntfs_loadntnode(ntmp,ip); - if(error) { - printf("ntfs_ntvattrget: CAN'T LOAD " \ - "INO: %d\n", newip->i_number); - vput(newvp); - goto out; - } - } - for (vap = newip->i_valist.lh_first; vap; vap = vap->va_list.le_next) { - if ((vap->va_type == type) && - (vap->va_vcnstart <= vcn) && - (vap->va_vcnend >= vcn) && - (vap->va_namelen == namelen) && - (!strncmp(name, vap->va_name, namelen))) { - *vapp = vap; - ntfs_ntref(vap->va_ip); - vput(newvp); - error = 0; - goto out; - } - if (vap->va_type == NTFS_A_ATTRLIST) - lvap = vap; - } - printf("ntfs_ntvattrget: ATTRLIST ERROR.\n"); - vput(newvp); - break; + /* this is not a main record, so we can't use just plain + vget() */ + error = ntfs_vgetex(ntmp->ntm_mountp, aalp->al_inumber, + NTFS_A_DATA, NULL, LK_EXCLUSIVE, + VG_EXT, curproc, &newvp); + if (error) { + printf("ntfs_ntvattrget: CAN'T VGET INO: %d\n", + aalp->al_inumber); + goto out; } -#undef AALPCMP - aalp = nextaalp; + newip = VTONT(newvp); + /* XXX have to lock ntnode */ + error = ntfs_findvattr(ntmp, newip, &lvap, vapp, + type, name, namelen, vcn); + vput(newvp); + if (error == 0) + goto out; + printf("ntfs_ntvattrget: ATTRLIST ERROR.\n"); + break; } error = ENOENT; dprintf(("ntfs_ntvattrget: UNEXISTED ATTRIBUTE: " \ - "ino: %d, type: 0x%x, name: %s, vcn: %d\n", \ - ip->i_number, type, name, (u_int32_t) vcn)); + "ino: %d, type: 0x%x, name: %.*s, vcn: %d\n", \ + ip->i_number, type, (int) namelen, name, (u_int32_t) vcn)); out: FREE(alpool, M_TEMP); return (error); @@ -256,7 +270,7 @@ ntfs_loadntnode( struct attr *ap; struct ntvattr *nvap; - dprintf(("ntfs_loadnode: loading ino: %d\n",ip->i_number)); + dprintf(("ntfs_loadntnode: loading ino: %d\n",ip->i_number)); MALLOC(mfrp, struct filerec *, ntfs_bntob(ntmp->ntm_bpmftrec), M_TEMP, M_WAITOK); @@ -264,7 +278,7 @@ ntfs_loadntnode( if (ip->i_number < NTFS_SYSNODESNUM) { struct buf *bp; - dprintf(("ntfs_loadnode: read system node\n")); + dprintf(("ntfs_loadntnode: read system node\n")); bn = ntfs_cntobn(ntmp->ntm_mftcn) + ntmp->ntm_bpmftrec * ip->i_number; @@ -273,7 +287,7 @@ ntfs_loadntnode( bn, ntfs_bntob(ntmp->ntm_bpmftrec), NOCRED, &bp); if (error) { - printf("ntfs_loadnode: BREAD FAILED\n"); + printf("ntfs_loadntnode: BREAD FAILED\n"); brelse(bp); goto out; } @@ -285,9 +299,9 @@ ntfs_loadntnode( vp = ntmp->ntm_sysvn[NTFS_MFTINO]; error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, ip->i_number * ntfs_bntob(ntmp->ntm_bpmftrec), - ntfs_bntob(ntmp->ntm_bpmftrec), mfrp); + ntfs_bntob(ntmp->ntm_bpmftrec), mfrp, NULL); if (error) { - printf("ntfs_loadnode: ntfs_readattr failed\n"); + printf("ntfs_loadntnode: ntfs_readattr failed\n"); goto out; } } @@ -296,12 +310,12 @@ ntfs_loadntnode( error = ntfs_procfixups(ntmp, NTFS_FILEMAGIC, (caddr_t)mfrp, ntfs_bntob(ntmp->ntm_bpmftrec)); if (error) { - printf("ntfs_loadnode: BAD MFT RECORD %d\n", + printf("ntfs_loadntnode: BAD MFT RECORD %d\n", (u_int32_t) ip->i_number); goto out; } - dprintf(("ntfs_loadnode: load attrs for ino: %d\n",ip->i_number)); + dprintf(("ntfs_loadntnode: load attrs for ino: %d\n",ip->i_number)); off = mfrp->fr_attroff; ap = (struct attr *) ((caddr_t)mfrp + off); @@ -319,7 +333,7 @@ ntfs_loadntnode( ap = (struct attr *) ((caddr_t)mfrp + off); } if (error) { - printf("ntfs_loadnode: failed to load attr ino: %d\n", + printf("ntfs_loadntnode: failed to load attr ino: %d\n", ip->i_number); goto out; } @@ -337,26 +351,18 @@ out: /* * Routine locks ntnode and increase usecount, just opposite of - * ntfs_ntput. + * ntfs_ntput(). */ int -ntfs_ntget( - struct ntnode *ip) +ntfs_ntget(ip) + struct ntnode *ip; { dprintf(("ntfs_ntget: get ntnode %d: %p, usecount: %d\n", ip->i_number, ip, ip->i_usecount)); + simple_lock(&ip->i_interlock); ip->i_usecount++; - -restart: - if (ip->i_lock) { - while (ip->i_lock) { - ip->i_lock = -1; - tsleep(&ip->i_lock, PVM, "ntnode", 0); - } - goto restart; - } - ip->i_lock = 1; + LOCKMGR(&ip->i_lock, LK_EXCLUSIVE | LK_INTERLOCK, &ip->i_interlock); return 0; } @@ -368,7 +374,6 @@ restart: * * ntnode returned locked */ -static int ntfs_ntnode_hash_lock; int ntfs_ntlookup( struct ntfsmount * ntmp, @@ -377,28 +382,17 @@ ntfs_ntlookup( { struct ntnode *ip; - dprintf(("ntfs_ntlookup: for ntnode %d\n", ino)); - *ipp = NULL; - -restart: - ip = ntfs_nthashlookup(ntmp->ntm_dev, ino); /* XXX */ - if (ip) { - ntfs_ntget(ip); - *ipp = ip; - dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n", - ino, ip, ip->i_usecount)); + dprintf(("ntfs_ntlookup: looking for ntnode %d\n", ino)); - return (0); - } - - if (ntfs_ntnode_hash_lock) { - while(ntfs_ntnode_hash_lock) { - ntfs_ntnode_hash_lock = -1; - tsleep(&ntfs_ntnode_hash_lock, PVM, "ntfsntgt", 0); + do { + if ((ip = ntfs_nthashlookup(ntmp->ntm_dev, ino)) != NULL) { + ntfs_ntget(ip); + dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n", + ino, ip, ip->i_usecount)); + *ipp = ip; + return (0); } - goto restart; - } - ntfs_ntnode_hash_lock = 1; + } while (LOCKMGR(&ntfs_hashlock, LK_EXCLUSIVE | LK_SLEEPFAIL, NULL)); MALLOC(ip, struct ntnode *, sizeof(struct ntnode), M_NTFSNTNODE, M_WAITOK); @@ -406,23 +400,21 @@ restart: bzero((caddr_t) ip, sizeof(struct ntnode)); /* Generic initialization */ + ip->i_devvp = ntmp->ntm_devvp; + ip->i_dev = ntmp->ntm_dev; 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++; - - ip->i_lock = 1; LIST_INIT(&ip->i_fnlist); + /* init lock and lock the newborn ntnode */ + lockinit(&ip->i_lock, PINOD, "ntnode", 0, LK_EXCLUSIVE); + simple_lock_init(&ip->i_interlock); + ntfs_ntget(ip); + ntfs_nthashins(ip); - if (ntfs_ntnode_hash_lock < 0) - wakeup(&ntfs_ntnode_hash_lock); - ntfs_ntnode_hash_lock = 0; + LOCKMGR(&ntfs_hashlock, LK_RELEASE, NULL); *ipp = ip; @@ -439,22 +431,25 @@ restart: * ntnode should be locked on entry, and unlocked on return. */ void -ntfs_ntput( - struct ntnode *ip) +ntfs_ntput(ip) + struct ntnode *ip; { struct ntvattr *vap; - if (!ip->i_lock) printf("ntfs_ntput: NOT LOCKED"); - dprintf(("ntfs_ntput: rele ntnode %d: %p, usecount: %d\n", ip->i_number, ip, ip->i_usecount)); + simple_lock(&ip->i_interlock); ip->i_usecount--; +#ifdef DIAGNOSTIC if (ip->i_usecount < 0) { panic("ntfs_ntput: ino: %d usecount: %d \n", ip->i_number,ip->i_usecount); - } else if (ip->i_usecount == 0) { + } +#endif + + if (ip->i_usecount == 0) { dprintf(("ntfs_ntput: deallocating ntnode: %d\n", ip->i_number)); @@ -470,36 +465,51 @@ ntfs_ntput( } FREE(ip, M_NTFSNTNODE); } else { - if (ip->i_lock < 0) - wakeup(&ip->i_lock); - ip->i_lock = 0; + LOCKMGR(&ip->i_lock, LK_RELEASE|LK_INTERLOCK, &ip->i_interlock); } } /* + * increment usecount of ntnode + */ +void +ntfs_ntref(ip) + struct ntnode *ip; +{ + simple_lock(&ip->i_interlock); + ip->i_usecount++; + simple_unlock(&ip->i_interlock); + + dprintf(("ntfs_ntref: ino %d, usecount: %d\n", + ip->i_number, ip->i_usecount)); + +} + +/* * Decrement usecount of ntnode. */ void -ntfs_ntrele( - struct ntnode * ip) +ntfs_ntrele(ip) + struct ntnode *ip; { dprintf(("ntfs_ntrele: rele ntnode %d: %p, usecount: %d\n", ip->i_number, ip, ip->i_usecount)); + simple_lock(&ip->i_interlock); ip->i_usecount--; if (ip->i_usecount < 0) panic("ntfs_ntrele: ino: %d usecount: %d \n", ip->i_number,ip->i_usecount); + simple_unlock(&ip->i_interlock); } /* - * Deallocate all memory allocated for ntvattr by call to - * ntfs_attrtontvattr and some other functions. + * Deallocate all memory allocated for ntvattr */ void -ntfs_freentvattr( - struct ntvattr * vap) +ntfs_freentvattr(vap) + struct ntvattr * vap; { if (vap->va_flag & NTFS_AF_INRUN) { if (vap->va_vruncn) @@ -647,82 +657,46 @@ ntfs_runtovrun( } /* - * Convert wchar to uppercase wchar, should be macros? - */ -wchar -ntfs_toupper( - struct ntfsmount * ntmp, - wchar wc) -{ - return (ntmp->ntm_upcase[wc & 0xFF]); -} - -/* - * Compare to unicode strings case insensible. - */ -int -ntfs_uustricmp( - struct ntfsmount * ntmp, - wchar * str1, - int str1len, - wchar * str2, - int str2len) -{ - int i; - int res; - - for (i = 0; i < str1len && i < str2len; i++) { - res = (int) ntfs_toupper(ntmp, str1[i]) - - (int) ntfs_toupper(ntmp, str2[i]); - if (res) - return res; - } - return (str1len - str2len); -} - -/* * Compare unicode and ascii string case insens. */ -int -ntfs_uastricmp( - struct ntfsmount * ntmp, - const wchar *str1, - int str1len, - const char *str2, - int str2len) +static int +ntfs_uastricmp(ustr, ustrlen, astr, astrlen) + const wchar *ustr; + size_t ustrlen; + const char *astr; + size_t astrlen; { - int i; + size_t i; int res; - for (i = 0; i < str1len && i < str2len; i++) { - res = (int) ntfs_toupper(ntmp, str1[i]) - - (int) ntfs_toupper(ntmp, (wchar) str2[i]); + for (i = 0; i < ustrlen && i < astrlen; i++) { + res = ((int) NTFS_TOUPPER(NTFS_U28(ustr[i]))) - + ((int)NTFS_TOUPPER(astr[i])); if (res) return res; } - return (str1len - str2len); + return (ustrlen - astrlen); } /* * Compare unicode and ascii string case sens. */ -int -ntfs_uastrcmp( - struct ntfsmount *ntmp, - const wchar *str1, - int str1len, - const char *str2, - int str2len) +static int +ntfs_uastrcmp(ustr, ustrlen, astr, astrlen) + const wchar *ustr; + size_t ustrlen; + const char *astr; + size_t astrlen; { - int i; + size_t i; int res; - for (i = 0; (i < str1len) && (i < str2len); i++) { - res = ((int) str1[i]) - ((int) str2[i]); + for (i = 0; (i < ustrlen) && (i < astrlen); i++) { + res = (int) (((char)NTFS_U28(ustr[i])) - astr[i]); if (res) return res; } - return (str1len - str2len); + return (ustrlen - astrlen); } /* @@ -763,10 +737,6 @@ ntfs_fget( 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; @@ -809,7 +779,7 @@ ntfs_frele( * $ATTR_TYPE is searched in attrdefs read from $AttrDefs. * If $ATTR_TYPE nott specifed, ATTR_A_DATA assumed. */ -int +static int ntfs_ntlookupattr( struct ntfsmount * ntmp, const char * name, @@ -837,24 +807,19 @@ ntfs_ntlookupattr( namelen -= syslen; adp = ntmp->ntm_ad; - for (i = 0; i < ntmp->ntm_adnum; i++){ - if((syslen == adp->ad_namelen) && - (!strncmp(sys,adp->ad_name,syslen))) { - *attrtype = adp->ad_type; - if(namelen) { - MALLOC((*attrname), char *, namelen, - M_TEMP, M_WAITOK); - memcpy((*attrname), name, namelen); - (*attrname)[namelen] = '\0'; - } - return (0); - } - adp++; + for (i = 0; i < ntmp->ntm_adnum; i++, adp++){ + if (syslen != adp->ad_namelen || + strncmp(sys, adp->ad_name, syslen) != 0) + continue; + + *attrtype = adp->ad_type; + goto out; } return (ENOENT); } - if(namelen) { + out: + if (namelen) { MALLOC((*attrname), char *, namelen, M_TEMP, M_WAITOK); memcpy((*attrname), name, namelen); (*attrname)[namelen] = '\0'; @@ -886,6 +851,11 @@ ntfs_ntlookupfile( int error, res, anamelen, fnamelen; const char *fname,*aname; u_int32_t aoff; + int attrtype = NTFS_A_DATA; + char *attrname = NULL; + struct fnode *nfp; + struct vnode *nvp; + enum vtype f_type; error = ntfs_ntget(ip); if (error) @@ -919,7 +889,7 @@ ntfs_ntlookupfile( MALLOC(rdbuf, caddr_t, blsize, M_TEMP, M_WAITOK); error = ntfs_readattr(ntmp, ip, NTFS_A_INDXROOT, "$I30", - 0, rdsize, rdbuf); + 0, rdsize, rdbuf, NULL); if (error) goto fail; @@ -928,105 +898,104 @@ ntfs_ntlookupfile( do { iep = (struct attr_indexentry *) (rdbuf + aoff); - while (!(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff)) { + for (; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff); + aoff += iep->reclen, + iep = (struct attr_indexentry *) (rdbuf + aoff)) + { ddprintf(("scan: %d, %d\n", (u_int32_t) iep->ie_number, (u_int32_t) iep->ie_fnametype)); - res = ntfs_uastricmp(ntmp, iep->ie_fname, - iep->ie_fnamelen, fname, - fnamelen); - if (res == 0) { - /* Matched something (case ins.) */ - if (iep->ie_fnametype == 0 || - !(ntmp->ntm_flag & NTFS_MFLAG_CASEINS)) - res = ntfs_uastrcmp(ntmp, - iep->ie_fname, - iep->ie_fnamelen, - fname, - fnamelen); - if (res == 0) { - int attrtype = NTFS_A_DATA; - char *attrname = NULL; - struct fnode *nfp; - struct vnode *nvp; - - if (aname) { - error = ntfs_ntlookupattr(ntmp, - aname, anamelen, - &attrtype, &attrname); - if (error) - goto fail; - } - /* 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; - } + /* check the name - the case-insensitible check + * has to come first, to break from this for loop + * if needed, so we can dive correctly */ + res = ntfs_uastricmp(iep->ie_fname, iep->ie_fnamelen, + fname, fnamelen); + if (res > 0) break; + if (res < 0) continue; + + if (iep->ie_fnametype == 0 || + !(ntmp->ntm_flag & NTFS_MFLAG_CASEINS)) + { + res = ntfs_uastrcmp(iep->ie_fname, + iep->ie_fnamelen, fname, fnamelen); + if (res != 0) continue; + } - /* vget node, but don't load it */ - error = ntfs_vgetex(ntmp->ntm_mountp, - iep->ie_number, - attrtype, - attrname, - LK_EXCLUSIVE, - VG_DONTLOADIN | - VG_DONTVALIDFN, - curproc, - &nvp); - if(error) - goto fail; - - nfp = VTOF(nvp); - - if (nfp->f_flag & FN_VALID) { - *vpp = nvp; - goto fail; - } + if (aname) { + error = ntfs_ntlookupattr(ntmp, + aname, anamelen, + &attrtype, &attrname); + if (error) + goto fail; + } - 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 */ - nfp->f_size = iep->ie_fsize; - nfp->f_allocated = iep->ie_fallocated; - nfp->f_flag |= FN_PRELOADED; - } else { - error = ntfs_filesize(ntmp, nfp, - &nfp->f_size, - &nfp->f_allocated); - if (error) { - vput(nvp); - goto fail; - } - } + /* 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; + error = 0; + goto fail; + } + + /* free the buffer returned by ntfs_ntlookupattr() */ + if (attrname) { + FREE(attrname, M_TEMP); + attrname = NULL; + } + + /* vget node, but don't load it */ + error = ntfs_vgetex(ntmp->ntm_mountp, + iep->ie_number, attrtype, attrname, + LK_EXCLUSIVE, VG_DONTLOADIN | VG_DONTVALIDFN, + curproc, &nvp); + if (error) + goto fail; + + nfp = VTOF(nvp); + + if (nfp->f_flag & FN_VALID) { + *vpp = nvp; + goto fail; + } + + 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)) + f_type = VDIR; + else + f_type = VREG; - nfp->f_flag &= ~FN_VALID; - *vpp = nvp; + nvp->v_type = f_type; + + if ((nfp->f_attrtype == NTFS_A_DATA) && + (nfp->f_attrname == NULL)) + { + /* Opening default attribute */ + nfp->f_size = iep->ie_fsize; + nfp->f_allocated = iep->ie_fallocated; + nfp->f_flag |= FN_PRELOADED; + } else { + error = ntfs_filesize(ntmp, nfp, + &nfp->f_size, &nfp->f_allocated); + if (error) { + vput(nvp); goto fail; } - } else if (res > 0) - break; + } - aoff += iep->reclen; - iep = (struct attr_indexentry *) (rdbuf + aoff); + nfp->f_flag &= ~FN_VALID; + *vpp = nvp; + goto fail; } /* Dive if possible */ @@ -1038,7 +1007,7 @@ ntfs_ntlookupfile( rdsize = blsize; error = ntfs_readattr(ntmp, ip, NTFS_A_INDX, "$I30", - ntfs_cntob(cn), rdsize, rdbuf); + ntfs_cntob(cn), rdsize, rdbuf, NULL); if (error) goto fail; @@ -1059,6 +1028,7 @@ ntfs_ntlookupfile( dprintf(("finish\n")); fail: + if (attrname) FREE(attrname, M_TEMP); ntfs_ntvattrrele(vap); ntfs_ntput(ip); FREE(rdbuf, M_TEMP); @@ -1073,7 +1043,6 @@ ntfs_isnamepermitted( struct ntfsmount * ntmp, struct attr_indexentry * iep) { - if (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES) return 1; @@ -1151,7 +1120,7 @@ ntfs_ntreaddir( } MALLOC(bmp, u_char *, bmvap->va_datalen, M_TEMP, M_WAITOK); error = ntfs_readattr(ntmp, ip, NTFS_A_INDXBITMAP, "$I30", 0, - bmvap->va_datalen, bmp); + bmvap->va_datalen, bmp, NULL); if (error) goto fail; @@ -1188,7 +1157,7 @@ ntfs_ntreaddir( attrnum, (u_int32_t) blnum, cnum, num, aoff)); rdsize = (attrnum == NTFS_A_INDXROOT) ? vap->va_datalen : blsize; error = ntfs_readattr(ntmp, ip, attrnum, "$I30", - ntfs_cntob(blnum * cpbl), rdsize, rdbuf); + ntfs_cntob(blnum * cpbl), rdsize, rdbuf, NULL); if (error) goto fail; @@ -1204,23 +1173,24 @@ ntfs_ntreaddir( sizeof(struct attr_indexroot); iep = (struct attr_indexentry *) (rdbuf + aoff); - while (!(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff)) { - if (ntfs_isnamepermitted(ntmp, iep)) { - if (cnum >= num) { - fp->f_lastdnum = cnum; - fp->f_lastdoff = aoff; - fp->f_lastdblnum = blnum; - fp->f_lastdattr = attrnum; + for (; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff); + aoff += iep->reclen, + iep = (struct attr_indexentry *) (rdbuf + aoff)) + { + if (!ntfs_isnamepermitted(ntmp, iep)) continue; - *riepp = iep; + if (cnum >= num) { + fp->f_lastdnum = cnum; + fp->f_lastdoff = aoff; + fp->f_lastdblnum = blnum; + fp->f_lastdattr = attrnum; - error = 0; - goto fail; - } - cnum++; + *riepp = iep; + + error = 0; + goto fail; } - aoff += iep->reclen; - iep = (struct attr_indexentry *) (rdbuf + aoff); + cnum++; } if (iavap) { @@ -1349,19 +1319,18 @@ ntfs_filesize( /* * This is one of write routine. - * - * ntnode should be locked. */ int 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) + struct ntfsmount * ntmp, + struct ntnode * ip, + u_int32_t attrnum, + char *attrname, + off_t roff, + size_t rsize, + void *rdata, + size_t * initp, + struct uio *uio) { size_t init; int error = 0; @@ -1382,7 +1351,7 @@ ntfs_writeattr_plain( (u_int32_t) vap->va_vcnend)); error = ntfs_writentvattr_plain(ntmp, ip, vap, off - ntfs_cntob(vap->va_vcnstart), - towrite, data, &init); + towrite, data, &init, uio); if (error) { printf("ntfs_writeattr_plain: " \ "ntfs_writentvattr_plain failed: o: %d, s: %d\n", @@ -1410,101 +1379,104 @@ ntfs_writeattr_plain( */ int ntfs_writentvattr_plain( - struct ntfsmount * ntmp, - struct ntnode * ip, - struct ntvattr * vap, - off_t roff, - size_t rsize, - void *rdata, - size_t * initp) + struct ntfsmount * ntmp, + struct ntnode * ip, + struct ntvattr * vap, + off_t roff, + size_t rsize, + void *rdata, + size_t * initp, + struct uio *uio) { int error = 0; int off; + int cnt; + cn_t ccn, ccl, cn, left, cl; + caddr_t data = rdata; + struct buf *bp; + size_t tocopy; *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)); + if ((vap->va_flag & NTFS_AF_INRUN) == 0) { + printf("ntfs_writevattr_plain: CAN'T WRITE RES. ATTRIBUTE\n"); + return ENOTTY; + } - 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: data in run: %d chains\n", + vap->va_vruncnt)); - 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)); + off = roff; + left = rsize; + ccl = 0; + ccn = 0; + cnt = 0; + for (; left && (cnt < vap->va_vruncnt); cnt++) { + ccn = vap->va_vruncn[cnt]; + ccl = vap->va_vruncl[cnt]; - 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); + 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)); - 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); - bawrite(bp); - data = data + tocopy; - *initp += tocopy; - off = 0; - left -= tocopy; - cn += cl; - ccl -= cl; - } - } + if (ntfs_cntob(ccl) < off) { + off -= ntfs_cntob(ccl); cnt++; + continue; } - if (left) { - printf("ntfs_writentvattr_plain: POSSIBLE RUN ERROR\n"); - error = EINVAL; + if (!ccn && ip->i_number != NTFS_BOOTINO) + continue; /* XXX */ + + ccl -= ntfs_btocn(off); + cn = ccn + ntfs_btocn(off); + off = ntfs_btocnoff(off); + + while (left && ccl) { +#if defined(__FreeBSD__) + tocopy = min(left, + min(ntfs_cntob(ccl) - off, MAXBSIZE - off)); +#else + /* under NetBSD, bread() can read + * maximum one block worth of data */ + tocopy = min(left, ntmp->ntm_bps - off); +#endif + 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); + } + } + if (uio) + uiomove(bp->b_data + off, tocopy, uio); + else + memcpy(bp->b_data + off, data, tocopy); + bawrite(bp); + data = data + tocopy; + *initp += tocopy; + off = 0; + left -= tocopy; + cn += cl; + ccl -= cl; } - } else { - printf("ntfs_writevattr_plain: CAN'T WRITE RES. ATTRIBUTE\n"); - error = ENOTTY; + } + + if (left) { + printf("ntfs_writentvattr_plain: POSSIBLE RUN ERROR\n"); + error = EINVAL; } return (error); @@ -1517,13 +1489,14 @@ ntfs_writentvattr_plain( */ int ntfs_readntvattr_plain( - struct ntfsmount * ntmp, - struct ntnode * ip, - struct ntvattr * vap, - off_t roff, - size_t rsize, - void *rdata, - size_t * initp) + struct ntfsmount * ntmp, + struct ntnode * ip, + struct ntvattr * vap, + off_t roff, + size_t rsize, + void *rdata, + size_t * initp, + struct uio *uio) { int error = 0; int off; @@ -1564,9 +1537,16 @@ ntfs_readntvattr_plain( off = ntfs_btocnoff(off); while (left && ccl) { +#if defined(__FreeBSD__) tocopy = min(left, min(ntfs_cntob(ccl) - off, MAXBSIZE - off)); +#else + /* under NetBSD, bread() can read + * maximum one block worth of data */ + tocopy = min(left, + ntmp->ntm_bps - off); +#endif cl = ntfs_btocl(tocopy + off); ddprintf(("ntfs_readntvattr_plain: " \ "read: cn: 0x%x cl: %d, " \ @@ -1584,7 +1564,13 @@ ntfs_readntvattr_plain( brelse(bp); return (error); } - memcpy(data, bp->b_data + off, tocopy); + if (uio) { + uiomove(bp->b_data + off, + tocopy, uio); + } else { + memcpy(data, bp->b_data + off, + tocopy); + } brelse(bp); data = data + tocopy; *initp += tocopy; @@ -1596,14 +1582,19 @@ ntfs_readntvattr_plain( } else { tocopy = min(left, ntfs_cntob(ccl) - off); ddprintf(("ntfs_readntvattr_plain: " - "sparce: ccn: 0x%x ccl: %d, off: %d, " \ + "hole: ccn: 0x%x ccl: %d, off: %d, " \ " len: %d, left: %d\n", (u_int32_t) ccn, (u_int32_t) ccl, (u_int32_t) off, (u_int32_t) tocopy, (u_int32_t) left)); left -= tocopy; off = 0; - bzero(data, tocopy); + if (uio) { + size_t remains = tocopy; + for(; remains; remains++) + uiomove("", 1, uio); + } else + bzero(data, tocopy); data = data + tocopy; } cnt++; @@ -1614,7 +1605,10 @@ ntfs_readntvattr_plain( } } else { ddprintf(("ntfs_readnvattr_plain: data is in mft record\n")); - memcpy(rdata, vap->va_datap + roff, rsize); + if (uio) + uiomove(vap->va_datap + roff, rsize, uio); + else + memcpy(rdata, vap->va_datap + roff, rsize); *initp += rsize; } @@ -1623,19 +1617,18 @@ ntfs_readntvattr_plain( /* * This is one of read routines. - * - * ntnode should be locked. */ int ntfs_readattr_plain( - struct ntfsmount * ntmp, - struct ntnode * ip, - u_int32_t attrnum, - char *attrname, - off_t roff, - size_t rsize, - void *rdata, - size_t * initp) + struct ntfsmount * ntmp, + struct ntnode * ip, + u_int32_t attrnum, + char *attrname, + off_t roff, + size_t rsize, + void *rdata, + size_t * initp, + struct uio *uio) { size_t init; int error = 0; @@ -1656,7 +1649,7 @@ ntfs_readattr_plain( (u_int32_t) vap->va_vcnend)); error = ntfs_readntvattr_plain(ntmp, ip, vap, off - ntfs_cntob(vap->va_vcnstart), - toread, data, &init); + toread, data, &init, uio); if (error) { printf("ntfs_readattr_plain: " \ "ntfs_readntvattr_plain failed: o: %d, s: %d\n", @@ -1679,18 +1672,17 @@ ntfs_readattr_plain( /* * This is one of read routines. - * - * ntnode should be locked. */ int ntfs_readattr( - struct ntfsmount * ntmp, - struct ntnode * ip, - u_int32_t attrnum, - char *attrname, - off_t roff, - size_t rsize, - void *rdata) + struct ntfsmount * ntmp, + struct ntnode * ip, + u_int32_t attrnum, + char *attrname, + off_t roff, + size_t rsize, + void *rdata, + struct uio *uio) { int error = 0; struct ntvattr *vap; @@ -1731,21 +1723,33 @@ ntfs_readattr( error = ntfs_readattr_plain(ntmp, ip, attrnum, attrname, ntfs_cntob(cn), ntfs_cntob(NTFS_COMPUNIT_CL), - cup, &init); + cup, &init, NULL); if (error) break; tocopy = min(left, ntfs_cntob(NTFS_COMPUNIT_CL) - off); if (init == ntfs_cntob(NTFS_COMPUNIT_CL)) { - memcpy(data, cup + off, tocopy); + if (uio) + uiomove(cup + off, tocopy, uio); + else + memcpy(data, cup + off, tocopy); } else if (init == 0) { - bzero(data, tocopy); + if (uio) { + size_t remains = tocopy; + for(; remains; remains--) + uiomove("", 1, uio); + } + else + bzero(data, tocopy); } else { error = ntfs_uncompunit(ntmp, uup, cup); if (error) break; - memcpy(data, uup + off, tocopy); + if (uio) + uiomove(uup + off, tocopy, uio); + else + memcpy(data, uup + off, tocopy); } left -= tocopy; @@ -1758,7 +1762,7 @@ ntfs_readattr( FREE(cup, M_NTFSDECOMP); } else error = ntfs_readattr_plain(ntmp, ip, attrnum, attrname, - roff, rsize, rdata, &init); + roff, rsize, rdata, &init, uio); ntfs_ntvattrrele(vap); return (error); } @@ -1831,8 +1835,8 @@ ntfs_procfixups( } if ((fhp->fh_fnum - 1) * ntmp->ntm_bps != len) { printf("ntfs_procfixups: " \ - "bad fixups number: %d for %d bytes block\n", - fhp->fh_fnum, len); + "bad fixups number: %d for %ld bytes block\n", + fhp->fh_fnum, (long)len); /* XXX printf kludge */ return (EINVAL); } if (fhp->fh_foff >= ntmp->ntm_spc * ntmp->ntm_mftrecsz * ntmp->ntm_bps) { @@ -1897,3 +1901,95 @@ ntfs_runtocn( return (0); } #endif + +/* + * this initializes toupper table & dependant variables to be ready for + * later work + */ +void +ntfs_toupper_init() +{ + ntfs_toupper_tab = (wchar *) NULL; + lockinit(&ntfs_toupper_lock, PVFS, "ntfs_toupper", 0, 0); + ntfs_toupper_usecount = 0; +} + +/* + * if the ntfs_toupper_tab[] is filled already, just raise use count; + * otherwise read the data from the filesystem we are currently mounting + */ +int +ntfs_toupper_use(mp, ntmp) + struct mount *mp; + struct ntfsmount *ntmp; +{ + int error = 0; + struct vnode *vp; + + /* get exclusive access */ + LOCKMGR(&ntfs_toupper_lock, LK_EXCLUSIVE, NULL); + + /* only read the translation data from a file if it hasn't been + * read already */ + if (ntfs_toupper_tab) + goto out; + + /* + * Read in Unicode lowercase -> uppercase translation file. + * XXX for now, just the first 256 entries are used anyway, + * so don't bother reading more + */ + MALLOC(ntfs_toupper_tab, wchar *, 256 * sizeof(wchar), + M_NTFSRDATA, M_WAITOK); + + if ((error = VFS_VGET(mp, NTFS_UPCASEINO, &vp))) + goto out; + error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, + 0, 256*sizeof(wchar), (char *) ntfs_toupper_tab, NULL); + vput(vp); + + out: + ntfs_toupper_usecount++; + LOCKMGR(&ntfs_toupper_lock, LK_RELEASE, NULL); + return (error); +} + +/* + * lower the use count and if it reaches zero, free the memory + * tied by toupper table + */ +void +ntfs_toupper_unuse() +{ + /* get exclusive access */ + LOCKMGR(&ntfs_toupper_lock, LK_EXCLUSIVE, NULL); + + ntfs_toupper_usecount--; + if (ntfs_toupper_usecount == 0) { + FREE(ntfs_toupper_tab, M_NTFSRDATA); + ntfs_toupper_tab = NULL; + } +#ifdef DIAGNOSTIC + else if (ntfs_toupper_usecount < 0) { + panic("ntfs_toupper_unuse(): use count negative: %d\n", + ntfs_toupper_usecount); + } +#endif + + /* release the lock */ + LOCKMGR(&ntfs_toupper_lock, LK_RELEASE, NULL); +} + +/* + * maps the Unicode char to 8bit equivalent + * XXX currently only gets lower 8bit from the Unicode char + * and substitutes a '_' for it if the result would be '\0'; + * something better has to be definitely though out + */ +char +ntfs_u28(unichar) + wchar unichar; +{ + return (char) NTFS_U28(unichar); +} + diff --git a/sys/fs/ntfs/ntfs_subr.h b/sys/fs/ntfs/ntfs_subr.h index f0b9a8a..7f2d793 100644 --- a/sys/fs/ntfs/ntfs_subr.h +++ b/sys/fs/ntfs/ntfs_subr.h @@ -1,4 +1,4 @@ -/* $NetBSD: ntfs_subr.h,v 1.2 1999/05/06 15:43:20 christos Exp $ */ +/* $NetBSD: ntfs_subr.h,v 1.8 1999/10/10 14:48:37 jdolecek Exp $ */ /*- * Copyright (c) 1998, 1999 Semen Ustimenko @@ -70,34 +70,17 @@ struct ntvattr { #define va_a_iroot va_d.iroot #define va_a_ialloc va_d.ialloc - -#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 *, 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_readntvattr_plain __P(( struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *,size_t *, struct uio *)); +int ntfs_readattr_plain __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *,size_t *, struct uio *)); +int ntfs_readattr __P(( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *, struct uio *)); 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 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 *, const wchar *, int, const char *, - int )); -int ntfs_uastrcmp __P(( struct ntfsmount *, const wchar *, int, const char *, - int )); +char ntfs_u28 __P((wchar)); 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 * )); @@ -106,12 +89,17 @@ struct ntvattr * ntfs_findntvattr __P(( struct ntfsmount *, struct ntnode *, u_i int ntfs_ntlookupfile __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_ntvattrget __P((struct ntfsmount *, struct ntnode *, u_int32_t, const char *, cn_t , struct ntvattr **)); int ntfs_ntlookup __P((struct ntfsmount *, ino_t, struct ntnode **)); int ntfs_ntget __P((struct ntnode *)); +void ntfs_ntref __P((struct ntnode *)); void ntfs_ntrele __P((struct ntnode *)); void ntfs_ntput __P((struct ntnode *)); int ntfs_loadntnode __P(( struct ntfsmount *, struct ntnode * )); -int ntfs_ntlookupattr(struct ntfsmount *, const 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 *); +int ntfs_writentvattr_plain __P((struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *, size_t *, struct uio *)); +int ntfs_writeattr_plain __P((struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *, size_t *, struct uio *)); +void ntfs_toupper_init __P((void)); +int ntfs_toupper_use __P((struct mount *, struct ntfsmount *)); +void ntfs_toupper_unuse __P((void)); +int ntfs_fget __P((struct ntfsmount *, struct ntnode *, int, char *, struct fnode **)); +void ntfs_frele __P((struct fnode *)); diff --git a/sys/fs/ntfs/ntfs_vfsops.c b/sys/fs/ntfs/ntfs_vfsops.c index ffd2412..9ad0775 100644 --- a/sys/fs/ntfs/ntfs_vfsops.c +++ b/sys/fs/ntfs/ntfs_vfsops.c @@ -1,4 +1,4 @@ -/* $NetBSD: ntfs_vfsops.c,v 1.2 1999/05/06 15:43:20 christos Exp $ */ +/* $NetBSD: ntfs_vfsops.c,v 1.23 1999/11/15 19:38:14 jdolecek Exp $ */ /*- * Copyright (c) 1998, 1999 Semen Ustimenko @@ -40,20 +40,30 @@ #include <sys/buf.h> #include <sys/fcntl.h> #include <sys/malloc.h> +#include <sys/systm.h> +#if defined(__NetBSD__) +#include <sys/device.h> +#endif #include <vm/vm.h> #include <vm/vm_param.h> +#if defined(__NetBSD__) +#include <vm/vm_prot.h> +#endif #include <vm/vm_page.h> #include <vm/vm_object.h> #include <vm/vm_extern.h> +#if defined(__NetBSD__) +#include <miscfs/specfs/specdev.h> +#endif + /*#define NTFS_DEBUG 1*/ #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 defined(__FreeBSD__) @@ -63,13 +73,6 @@ MALLOC_DEFINE(M_NTFSFNODE,"NTFS fnode", "NTFS fnode information"); MALLOC_DEFINE(M_NTFSDIR,"NTFS dir", "NTFS dir buffer"); #endif -#if defined(__FreeBSD__) -static int ntfs_mount __P((struct mount *, char *, caddr_t, - struct nameidata *, struct proc *)); -#else -static int ntfs_mount __P((struct mount *, const char *, void *, - struct nameidata *, struct proc *)); -#endif static int ntfs_root __P((struct mount *, struct vnode **)); static int ntfs_statfs __P((struct mount *, struct statfs *, struct proc *)); @@ -78,53 +81,70 @@ static int ntfs_vget __P((struct mount *mp, ino_t ino, struct vnode **vpp)); static int ntfs_mountfs __P((register struct vnode *, struct mount *, struct ntfs_args *, struct proc *)); +static int ntfs_vptofh __P((struct vnode *, struct fid *)); +static int ntfs_fhtovp __P((struct mount *, struct fid *, + struct vnode **)); -#if !defined(__FreeBSD__) +#if !defined (__FreeBSD__) static int ntfs_quotactl __P((struct mount *, int, uid_t, caddr_t, struct proc *)); static int ntfs_start __P((struct mount *, int, struct proc *)); static int ntfs_sync __P((struct mount *, int, struct ucred *, struct proc *)); -static int ntfs_vptofh __P((struct vnode *, struct fid *)); -#endif /* !defined(__FreeBSD__) */ +#endif #if defined(__FreeBSD__) +struct sockaddr; +static int ntfs_mount __P((struct mount *, char *, caddr_t, + struct nameidata *, struct proc *)); static int ntfs_init __P((struct vfsconf *)); -#if 0 /* may be implemented at a later date */ -static int ntfs_fhtovp __P((struct mount *, struct fid *, - struct vnode **)); -static int ntfs_checkexp __P((struct vnode *, struct mbuf *, +static int ntfs_checkexp __P((struct mount *, struct sockaddr *, int *, struct ucred **)); -#endif /* 0, default ops in FreeBSD */ #elif defined(__NetBSD__) +static int ntfs_mount __P((struct mount *, const char *, void *, + struct nameidata *, struct proc *)); static void ntfs_init __P((void)); -static int ntfs_fhtovp __P((struct mount *, struct fid *, - struct vnode **)); -static int ntfs_checkexp __P((struct mount *, struct mbuf *, - int *, struct ucred **)); static int ntfs_mountroot __P((void)); static int ntfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t, struct proc *)); -#else -static int ntfs_init __P((void)); -static int ntfs_fhtovp __P((struct mount *, struct fid *, - struct mbuf *, struct vnode **, - int *, struct ucred **)); +static int ntfs_checkexp __P((struct mount *, struct mbuf *, + int *, struct ucred **)); #endif -#ifdef __NetBSD__ -/*ARGSUSED*/ +/* + * Verify a remote client has export rights and return these rights via. + * exflagsp and credanonp. + */ static int ntfs_checkexp(mp, nam, exflagsp, credanonp) +#if defined(__FreeBSD__) + register struct mount *mp; + struct sockaddr *nam; + int *exflagsp; + struct ucred **credanonp; +#else /* defined(__NetBSD__) */ register struct mount *mp; struct mbuf *nam; int *exflagsp; struct ucred **credanonp; +#endif { + register struct netcred *np; + register struct ntfsmount *ntm = VFSTONTFS(mp); - return (EINVAL); + /* + * Get the export permission structure for this <mp, client> tuple. + */ + np = vfs_export_lookup(mp, &ntm->ntm_export, nam); + if (np == NULL) + return (EACCES); + + *exflagsp = np->netc_exflags; + *credanonp = &np->netc_anon; + return (0); } +#if defined(__NetBSD__) /*ARGSUSED*/ static int ntfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) @@ -142,28 +162,67 @@ ntfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) static int ntfs_mountroot() { - return (EINVAL); + struct mount *mp; + extern struct vnode *rootvp; + struct proc *p = curproc; /* XXX */ + int error; + struct ntfs_args args; + + if (root_device->dv_class != DV_DISK) + return (ENODEV); + + /* + * Get vnodes for rootdev. + */ + if (bdevvp(rootdev, &rootvp)) + panic("ntfs_mountroot: can't setup rootvp"); + + if ((error = vfs_rootmountalloc(MOUNT_NTFS, "root_device", &mp))) { + vrele(rootvp); + return (error); + } + + args.flag = 0; + args.uid = 0; + args.gid = 0; + args.mode = 0777; + + if ((error = ntfs_mountfs(rootvp, mp, &args, p)) != 0) { + mp->mnt_op->vfs_refcount--; + vfs_unbusy(mp); + free(mp, M_MOUNT); + vrele(rootvp); + return (error); + } + + simple_lock(&mountlist_slock); + CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); + simple_unlock(&mountlist_slock); + (void)ntfs_statfs(mp, &mp->mnt_stat, p); + vfs_unbusy(mp); + return (0); } -#endif -#if defined(__FreeBSD__) -static int -ntfs_init ( - struct vfsconf *vcp ) -#elif defined(__NetBSD__) static void ntfs_init () -#else +{ + ntfs_nthashinit(); + ntfs_toupper_init(); +} + +#elif defined(__FreeBSD__) + static int -ntfs_init () -#endif +ntfs_init ( + struct vfsconf *vcp ) { ntfs_nthashinit(); -#if !defined(__NetBSD__) + ntfs_toupper_init(); return 0; -#endif } +#endif /* NetBSD */ + static int ntfs_mount ( struct mount *mp, @@ -177,11 +236,12 @@ ntfs_mount ( struct nameidata *ndp, struct proc *p ) { - u_int size; + size_t size; int err = 0; struct vnode *devvp; struct ntfs_args args; +#ifdef __FreeBSD__ /* * Use NULL path to flag a root mount */ @@ -212,6 +272,7 @@ ntfs_mount ( goto dostatfs; /* success*/ } +#endif /* FreeBSD */ /* *** @@ -229,57 +290,20 @@ ntfs_mount ( * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { - printf("ntfs_mount(): MNT_UPDATE not supported\n"); - err = EINVAL; - goto error_1; - -#if 0 - ump = VFSTOUFS(mp); - fs = ump->um_fs; - err = 0; - if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { - flags = WRITECLOSE; - if (mp->mnt_flag & MNT_FORCE) - flags |= FORCECLOSE; - if (vfs_busy(mp)) { - err = EBUSY; - goto error_1; - } - err = ffs_flushfiles(mp, flags, p); - vfs_unbusy(mp); - } - if (!err && (mp->mnt_flag & MNT_RELOAD)) - err = ffs_reload(mp, ndp->ni_cnd.cn_cred, p); - if (err) { - goto error_1; - } - if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) { - if (!fs->fs_clean) { - if (mp->mnt_flag & MNT_FORCE) { - printf("WARNING: %s was not properly dismounted.\n",fs->fs_fsmnt); - } else { - printf("WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck.\n", - fs->fs_fsmnt); - err = EPERM; - goto error_1; - } - } - fs->fs_ronly = 0; - } - if (fs->fs_ronly == 0) { - fs->fs_clean = 0; - ffs_sbupdate(ump, MNT_WAIT); - } /* if not updating name...*/ if (args.fspec == 0) { /* * Process export requests. Jumping to "success" * will return the vfs_export() error code. */ - err = vfs_export(mp, &ump->um_export, &args.export); + struct ntfsmount *ntm = VFSTONTFS(mp); + err = vfs_export(mp, &ntm->ntm_export, &args.export); goto success; } -#endif + + printf("ntfs_mount(): MNT_UPDATE not supported\n"); + err = EINVAL; + goto error_1; } /* @@ -295,10 +319,21 @@ ntfs_mount ( devvp = ndp->ni_vp; +#if defined(__FreeBSD__) if (!vn_isdisk(devvp)) { err = ENOTBLK; goto error_2; } +#else + if (devvp->v_type != VBLK) { + err = ENOTBLK; + goto error_2; + } + if (major(devvp->v_rdev) >= nblkdev) { + err = ENXIO; + goto error_2; + } +#endif if (mp->mnt_flag & MNT_UPDATE) { #if 0 /* @@ -356,7 +391,9 @@ ntfs_mount ( goto error_2; } +#ifdef __FreeBSD__ dostatfs: +#endif /* * Initialize FS stat information in mount struct; uses both * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname @@ -376,7 +413,7 @@ error_2: /* error with devvp held*/ error_1: /* no state to back out*/ success: - return( err); + return(err); } /* @@ -412,9 +449,9 @@ ntfs_mountfs(devvp, mp, argsp, p) if (ncount > 1 && devvp != rootvp) return (EBUSY); #if defined(__FreeBSD__) - vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); + VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, p); error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0); - VOP_UNLOCK(devvp, 0, p); + VOP__UNLOCK(devvp, 0, p); #else error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0); #endif @@ -422,9 +459,9 @@ ntfs_mountfs(devvp, mp, argsp, p) return (error); ronly = (mp->mnt_flag & MNT_RDONLY) != 0; - vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); + VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, p); error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p); - VOP_UNLOCK(devvp, 0, p); + VOP__UNLOCK(devvp, 0, p); if (error) return (error); @@ -441,7 +478,7 @@ ntfs_mountfs(devvp, mp, argsp, p) if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) { error = EINVAL; - printf("ntfs_mountfs: invalid boot block\n"); + dprintf(("ntfs_mountfs: invalid boot block\n")); goto out; } @@ -488,20 +525,9 @@ ntfs_mountfs(devvp, mp, argsp, p) } } - /* - * Read in WHOLE lowcase -> upcase translation - * file. - */ - MALLOC(ntmp->ntm_upcase, wchar *, 65536 * sizeof(wchar), - M_NTFSMNT, M_WAITOK); - - error = VFS_VGET(mp, NTFS_UPCASEINO, &vp); - if(error) - goto out1; - error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, - 0, 65536*sizeof(wchar), ntmp->ntm_upcase); - vput(vp); - if(error) + /* read the Unicode lowercase --> uppercase translation table, + * if necessary */ + if ((error = ntfs_toupper_use(mp, ntmp))) goto out1; /* @@ -529,7 +555,7 @@ ntfs_mountfs(devvp, mp, argsp, p) error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, num * sizeof(ad), sizeof(ad), - &ad); + &ad, NULL); if (error) goto out1; if (ad.ad_name[0] == 0) @@ -548,7 +574,7 @@ ntfs_mountfs(devvp, mp, argsp, p) error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, i * sizeof(ad), sizeof(ad), - &ad); + &ad, NULL); if (error) goto out1; j = 0; @@ -562,19 +588,16 @@ ntfs_mountfs(devvp, mp, argsp, p) vput(vp); } - mp->mnt_stat.f_fsid.val[0] = dev2udev(dev); #if defined(__FreeBSD__) + mp->mnt_stat.f_fsid.val[0] = dev2udev(dev); mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; #else + mp->mnt_stat.f_fsid.val[0] = dev; mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_NTFS); #endif mp->mnt_maxsymlinklen = 0; mp->mnt_flag |= MNT_LOCAL; -#if defined(__FreeBSD__) devvp->v_specmountpoint = mp; -#else - devvp->v_specflags |= SI_MOUNTEDON; -#endif return (0); out1: @@ -582,17 +605,22 @@ out1: if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); if (vflush(mp,NULLVP,0)) - printf("ntfs_mountfs: vflush failed\n"); + dprintf(("ntfs_mountfs: vflush failed\n")); out: -#if defined(__FreeBSD__) devvp->v_specmountpoint = NULL; -#else - devvp->v_specflags &= ~SI_MOUNTEDON; -#endif if (bp) brelse(bp); + +#if defined __NetBSD__ + /* lock the device vnode before calling VOP_CLOSE() */ + VN_LOCK(devvp, LK_EXCLUSIVE | LK_RETRY, p); + (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); + VOP__UNLOCK(devvp, 0, p); +#else (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); +#endif + return (error); } @@ -605,7 +633,7 @@ ntfs_start ( { return (0); } -#endif /* !defined(__FreeBSD__) */ +#endif static int ntfs_unmount( @@ -635,7 +663,7 @@ ntfs_unmount( if((ntmp->ntm_sysvn[i]) && (ntmp->ntm_sysvn[i]->v_usecount > 1)) return (EBUSY); - /* Derefernce all system vnodes */ + /* Dereference all system vnodes */ for(i=0;i<NTFS_SYSNODESNUM;i++) if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); @@ -644,23 +672,35 @@ ntfs_unmount( if (error) printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error); -#if defined(__FreeBSD__) - ntmp->ntm_devvp->v_specmountpoint = NULL; -#else - ntmp->ntm_devvp->v_specflags &= ~SI_MOUNTEDON; -#endif + /* Check if the type of device node isn't VBAD before + * touching v_specinfo. If the device vnode is revoked, the + * field is NULL and touching it causes null pointer derefercence. + */ + if (ntmp->ntm_devvp->v_type != VBAD) + ntmp->ntm_devvp->v_specmountpoint = NULL; vinvalbuf(ntmp->ntm_devvp, V_SAVE, NOCRED, p, 0, 0); + +#if defined(__NetBSD__) + /* lock the device vnode before calling VOP_CLOSE() */ + VOP_LOCK(ntmp->ntm_devvp, LK_EXCLUSIVE | LK_RETRY); + error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE, + NOCRED, p); + VOP__UNLOCK(ntmp->ntm_devvp, 0, p); +#else error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); +#endif vrele(ntmp->ntm_devvp); + /* free the toupper table, if this has been last mounted ntfs volume */ + ntfs_toupper_unuse(); + dprintf(("ntfs_umount: freeing memory...\n")); mp->mnt_data = (qaddr_t)0; mp->mnt_flag &= ~MNT_LOCAL; FREE(ntmp->ntm_ad, M_NTFSMNT); - FREE(ntmp->ntm_upcase, M_NTFSMNT); FREE(ntmp, M_NTFSMNT); return (error); } @@ -697,7 +737,7 @@ ntfs_quotactl ( printf("\nntfs_quotactl():\n"); return EOPNOTSUPP; } -#endif /* !defined(__FreeBSD__) */ +#endif int ntfs_calccfree( @@ -717,21 +757,18 @@ ntfs_calccfree( MALLOC(tmp, u_int8_t *, bmsize, M_TEMP, M_WAITOK); error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, - 0, bmsize, tmp); - if(error) { - FREE(tmp, M_TEMP); - return (error); - } + 0, bmsize, tmp, NULL); + if (error) + goto out; for(i=0;i<bmsize;i++) for(j=0;j<8;j++) if(~tmp[i] & (1 << j)) cfree++; - - FREE(tmp, M_TEMP); - *cfreep = cfree; - return(0); + out: + FREE(tmp, M_TEMP); + return(error); } static int @@ -769,6 +806,9 @@ ntfs_statfs( (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); } sbp->f_flags = mp->mnt_flag; +#ifdef __NetBSD__ + strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN); +#endif return (0); } @@ -784,34 +824,31 @@ ntfs_sync ( /*dprintf(("ntfs_sync():\n"));*/ return (0); } -#endif /* !defined(__FreeBSD__) */ +#endif -#if !defined(__FreeBSD__) /*ARGSUSED*/ static int ntfs_fhtovp( -#if defined(__FreeBSD__) - struct mount *mp, - struct fid *fhp, - struct sockaddr *nam, - struct vnode **vpp, - int *exflagsp, - struct ucred **credanonp) -#elif defined(__NetBSD__) struct mount *mp, struct fid *fhp, struct vnode **vpp) -#else - struct mount *mp, - struct fid *fhp, - struct mbuf *nam, - struct vnode **vpp, - int *exflagsp, - struct ucred **credanonp) -#endif { - printf("\ntfs_fhtovp():\n"); - return 0; + struct vnode *nvp; + struct ntfid *ntfhp = (struct ntfid *)fhp; + int error; + + ddprintf(("ntfs_fhtovp(): %s: %d\n", mp->mnt_stat->f_mntonname, + ntfhp->ntfid_ino)); + + if ((error = VFS_VGET(mp, ntfhp->ntfid_ino, &nvp)) != 0) { + *vpp = NULLVP; + return (error); + } + /* XXX as unlink/rmdir/mkdir/creat are not currently possible + * with NTFS, we don't need to check anything else for now */ + *vpp = nvp; + + return (0); } static int @@ -819,10 +856,19 @@ ntfs_vptofh( struct vnode *vp, struct fid *fhp) { - printf("ntfs_vptofh():\n"); - return EOPNOTSUPP; + register struct ntnode *ntp; + register struct ntfid *ntfhp; + + ddprintf(("ntfs_fhtovp(): %s: %p\n", vp->v_mount->mnt_stat->f_mntonname, + vp)); + + ntp = VTONT(vp); + ntfhp = (struct ntfid *)fhp; + ntfhp->ntfid_len = sizeof(struct ntfid); + ntfhp->ntfid_ino = ntp->i_number; + /* ntfhp->ntfid_gen = ntp->i_gen; */ + return (0); } -#endif /* !defined(__FreeBSD__) */ int ntfs_vgetex( @@ -840,9 +886,11 @@ ntfs_vgetex( struct ntnode *ip; struct fnode *fp; struct vnode *vp; + enum vtype f_type; - dprintf(("ntfs_vgetex: ino: %d, attr: 0x%x:%s, lkf: 0x%x, f: 0x%x\n", - ino, attrtype, attrname?attrname:"", lkflags, flags )); + dprintf(("ntfs_vgetex: ino: %d, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n", + ino, attrtype, attrname?attrname:"", (u_long)lkflags, + (u_long)flags )); ntmp = VFSTONTFS(mp); *vpp = NULL; @@ -872,16 +920,16 @@ ntfs_vgetex( return (error); } + f_type = VNON; if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) { if ((ip->i_frflag & NTFS_FRFLAG_DIR) && - (fp->f_attrtype == 0x80 && fp->f_attrname == NULL)) { - fp->f_type = VDIR; - } else if(flags & VG_EXT) { - fp->f_type = VNON; - - fp->f_size =fp->f_allocated = 0; + (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) { + f_type = VDIR; + } else if (flags & VG_EXT) { + f_type = VNON; + fp->f_size = fp->f_allocated = 0; } else { - fp->f_type = VREG; + f_type = VREG; error = ntfs_filesize(ntmp, fp, &fp->f_size, &fp->f_allocated); @@ -909,10 +957,12 @@ ntfs_vgetex( } dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino)); +#ifdef __FreeBSD__ lockinit(&fp->f_lock, PINOD, "fnode", 0, 0); +#endif fp->f_vp = vp; vp->v_data = fp; - vp->v_type = fp->f_type; + vp->v_type = f_type; if (ino == NTFS_ROOTINO) vp->v_flag |= VROOT; @@ -927,7 +977,7 @@ ntfs_vgetex( } } - VREF(fp->f_devvp); + VREF(ip->i_devvp); *vpp = vp; return (0); @@ -940,7 +990,7 @@ ntfs_vget( struct vnode **vpp) { return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL, - LK_EXCLUSIVE, 0, curproc, vpp); + LK_EXCLUSIVE | LK_RETRY, 0, curproc, vpp); } #if defined(__FreeBSD__) @@ -953,9 +1003,9 @@ static struct vfsops ntfs_vfsops = { ntfs_statfs, vfs_stdsync, ntfs_vget, - vfs_stdfhtovp, - vfs_stdcheckexp, - vfs_stdvptofh, + ntfs_fhtovp, + ntfs_checkexp, + ntfs_vptofh, ntfs_init, NULL }; @@ -986,7 +1036,7 @@ struct vfsops ntfs_vfsops = { ntfs_checkexp, ntfs_vnodeopv_descs, }; -#else +#else /* !NetBSD && !FreeBSD */ static struct vfsops ntfs_vfsops = { ntfs_mount, ntfs_start, diff --git a/sys/fs/ntfs/ntfs_vfsops.h b/sys/fs/ntfs/ntfs_vfsops.h index d7f5f5d..f124c77 100644 --- a/sys/fs/ntfs/ntfs_vfsops.h +++ b/sys/fs/ntfs/ntfs_vfsops.h @@ -1,4 +1,4 @@ -/* $NetBSD: ntfs_vfsops.h,v 1.2 1999/05/06 15:43:20 christos Exp $ */ +/* $NetBSD: ntfs_vfsops.h,v 1.4 1999/10/10 14:20:33 jdolecek Exp $ */ /*- * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) @@ -28,7 +28,7 @@ * $FreeBSD$ */ #define VG_DONTLOADIN 0x0001 /* Tells ntfs_vgetex to do not call */ - /* ntfs_loadnode on ntnode, even if */ + /* ntfs_loadntnode() on ntnode, even if */ /* ntnode not loaded */ #define VG_DONTVALIDFN 0x0002 /* Tells ntfs_vgetex to do not validate */ /* fnode */ diff --git a/sys/fs/ntfs/ntfs_vnops.c b/sys/fs/ntfs/ntfs_vnops.c index 9d3f6e5..381cb8f 100644 --- a/sys/fs/ntfs/ntfs_vnops.c +++ b/sys/fs/ntfs/ntfs_vnops.c @@ -1,4 +1,4 @@ -/* $NetBSD: ntfs_vnops.c,v 1.2 1999/05/06 15:43:20 christos Exp $ */ +/* $NetBSD: ntfs_vnops.c,v 1.23 1999/10/31 19:45:27 jdolecek Exp $ */ /* * Copyright (c) 1992, 1993 @@ -42,7 +42,6 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> -#include <sys/proc.h> #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> @@ -55,6 +54,9 @@ #include <vm/vm.h> #include <vm/vm_param.h> +#if defined(__NetBSD__) +#include <vm/vm_prot.h> +#endif #include <vm/vm_page.h> #include <vm/vm_object.h> #include <vm/vm_pager.h> @@ -65,12 +67,16 @@ #include <sys/sysctl.h> - /*#define NTFS_DEBUG 1*/ #include <ntfs/ntfs.h> #include <ntfs/ntfs_inode.h> #include <ntfs/ntfs_subr.h> -#include <ntfs/ntfs_extern.h> +#if defined(__NetBSD__) +#include <miscfs/specfs/specdev.h> +#include <miscfs/genfs/genfs.h> +#endif + +#include <sys/unistd.h> /* for pathconf(2) constants */ static int ntfs_bypass __P((struct vop_generic_args *ap)); static int ntfs_read __P((struct vop_read_args *)); @@ -80,11 +86,6 @@ static int ntfs_inactive __P((struct vop_inactive_args *ap)); static int ntfs_print __P((struct vop_print_args *ap)); static int ntfs_reclaim __P((struct vop_reclaim_args *ap)); static int ntfs_strategy __P((struct vop_strategy_args *ap)); -#if defined(__NetBSD__) -static int ntfs_islocked __P((struct vop_islocked_args *ap)); -static int ntfs_unlock __P((struct vop_unlock_args *ap)); -static int ntfs_lock __P((struct vop_lock_args *ap)); -#endif static int ntfs_access __P((struct vop_access_args *ap)); static int ntfs_open __P((struct vop_open_args *ap)); static int ntfs_close __P((struct vop_close_args *ap)); @@ -94,8 +95,9 @@ static int ntfs_bmap __P((struct vop_bmap_args *ap)); #if defined(__FreeBSD__) static int ntfs_getpages __P((struct vop_getpages_args *ap)); static int ntfs_putpages __P((struct vop_putpages_args *)); -#endif static int ntfs_fsync __P((struct vop_fsync_args *ap)); +#endif +static int ntfs_pathconf __P((void *)); int ntfs_prtactive = 1; /* 1 => print out reclaim of active vnodes */ @@ -159,39 +161,31 @@ ntfs_read(ap) 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 toread; int error; 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)); - toread = fp->f_size; - - dprintf(("ntfs_read: filesize: %d",(u_int32_t)toread)); + dprintf(("ntfs_read: filesize: %d",(u_int32_t)fp->f_size)); - toread = min( uio->uio_resid, toread - uio->uio_offset ); + /* don't allow reading after end of file */ + if (uio->uio_offset > fp->f_size) + toread = 0; + else + toread = min( uio->uio_resid, fp->f_size - uio->uio_offset ); dprintf((", toread: %d\n",(u_int32_t)toread)); - MALLOC(data, u_int8_t *, toread, M_TEMP,M_WAITOK); + if (toread == 0) + return (0); error = ntfs_readattr(ntmp, ip, fp->f_attrtype, - fp->f_attrname, uio->uio_offset, toread, data); - if(error) { + fp->f_attrname, uio->uio_offset, toread, NULL, uio); + if (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); } - FREE(data, M_TEMP); - return (0); } @@ -224,12 +218,16 @@ ntfs_getattr(ap) dprintf(("ntfs_getattr: %d, flags: %d\n",ip->i_number,ip->i_flag)); - vap->va_fsid = dev2udev(fp->f_dev); +#if defined(__FreeBSD__) + vap->va_fsid = dev2udev(ip->i_dev); +#else /* NetBSD */ + vap->va_fsid = ip->i_dev; +#endif vap->va_fileid = ip->i_number; - vap->va_mode = ip->i_mode; + vap->va_mode = ip->i_mp->ntm_mode; vap->va_nlink = ip->i_nlink; - vap->va_uid = ip->i_uid; - vap->va_gid = ip->i_gid; + vap->va_uid = ip->i_mp->ntm_uid; + vap->va_gid = ip->i_mp->ntm_gid; vap->va_rdev = 0; /* XXX UNODEV ? */ vap->va_size = fp->f_size; vap->va_bytes = fp->f_allocated; @@ -239,7 +237,7 @@ ntfs_getattr(ap) 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 = fp->f_type; + vap->va_type = vp->v_type; vap->va_filerev = 0; return (0); } @@ -255,33 +253,25 @@ ntfs_inactive(ap) } */ *ap; { register struct vnode *vp = ap->a_vp; +#ifdef NTFS_DEBUG register struct ntnode *ip = VTONT(vp); - int error; +#endif 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); - error = 0; - - VOP__UNLOCK(vp,0,ap->a_p); + VOP__UNLOCK(vp, 0, ap->a_p); - /* - * If we are done with the ntnode, reclaim it - * so that it can be reused immediately. + /* XXX since we don't support any filesystem changes + * right now, nothing more needs to be done */ - if (vp->v_usecount == 0 && ip->i_mode == 0) -#if defined(__FreeBSD__) - vrecycle(vp, (struct simplelock *)0, ap->a_p); -#else /* defined(__NetBSD__) */ - vgone(vp); -#endif - return (error); + return (0); } /* - * Reclaim an inode so that it can be used for other purposes. + * Reclaim an fnode/ntnode so that it can be used for other purposes. */ int ntfs_reclaim(ap) @@ -296,26 +286,22 @@ ntfs_reclaim(ap) dprintf(("ntfs_reclaim: vnode: %p, ntnode: %d\n", vp, ip->i_number)); - error = ntfs_ntget(ip); - if (error) - return (error); - -#if defined(__FreeBSD__) - VOP__UNLOCK(vp,0,ap->a_p); -#endif + if (ntfs_prtactive && vp->v_usecount != 0) + vprint("ntfs_reclaim: pushing active", vp); + if ((error = ntfs_ntget(ip)) != 0) + return (error); + /* Purge old data structures associated with the inode. */ cache_purge(vp); - if (fp->f_devvp) { - vrele(fp->f_devvp); - fp->f_devvp = NULL; + if (ip->i_devvp) { + vrele(ip->i_devvp); + ip->i_devvp = NULL; } ntfs_frele(fp); - - vp->v_data = NULL; - ntfs_ntput(ip); + vp->v_data = NULL; return (0); } @@ -326,8 +312,6 @@ ntfs_print(ap) struct vnode *a_vp; } */ *ap; { -/* printf("[ntfs_print]");*/ - return (0); } @@ -348,10 +332,17 @@ ntfs_strategy(ap) struct ntfsmount *ntmp = ip->i_mp; int error; +#ifdef __FreeBSD__ 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", +#else + dprintf(("ntfs_strategy: blkno: %d, lblkno: %d\n", + (u_int32_t)bp->b_blkno, + (u_int32_t)bp->b_lblkno)); +#endif + + dprintf(("strategy: bcount: %d flags: 0x%lx\n", (u_int32_t)bp->b_bcount,bp->b_flags)); if (bp->b_flags & B_READ) { @@ -368,7 +359,7 @@ ntfs_strategy(ap) error = ntfs_readattr(ntmp, ip, fp->f_attrtype, fp->f_attrname, ntfs_cntob(bp->b_blkno), - toread, bp->b_data); + toread, bp->b_data, NULL); if (error) { printf("ntfs_strategy: ntfs_readattr failed\n"); @@ -394,7 +385,7 @@ ntfs_strategy(ap) error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype, fp->f_attrname, ntfs_cntob(bp->b_blkno),towrite, - bp->b_data, &tmp); + bp->b_data, &tmp, NULL); if (error) { printf("ntfs_strategy: ntfs_writeattr fail\n"); @@ -421,172 +412,31 @@ ntfs_write(ap) 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; 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)); + dprintf(("ntfs_write: filesize: %d",(u_int32_t)fp->f_size)); - towrite = fp->f_size; - - dprintf(("ntfs_write: filesize: %d",(u_int32_t)towrite)); - - if (uio->uio_resid + uio->uio_offset > towrite) { - printf("ntfs_write: CAN'T WRITE BEYOND OF FILE\n"); + if (uio->uio_resid + uio->uio_offset > fp->f_size) { + printf("ntfs_write: CAN'T WRITE BEYOND END OF FILE\n"); return (EFBIG); } - towrite = min(uio->uio_resid, towrite - uio->uio_offset); - off = uio->uio_offset; + towrite = min(uio->uio_resid, fp->f_size - 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 defined(__NetBSD__) -/* - * Check for a locked ntnode. - */ -int -ntfs_islocked(ap) - struct vop_islocked_args /* { - struct vnode *a_vp; - } */ *ap; -{ - register struct ntnode *ip = VTONT(ap->a_vp); - - dprintf(("ntfs_islocked %d\n",ip->i_number)); - - if (ip->i_flag & IN_LOCKED) - return (1); - return (0); -} - -/* - * Unlock an ntnode. If WANT bit is on, wakeup. - */ -int ntfs_lockcount = 90; -int -ntfs_unlock(ap) - struct vop_unlock_args /* { - struct vnode *a_vp; - } */ *ap; -{ - register struct ntnode *ip = VTONT(ap->a_vp); -#ifdef DIAGNOSTIC - struct proc *p = curproc; -#endif - - dprintf(("ntfs_unlock %d\n",ip->i_number)); - -#ifdef DIAGNOSTIC - - if ((ip->i_flag & IN_LOCKED) == 0) { - vprint("ntfs_unlock: unlocked ntnode", ap->a_vp); - panic("ntfs_unlock NOT LOCKED"); - } - if (p && p->p_pid != ip->i_lockholder && p->p_pid > -1 && - ip->i_lockholder > -1 && ntfs_lockcount++ < 100) - panic("unlocker (%d) != lock holder (%d)", - p->p_pid, ip->i_lockholder); -#endif - - if (--ip->i_lockcount > 0) { - if ((ip->i_flag & IN_RECURSE) == 0) - panic("ntfs_unlock: recursive lock prematurely released, pid=%d\n", ip->i_lockholder); - return (0); - } - ip->i_lockholder = 0; - ip->i_flag &= ~(IN_LOCKED|IN_RECURSE); - if (ip->i_flag & IN_WANTED) { - ip->i_flag &= ~IN_WANTED; - wakeup((caddr_t)ip); - } - return (0); -} - -/* - * Lock an ntnode. If its already locked, set the WANT bit and sleep. - */ -int -ntfs_lock(ap) - struct vop_lock_args /* { - struct vnode *a_vp; - } */ *ap; -{ - struct proc *p = curproc; - register struct vnode *vp = ap->a_vp; - register struct ntnode *ip = VTONT(vp); - - dprintf(("ntfs_lock %d (%d locks)\n",ip->i_number,ip->i_lockcount)); - -start: - while (vp->v_flag & VXLOCK) { - vp->v_flag |= VXWANT; - (void) tsleep((caddr_t)vp, PINOD, "ntflk1", 0); - } - if (vp->v_tag == VT_NON) - return (ENOENT); - ip = VTONT(vp); - if (ip->i_flag & IN_LOCKED) { - if (p->p_pid == ip->i_lockholder) { - if( (ip->i_flag & IN_RECURSE) == 0) - panic("ntfs_lock: recursive lock not expected, pid: %d\n", - ip->i_lockholder); - } else { - ip->i_flag |= IN_WANTED; -#ifdef DIAGNOSTIC - if (p) - ip->i_lockwaiter = p->p_pid; - else - ip->i_lockwaiter = -1; -#endif - (void) tsleep((caddr_t)ip, PINOD, "ntflk2", 0); - goto start; - } - } -#ifdef DIAGNOSTIC - ip->i_lockwaiter = 0; - if (((ip->i_flag & IN_RECURSE) == 0) && (ip->i_lockholder != 0)) - panic("lockholder (%d) != 0", ip->i_lockholder); - if (p && p->p_pid == 0) - printf("locking by process 0\n"); + fp->f_attrname, uio->uio_offset, towrite, NULL, &written, uio); +#ifdef NTFS_DEBUG + if (error) + printf("ntfs_write: ntfs_writeattr failed: %d\n", error); #endif - if ((ip->i_flag & IN_RECURSE) == 0) - ip->i_lockcount = 1; - else - ++ip->i_lockcount; - - if (p) - ip->i_lockholder = p->p_pid; - else - ip->i_lockholder = -1; - ip->i_flag |= IN_LOCKED; - return (0); + return (error); } -#endif int ntfs_access(ap) @@ -629,12 +479,6 @@ ntfs_access(ap) } } - /* If immutable bit set, nobody gets to write it. */ -/* - if ((mode & VWRITE) && (ip->i_flags & IMMUTABLE)) - return (EPERM); -*/ - /* Otherwise, user id 0 always gets access. */ if (cred->cr_uid == 0) return (0); @@ -642,26 +486,26 @@ ntfs_access(ap) mask = 0; /* Otherwise, check the owner. */ - if (cred->cr_uid == ip->i_uid) { + if (cred->cr_uid == ip->i_mp->ntm_uid) { if (mode & VEXEC) mask |= S_IXUSR; if (mode & VREAD) mask |= S_IRUSR; if (mode & VWRITE) mask |= S_IWUSR; - return ((ip->i_mode & mask) == mask ? 0 : EACCES); + return ((ip->i_mp->ntm_mode & mask) == mask ? 0 : EACCES); } /* Otherwise, check the groups. */ for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) - if (ip->i_gid == *gp) { + if (ip->i_mp->ntm_gid == *gp) { if (mode & VEXEC) mask |= S_IXGRP; if (mode & VREAD) mask |= S_IRGRP; if (mode & VWRITE) mask |= S_IWGRP; - return ((ip->i_mode & mask) == mask ? 0 : EACCES); + return ((ip->i_mp->ntm_mode&mask) == mask ? 0 : EACCES); } /* Otherwise, check everyone else. */ @@ -671,7 +515,7 @@ ntfs_access(ap) mask |= S_IROTH; if (mode & VWRITE) mask |= S_IWOTH; - return ((ip->i_mode & mask) == mask ? 0 : EACCES); + return ((ip->i_mp->ntm_mode & mask) == mask ? 0 : EACCES); } /* @@ -794,31 +638,31 @@ ntfs_readdir(ap) if( NULL == iep ) break; - while( !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent)) ) { - - if( ntfs_isnamepermitted(ntmp,iep) ) { - dprintf(("ntfs_readdir: elem: %d, fname:[",num)); - for(i=0;i<iep->ie_fnamelen;i++) { - cde.d_name[i] = (char)iep->ie_fname[i]; - dprintf(("%c", cde.d_name[i])); - } - dprintf(("] type: %d, flag: %d, ",iep->ie_fnametype, iep->ie_flag)); - cde.d_name[i] = '\0'; - cde.d_namlen = iep->ie_fnamelen; - cde.d_fileno = iep->ie_number; - cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG; - cde.d_reclen = sizeof(struct dirent); - dprintf(("%s\n", (cde.d_type == DT_DIR) ? "dir":"reg")); - - error = uiomove((char *)&cde, sizeof(struct dirent), uio); - if(error) - return (error); - - ncookies++; - num++; + for(; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent)); + iep = NTFS_NEXTREC(iep, struct attr_indexentry *)) + { + if(!ntfs_isnamepermitted(ntmp,iep)) + continue; + + for(i=0; i<iep->ie_fnamelen; i++) { + cde.d_name[i] = ntfs_u28(iep->ie_fname[i]); } + cde.d_name[i] = '\0'; + dprintf(("ntfs_readdir: elem: %d, fname:[%s] type: %d, flag: %d, ", + num, cde.d_name, iep->ie_fnametype, + iep->ie_flag)); + cde.d_namlen = iep->ie_fnamelen; + cde.d_fileno = iep->ie_number; + cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG; + cde.d_reclen = sizeof(struct dirent); + dprintf(("%s\n", (cde.d_type == DT_DIR) ? "dir":"reg")); + + error = uiomove((char *)&cde, sizeof(struct dirent), uio); + if(error) + return (error); - iep = NTFS_NEXTREC(iep,struct attr_indexentry *); + ncookies++; + num++; } } @@ -838,7 +682,7 @@ ntfs_readdir(ap) off_t *cookiep; #endif - printf("ntfs_readdir: %d cookies\n",ncookies); + ddprintf(("ntfs_readdir: %d cookies\n",ncookies)); if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) panic("ntfs_readdir: unexpected uio from NFS server"); dpStart = (struct dirent *) @@ -885,25 +729,40 @@ ntfs_lookup(ap) #if NTFS_DEBUG int wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT); #endif - dprintf(("ntfs_lookup: %s (%ld bytes) in %d, lp: %d, wp: %d \n", - cnp->cn_nameptr, cnp->cn_namelen, - dip->i_number,lockparent, wantparent)); + dprintf(("ntfs_lookup: \"%.*s\" (%ld bytes) in %d, lp: %d, wp: %d \n", + (int)cnp->cn_namelen, cnp->cn_nameptr, cnp->cn_namelen, + dip->i_number, lockparent, wantparent)); error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_proc); if(error) return (error); - if( (cnp->cn_namelen == 1) && - !strncmp(cnp->cn_nameptr,".",1) ) { + if ((cnp->cn_flags & ISLASTCN) && + (dvp->v_mount->mnt_flag & MNT_RDONLY) && + (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) + return (EROFS); + +#ifdef __NetBSD__ + /* + * We now have a segment name to search for, and a directory + * to search. + * + * Before tediously performing a linear scan of the directory, + * check the name cache to see if the directory/name pair + * we are looking for is known already. + */ + if ((error = cache_lookup(ap->a_dvp, ap->a_vpp, cnp)) >= 0) + return (error); +#endif + + if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { dprintf(("ntfs_lookup: faking . directory in %d\n", dip->i_number)); VREF(dvp); *ap->a_vpp = dvp; - return (0); - } else if( (cnp->cn_namelen == 2) && - !strncmp(cnp->cn_nameptr,"..",2) && - (cnp->cn_flags & ISDOTDOT) ) { + error = 0; + } else if (cnp->cn_flags & ISDOTDOT) { struct ntvattr *vap; dprintf(("ntfs_lookup: faking .. directory in %d\n", @@ -914,40 +773,48 @@ ntfs_lookup(ap) return (error); VOP__UNLOCK(dvp,0,cnp->cn_proc); + cnp->cn_flags |= PDIRUNLOCK; dprintf(("ntfs_lookup: parentdir: %d\n", vap->va_a_name->n_pnumber)); error = VFS_VGET(ntmp->ntm_mountp, vap->va_a_name->n_pnumber,ap->a_vpp); ntfs_ntvattrrele(vap); - if(error) { - VOP__LOCK(dvp, 0, cnp->cn_proc); - return(error); + if (error) { + if (VN_LOCK(dvp,LK_EXCLUSIVE|LK_RETRY,cnp->cn_proc)==0) + cnp->cn_flags &= ~PDIRUNLOCK; + return (error); } - if( lockparent && (cnp->cn_flags & ISLASTCN) && - (error = VOP__LOCK(dvp, 0, cnp->cn_proc)) ) { - vput( *(ap->a_vpp) ); - return (error); + if (lockparent && (cnp->cn_flags & ISLASTCN)) { + error = VN_LOCK(dvp, LK_EXCLUSIVE, cnp->cn_proc); + if (error) { + vput( *(ap->a_vpp) ); + return (error); + } + cnp->cn_flags &= ~PDIRUNLOCK; } - return (error); } else { error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp); - if(error) + if (error) { + dprintf(("ntfs_ntlookupfile: returned %d\n", error)); return (error); + } dprintf(("ntfs_lookup: found ino: %d\n", VTONT(*ap->a_vpp)->i_number)); if(!lockparent || !(cnp->cn_flags & ISLASTCN)) VOP__UNLOCK(dvp, 0, cnp->cn_proc); - if (cnp->cn_flags & MAKEENTRY) - cache_enter(dvp, *ap->a_vpp, cnp); - } + + if (cnp->cn_flags & MAKEENTRY) + cache_enter(dvp, *ap->a_vpp, cnp); + return (error); } +#if defined(__FreeBSD__) /* * Flush the blocks of a file to disk. * @@ -965,6 +832,50 @@ ntfs_fsync(ap) { return (0); } +#endif + +/* + * Return POSIX pathconf information applicable to NTFS filesystem + */ +int +ntfs_pathconf(v) + void *v; +{ + struct vop_pathconf_args /* { + struct vnode *a_vp; + int a_name; + register_t *a_retval; + } */ *ap = v; + + switch (ap->a_name) { + case _PC_LINK_MAX: + *ap->a_retval = 1; + return (0); + case _PC_NAME_MAX: + *ap->a_retval = NTFS_MAXFILENAME; + return (0); + case _PC_PATH_MAX: + *ap->a_retval = PATH_MAX; + return (0); + case _PC_CHOWN_RESTRICTED: + *ap->a_retval = 1; + return (0); + case _PC_NO_TRUNC: + *ap->a_retval = 0; + return (0); +#if defined(__NetBSD__) + case _PC_SYNC_IO: + *ap->a_retval = 1; + return (0); + case _PC_FILESIZEBITS: + *ap->a_retval = 64; + return (0); +#endif + default: + return (EINVAL); + } + /* NOTREACHED */ +} /* * Global vfs data structures @@ -972,7 +883,6 @@ ntfs_fsync(ap) vop_t **ntfs_vnodeop_p; #if defined(__FreeBSD__) static -#endif struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = { { &vop_default_desc, (vop_t *)ntfs_bypass }, @@ -980,19 +890,13 @@ struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = { { &vop_inactive_desc, (vop_t *)ntfs_inactive }, { &vop_reclaim_desc, (vop_t *)ntfs_reclaim }, { &vop_print_desc, (vop_t *)ntfs_print }, + { &vop_pathconf_desc, ntfs_pathconf }, -#if defined(__FreeBSD__) { &vop_islocked_desc, (vop_t *)vop_stdislocked }, { &vop_unlock_desc, (vop_t *)vop_stdunlock }, { &vop_lock_desc, (vop_t *)vop_stdlock }, { &vop_cachedlookup_desc, (vop_t *)ntfs_lookup }, { &vop_lookup_desc, (vop_t *)vfs_cache_lookup }, -#else - { &vop_islocked_desc, (vop_t *)ntfs_islocked }, - { &vop_unlock_desc, (vop_t *)ntfs_unlock }, - { &vop_lock_desc, (vop_t *)ntfs_lock }, - { &vop_lookup_desc, (vop_t *)ntfs_lookup }, -#endif { &vop_access_desc, (vop_t *)ntfs_access }, { &vop_close_desc, (vop_t *)ntfs_close }, @@ -1001,28 +905,73 @@ struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = { { &vop_fsync_desc, (vop_t *)ntfs_fsync }, { &vop_bmap_desc, (vop_t *)ntfs_bmap }, -#if defined(__FreeBSD__) { &vop_getpages_desc, (vop_t *) ntfs_getpages }, { &vop_putpages_desc, (vop_t *) ntfs_putpages }, -#endif { &vop_strategy_desc, (vop_t *)ntfs_strategy }, -#if defined(__FreeBSD__) { &vop_bwrite_desc, (vop_t *)vop_stdbwrite }, -#else /* defined(__NetBSD__) */ - { &vop_bwrite_desc, (vop_t *)vn_bwrite }, -#endif { &vop_read_desc, (vop_t *)ntfs_read }, { &vop_write_desc, (vop_t *)ntfs_write }, { NULL, NULL } }; -#if defined(__FreeBSD__) static -#endif struct vnodeopv_desc ntfs_vnodeop_opv_desc = { &ntfs_vnodeop_p, ntfs_vnodeop_entries }; -#if defined(__FreeBSD__) VNODEOP_SET(ntfs_vnodeop_opv_desc); + +#else /* !FreeBSD */ + +struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = { + { &vop_default_desc, (vop_t *) ntfs_bypass }, + { &vop_lookup_desc, (vop_t *) ntfs_lookup }, /* lookup */ + { &vop_create_desc, genfs_eopnotsupp }, /* create */ + { &vop_mknod_desc, genfs_eopnotsupp }, /* mknod */ + { &vop_open_desc, (vop_t *) ntfs_open }, /* open */ + { &vop_close_desc,(vop_t *) ntfs_close }, /* close */ + { &vop_access_desc, (vop_t *) ntfs_access }, /* access */ + { &vop_getattr_desc, (vop_t *) ntfs_getattr }, /* getattr */ + { &vop_setattr_desc, genfs_eopnotsupp }, /* setattr */ + { &vop_read_desc, (vop_t *) ntfs_read }, /* read */ + { &vop_write_desc, (vop_t *) ntfs_write }, /* write */ + { &vop_lease_desc, genfs_lease_check }, /* lease */ + { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */ + { &vop_ioctl_desc, genfs_enoioctl }, /* ioctl */ + { &vop_poll_desc, genfs_poll }, /* poll */ + { &vop_revoke_desc, genfs_revoke }, /* revoke */ + { &vop_mmap_desc, genfs_eopnotsupp }, /* mmap */ + { &vop_fsync_desc, genfs_fsync }, /* fsync */ + { &vop_seek_desc, genfs_seek }, /* seek */ + { &vop_remove_desc, genfs_eopnotsupp }, /* remove */ + { &vop_link_desc, genfs_eopnotsupp }, /* link */ + { &vop_rename_desc, genfs_eopnotsupp }, /* rename */ + { &vop_mkdir_desc, genfs_eopnotsupp }, /* mkdir */ + { &vop_rmdir_desc, genfs_eopnotsupp }, /* rmdir */ + { &vop_symlink_desc, genfs_eopnotsupp }, /* symlink */ + { &vop_readdir_desc, (vop_t *) ntfs_readdir }, /* readdir */ + { &vop_readlink_desc, genfs_eopnotsupp }, /* readlink */ + { &vop_abortop_desc, genfs_abortop }, /* abortop */ + { &vop_inactive_desc, (vop_t *) ntfs_inactive }, /* inactive */ + { &vop_reclaim_desc, (vop_t *) ntfs_reclaim }, /* reclaim */ + { &vop_lock_desc, genfs_lock }, /* lock */ + { &vop_unlock_desc, genfs_unlock }, /* unlock */ + { &vop_bmap_desc, (vop_t *) ntfs_bmap }, /* bmap */ + { &vop_strategy_desc, (vop_t *) ntfs_strategy }, /* strategy */ + { &vop_print_desc, (vop_t *) ntfs_print }, /* print */ + { &vop_islocked_desc, genfs_islocked }, /* islocked */ + { &vop_pathconf_desc, ntfs_pathconf }, /* pathconf */ + { &vop_advlock_desc, genfs_nullop }, /* advlock */ + { &vop_blkatoff_desc, genfs_eopnotsupp }, /* blkatoff */ + { &vop_valloc_desc, genfs_eopnotsupp }, /* valloc */ + { &vop_reallocblks_desc, genfs_eopnotsupp }, /* reallocblks */ + { &vop_vfree_desc, genfs_eopnotsupp }, /* vfree */ + { &vop_truncate_desc, genfs_eopnotsupp }, /* truncate */ + { &vop_update_desc, genfs_eopnotsupp }, /* update */ + { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ + { (struct vnodeop_desc *)NULL, (int (*) __P((void *)))NULL } +}; +struct vnodeopv_desc ntfs_vnodeop_opv_desc = + { &ntfs_vnodeop_p, ntfs_vnodeop_entries }; + #endif diff --git a/sys/fs/ntfs/ntfsmount.h b/sys/fs/ntfs/ntfsmount.h index 0a1f791..f3a6d25 100644 --- a/sys/fs/ntfs/ntfsmount.h +++ b/sys/fs/ntfs/ntfsmount.h @@ -1,4 +1,4 @@ -/* $NetBSD: ntfsmount.h,v 1.2 1999/05/06 15:43:21 christos Exp $ */ +/* $NetBSD: ntfsmount.h,v 1.3 1999/07/26 14:02:32 jdolecek Exp $ */ /*- * Copyright (c) 1998, 1999 Semen Ustimenko |