From 42e01703dca788bba764956ba12647f3dcdd7ec9 Mon Sep 17 00:00:00 2001 From: semenu Date: Tue, 20 Apr 1999 21:06:44 +0000 Subject: [PATCH] Removed annoying messaged during boot,added some check before mounting (should help to do not mount extended partitions:-). Fixed problem with hanging while unmounting busy fs. And (the most important) added some locks to prevent simulaneous access to kernel structures! --- sys/fs/ntfs/ntfs.h | 5 +- sys/fs/ntfs/ntfs_inode.h | 11 +- sys/fs/ntfs/ntfs_subr.c | 322 ++++++++++++++++++++++++++++++-------- sys/fs/ntfs/ntfs_subr.h | 16 +- sys/fs/ntfs/ntfs_vfsops.c | 243 ++++++++++++++++------------ sys/fs/ntfs/ntfs_vfsops.h | 6 +- sys/fs/ntfs/ntfs_vnops.c | 30 ++-- sys/ntfs/ntfs.h | 5 +- sys/ntfs/ntfs_inode.h | 11 +- sys/ntfs/ntfs_subr.c | 322 ++++++++++++++++++++++++++++++-------- sys/ntfs/ntfs_subr.h | 16 +- sys/ntfs/ntfs_vfsops.c | 243 ++++++++++++++++------------ sys/ntfs/ntfs_vfsops.h | 6 +- sys/ntfs/ntfs_vnops.c | 30 ++-- 14 files changed, 890 insertions(+), 376 deletions(-) diff --git a/sys/fs/ntfs/ntfs.h b/sys/fs/ntfs/ntfs.h index e2bda5e7f779..e9fa1b3fcdc8 100644 --- a/sys/fs/ntfs/ntfs.h +++ b/sys/fs/ntfs/ntfs.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ntfs.h,v 1.2 1999/02/19 12:31:02 semenu Exp $ + * $Id: ntfs.h,v 1.9 1999/02/02 01:54:54 semen Exp $ */ /*#define NTFS_DEBUG 1*/ @@ -213,6 +213,8 @@ struct ntvattrdef { u_int32_t ad_type; }; +#define NTFS_BBID "NTFS " +#define NTFS_BBIDLEN 8 struct bootfile { u_int8_t reserved1[3]; /* asm jmp near ... */ u_int8_t bf_sysid[8]; /* 'NTFS ' */ @@ -246,6 +248,7 @@ struct ntfsmount { gid_t ntm_gid; mode_t ntm_mode; u_long ntm_flag; + cn_t ntm_cfree; struct ntvattrdef *ntm_ad; int ntm_adnum; }; diff --git a/sys/fs/ntfs/ntfs_inode.h b/sys/fs/ntfs/ntfs_inode.h index 2e6fb788fa96..bf1e26c73808 100644 --- a/sys/fs/ntfs/ntfs_inode.h +++ b/sys/fs/ntfs/ntfs_inode.h @@ -55,17 +55,18 @@ #define IN_PRELOADED 0x4000 /* loaded from directory entry */ struct ntnode { - LIST_ENTRY(ntnode) i_hash; + LIST_ENTRY(ntnode) i_hash; struct ntnode *i_next; struct ntnode **i_prev; - struct ntfsmount *i_mp; + struct ntfsmount *i_mp; ino_t i_number; dev_t i_dev; u_int32_t i_flag; + int i_lock; int i_usecount; - LIST_HEAD(,fnode) i_fnlist; - struct ntvattr *i_vattrp; /* ntvattrs list */ + LIST_HEAD(,fnode) i_fnlist; + LIST_HEAD(,ntvattr) i_valist; long i_nlink; /* MFR */ ino_t i_mainrec; /* MFR */ @@ -77,7 +78,7 @@ struct ntnode { }; #define FN_PRELOADED 0x0001 -#define FN_DEFAULT 0x0002 +#define FN_VALID 0x0002 #define FN_AATTRNAME 0x0004 /* space allocated for f_attrname */ struct fnode { struct lock f_lock; /* Must be first */ diff --git a/sys/fs/ntfs/ntfs_subr.c b/sys/fs/ntfs/ntfs_subr.c index 901ea6940310..cecc00af4e24 100644 --- a/sys/fs/ntfs/ntfs_subr.c +++ b/sys/fs/ntfs/ntfs_subr.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998, 1999 Semen Ustimenko + * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,6 +58,9 @@ MALLOC_DEFINE(M_NTFSRUN, "NTFS vrun", "NTFS vrun storage"); MALLOC_DEFINE(M_NTFSDECOMP, "NTFS decomp", "NTFS decompression temporary"); #endif +/* + * + */ int ntfs_ntvattrrele( struct ntvattr * vap) @@ -70,6 +73,13 @@ ntfs_ntvattrrele( return (0); } +/* + * 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). + * + * ntnode should be locked + */ int ntfs_ntvattrget( struct ntfsmount * ntmp, @@ -113,7 +123,7 @@ ntfs_ntvattrget( } } - for (vap = ip->i_vattrp; vap; vap = vap->va_nextp) { + 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)); @@ -171,14 +181,20 @@ ntfs_ntvattrget( dprintf(("ntfs_ntvattrget: attrbute 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)); @@ -190,7 +206,7 @@ ntfs_ntvattrget( goto out; } } - for (vap = newip->i_vattrp; vap; vap = vap->va_nextp) { + 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) && @@ -219,10 +235,14 @@ ntfs_ntvattrget( ip->i_number, type, name, (u_int32_t) vcn)); out: FREE(alpool, M_TEMP); - return (error); } +/* + * Read ntnode from disk, make ntvattr list. + * + * ntnode should be locked + */ int ntfs_loadntnode( struct ntfsmount * ntmp, @@ -232,7 +252,7 @@ ntfs_loadntnode( daddr_t bn; int error,off; struct attr *ap; - struct ntvattr**vapp; + struct ntvattr *nvap; dprintf(("ntfs_loadnode: loading ino: %d\n",ip->i_number)); @@ -269,6 +289,7 @@ ntfs_loadntnode( goto out; } } + /* Check if magic and fixups are correct */ error = ntfs_procfixups(ntmp, NTFS_FILEMAGIC, (caddr_t)mfrp, ntfs_bntob(ntmp->ntm_bpmftrec)); @@ -281,16 +302,16 @@ ntfs_loadntnode( 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"); + + LIST_INIT(&ip->i_valist); - vapp = &ip->i_vattrp; while (ap->a_hdr.a_type != -1) { - error = ntfs_attrtontvattr(ntmp, vapp, ap); + error = ntfs_attrtontvattr(ntmp, &nvap, ap); if (error) break; - (*vapp)->va_ip = ip; - vapp = &((*vapp)->va_nextp); + nvap->va_ip = ip; + + LIST_INSERT_HEAD(&ip->i_valist, nvap, va_list); off += ap->a_hdr.reclen; ap = (struct attr *) ((caddr_t)mfrp + off); @@ -312,44 +333,74 @@ out: return (error); } - -static int ntfs_ntnode_hash_lock; +/* + * Routine locks ntnode and increase usecount, just opposite of + * ntfs_ntput. + */ int ntfs_ntget( + struct ntnode *ip) +{ + dprintf(("ntfs_ntget: get ntnode %d: %p, usecount: %d\n", + ip->i_number, ip, ip->i_usecount)); + + 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; + + return 0; +} + +/* + * Routine search ntnode in hash, if found: lock, inc usecount and return. + * If not in hash allocate structure for ntnode, prefill it, lock, + * inc count and return. + * + * ntnode returned locked + */ +static int ntfs_ntnode_hash_lock; +int +ntfs_ntlookup( struct ntfsmount * ntmp, ino_t ino, struct ntnode ** ipp) { struct ntnode *ip; - dprintf(("ntfs_ntget: ntget ntnode %d\n", ino)); + dprintf(("ntfs_ntlookup: for ntnode %d\n", ino)); *ipp = NULL; restart: - ip = ntfs_nthashlookup(ntmp->ntm_dev, ino); + ip = ntfs_nthashlookup(ntmp->ntm_dev, ino); /* XXX */ if (ip) { - ip->i_usecount++; + ntfs_ntget(ip); *ipp = ip; - dprintf(("ntfs_ntget: ntnode %d: %p, usecount: %d\n", + dprintf(("ntfs_ntlookup: 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_NTFSNTNODE, M_WAITOK); - ddprintf(("ntfs_ntget: allocating ntnode: %d: %p\n", ino, ip)); + ddprintf(("ntfs_ntlookup: allocating ntnode: %d: %p\n", ino, ip)); bzero((caddr_t) ip, sizeof(struct ntnode)); /* Generic initialization */ @@ -361,6 +412,8 @@ restart: ip->i_mode = ntmp->ntm_mode; ip->i_usecount++; + ip->i_lock = 1; + LIST_INIT(&ip->i_fnlist); ntfs_nthashins(ip); @@ -371,45 +424,77 @@ restart: *ipp = ip; - dprintf(("ntfs_ntget: ntnode %d: %p, usecount: %d\n", + dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n", ino, ip, ip->i_usecount)); return (0); } +/* + * Decrement usecount of ntnode and unlock it, if usecount reach zero, + * deallocate ntnode. + * + * ntnode should be locked on entry, and unlocked on return. + */ void -ntfs_ntrele( - struct ntnode * ip) +ntfs_ntput( + struct ntnode *ip) { struct ntvattr *vap; - dprintf(("ntfs_ntrele: rele ntnode %d: %p, usecount: %d\n", + 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)); ip->i_usecount--; if (ip->i_usecount < 0) { - panic("ntfs_ntrele: ino: %d usecount: %d \n", + panic("ntfs_ntput: ino: %d usecount: %d \n", ip->i_number,ip->i_usecount); } else if (ip->i_usecount == 0) { - dprintf(("ntfs_ntrele: deallocating ntnode: %d\n", + dprintf(("ntfs_ntput: deallocating ntnode: %d\n", ip->i_number)); if (ip->i_fnlist.lh_first) - panic("ntfs_ntrele: ntnode has fnodes\n"); + panic("ntfs_ntput: ntnode has fnodes\n"); ntfs_nthashrem(ip); - while (ip->i_vattrp) { - vap = ip->i_vattrp; - ip->i_vattrp = vap->va_nextp; + while (ip->i_valist.lh_first != NULL) { + vap = ip->i_valist.lh_first; + LIST_REMOVE(vap,va_list); ntfs_freentvattr(vap); } FREE(ip, M_NTFSNTNODE); + } else { + if (ip->i_lock < 0) + wakeup(&ip->i_lock); + ip->i_lock = 0; } - dprintf(("ntfs_ntrele: rele ok\n")); } +/* + * Decrement usecount of ntnode. + */ +void +ntfs_ntrele( + struct ntnode * ip) +{ + 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); +} + +/* + * Deallocate all memory allocated for ntvattr by call to + * ntfs_attrtontvattr and some other functions. + */ void ntfs_freentvattr( struct ntvattr * vap) @@ -426,6 +511,10 @@ ntfs_freentvattr( FREE(vap, M_NTFSNTVATTR); } +/* + * Convert disk image of attribute into ntvattr structure, + * runs are expanded also. + */ int ntfs_attrtontvattr( struct ntfsmount * ntmp, @@ -493,6 +582,9 @@ ntfs_attrtontvattr( return (error); } +/* + * Expand run into more utilizable and more memory eating format. + */ int ntfs_runtovrun( cn_t ** rcnp, @@ -552,7 +644,9 @@ ntfs_runtovrun( return (0); } - +/* + * Convert wchar to uppercase wchar, should be macros? + */ wchar ntfs_toupper( struct ntfsmount * ntmp, @@ -561,6 +655,9 @@ ntfs_toupper( return (ntmp->ntm_upcase[wc & 0xFF]); } +/* + * Compare to unicode strings case insensible. + */ int ntfs_uustricmp( struct ntfsmount * ntmp, @@ -581,6 +678,9 @@ ntfs_uustricmp( return (str1len - str2len); } +/* + * Compare unicode and ascii string case insens. + */ int ntfs_uastricmp( struct ntfsmount * ntmp, @@ -601,6 +701,9 @@ ntfs_uastricmp( return (str1len - str2len); } +/* + * Compare unicode and ascii string case sens. + */ int ntfs_uastrcmp( struct ntfsmount * ntmp, @@ -620,6 +723,11 @@ ntfs_uastrcmp( return (str1len - str2len); } +/* + * Search fnode in ntnode, if not found allocate and preinitialize. + * + * ntnode should be locked on entry. + */ int ntfs_fget( struct ntfsmount *ntmp, @@ -628,7 +736,6 @@ ntfs_fget( char *attrname, struct fnode **fpp) { - int error; struct fnode *fp; dprintf(("ntfs_fget: ino: %d, attrtype: 0x%x, attrname: %s\n", @@ -662,15 +769,6 @@ ntfs_fget( 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); @@ -681,6 +779,11 @@ ntfs_fget( return (0); } +/* + * Deallocate fnode, remove it from ntnode's fnode list. + * + * ntnode should be locked. + */ void ntfs_frele( struct fnode *fp) @@ -699,6 +802,11 @@ ntfs_frele( ntfs_ntrele(ip); } +/* + * Lookup attribute name in format: [[:$ATTR_TYPE]:$ATTR_NAME], + * $ATTR_TYPE is searched in attrdefs read from $AttrDefs. + * If $ATTR_TYPE nott specifed, ATTR_A_DATA assumed. + */ int ntfs_ntlookupattr( struct ntfsmount * ntmp, @@ -753,12 +861,13 @@ ntfs_ntlookupattr( return (0); } + /* * Lookup specifed node for filename, matching cnp, * return fnode filled. */ int -ntfs_ntlookup( +ntfs_ntlookupfile( struct ntfsmount * ntmp, struct vnode * vp, struct componentname * cnp, @@ -776,6 +885,10 @@ ntfs_ntlookup( char *fname,*aname; u_int32_t aoff; + error = ntfs_ntget(ip); + if (error) + return (error); + error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap); if (error || (vap->va_flag & NTFS_AF_INRUN)) return (ENOTDIR); @@ -783,6 +896,10 @@ ntfs_ntlookup( blsize = vap->va_a_iroot->ir_size; rdsize = vap->va_datalen; + /* + * Divide file name into: foofilefoofilefoofile[:attrspec] + * Store like this: fname:fnamelen [aname:anamelen] + */ fname = cnp->cn_nameptr; aname = NULL; anamelen = 0; @@ -790,12 +907,12 @@ ntfs_ntlookup( if(fname[fnamelen] == ':') { aname = fname + fnamelen + 1; anamelen = cnp->cn_namelen - fnamelen - 1; - dprintf(("ntfs_ntlookup: file %s (%d), attr: %s (%d)\n", + dprintf(("ntfs_ntlookupfile: %s (%d), attr: %s (%d)\n", fname, fnamelen, aname, anamelen)); break; } - dprintf(("ntfs_ntlookup: blocksize: %d, rdsize: %d\n", blsize, rdsize)); + dprintf(("ntfs_ntlookupfile: blksz: %d, rdsz: %d\n", blsize, rdsize)); MALLOC(rdbuf, caddr_t, blsize, M_TEMP, M_WAITOK); @@ -856,7 +973,8 @@ ntfs_ntlookup( attrtype, attrname, LK_EXCLUSIVE, - VG_DONTLOAD, + VG_DONTLOADIN | + VG_DONTVALIDFN, curproc, &nvp); if(error) @@ -864,6 +982,11 @@ ntfs_ntlookup( 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; @@ -883,7 +1006,17 @@ ntfs_ntlookup( 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; + } } + + nfp->f_flag &= ~FN_VALID; *vpp = nvp; goto fail; } @@ -896,7 +1029,7 @@ ntfs_ntlookup( /* Dive if possible */ if (iep->ie_flag & NTFS_IEFLAG_SUBNODE) { - dprintf(("ntfs_ntlookup: diving\n")); + dprintf(("ntfs_ntlookupfile: diving\n")); cn = *(cn_t *) (rdbuf + aoff + iep->reclen - sizeof(cn_t)); @@ -915,7 +1048,7 @@ ntfs_ntlookup( aoff = (((struct attr_indexalloc *) rdbuf)->ia_hdrsize + 0x18); } else { - dprintf(("ntfs_ntlookup: nowhere to dive :-(\n")); + dprintf(("ntfs_ntlookupfile: nowhere to dive :-(\n")); error = ENOENT; break; } @@ -925,10 +1058,14 @@ ntfs_ntlookup( fail: ntfs_ntvattrrele(vap); + ntfs_ntput(ip); FREE(rdbuf, M_TEMP); return (error); } +/* + * Check if name type is permitted to show. + */ int ntfs_isnamepermitted( struct ntfsmount * ntmp, @@ -942,9 +1079,7 @@ ntfs_isnamepermitted( case 2: ddprintf(("ntfs_isnamepermitted: skiped DOS name\n")); return 0; - case 0: - case 1: - case 3: + case 0: case 1: case 3: return 1; default: printf("ntfs_isnamepermitted: " \ @@ -955,6 +1090,14 @@ ntfs_isnamepermitted( return 0; } +/* + * Read ntfs dir like stream of attr_indexentry, not like btree of them. + * This is done by scaning $BITMAP:$I30 for busy clusters and reading them. + * Ofcouse $INDEX_ROOT:$I30 is read before. Last read values are stored in + * fnode, so we can skip toward record number num almost immediatly. + * Anyway this is rather slow routine. The problem is that we don't know + * how many records are there in $INDEX_ALLOCATION:$I30 block. + */ int ntfs_ntreaddir( struct ntfsmount * ntmp, @@ -978,6 +1121,10 @@ ntfs_ntreaddir( u_int32_t aoff, cnum; dprintf(("ntfs_ntreaddir: read ino: %d, num: %d\n", ip->i_number, num)); + error = ntfs_ntget(ip); + if (error) + return (error); + error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap); if (error) return (ENOTDIR); @@ -1106,12 +1253,14 @@ fail: ntfs_ntvattrrele(iavap); if (bmp) FREE(bmp, M_TEMP); + ntfs_ntput(ip); return (error); } -/* - * #undef dprintf #define dprintf(a) - */ +/* + * Convert NTFS times that are in 100 ns units and begins from + * 1601 Jan 1 into unix times. + */ struct timespec ntfs_nttimetounix( u_int64_t nt) @@ -1126,6 +1275,9 @@ ntfs_nttimetounix( return (t); } +/* + * Get file times from NTFS_A_NAME attribute. + */ int ntfs_times( struct ntfsmount * ntmp, @@ -1136,15 +1288,28 @@ ntfs_times( int error; dprintf(("ntfs_times: ino: %d...\n", ip->i_number)); - error = ntfs_ntvattrget(ntmp, ip, NTFS_A_NAME, NULL, 0, &vap); + + error = ntfs_ntget(ip); if (error) return (error); + + error = ntfs_ntvattrget(ntmp, ip, NTFS_A_NAME, NULL, 0, &vap); + if (error) { + ntfs_ntput(ip); + return (error); + } *tm = vap->va_a_name->n_times; ntfs_ntvattrrele(vap); + ntfs_ntput(ip); return (0); } +/* + * Get file sizes from corresponding attribute. + * + * ntnode under fnode should be locked. + */ int ntfs_filesize( struct ntfsmount * ntmp, @@ -1158,15 +1323,12 @@ ntfs_filesize( int error; dprintf(("ntfs_filesize: ino: %d\n", ip->i_number)); - 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); - } + + error = ntfs_ntvattrget(ntmp, ip, + fp->f_attrtype, fp->f_attrname, 0, &vap); if (error) return (error); + bn = vap->va_allocated; sz = vap->va_datalen; @@ -1183,6 +1345,11 @@ ntfs_filesize( return (0); } +/* + * This is one of write routine. + * + * ntnode should be locked. + */ int ntfs_writeattr_plain( struct ntfsmount * ntmp, @@ -1234,6 +1401,11 @@ ntfs_writeattr_plain( return (error); } +/* + * This is one of write routine. + * + * ntnode should be locked. + */ int ntfs_writentvattr_plain( struct ntfsmount * ntmp, @@ -1313,7 +1485,7 @@ ntfs_writentvattr_plain( } } memcpy(bp->b_data + off, data, tocopy); - bwrite(bp); + bawrite(bp); data = data + tocopy; *initp += tocopy; off = 0; @@ -1336,6 +1508,11 @@ ntfs_writentvattr_plain( return (error); } +/* + * This is one of read routines. + * + * ntnode should be locked. + */ int ntfs_readntvattr_plain( struct ntfsmount * ntmp, @@ -1379,7 +1556,7 @@ ntfs_readntvattr_plain( cnt++; continue; } - if (ccn || ip->i_number == NTFS_BOOTINO) { /* XXX */ + if (ccn || ip->i_number == NTFS_BOOTINO) { ccl -= ntfs_btocn(off); cn = ccn + ntfs_btocn(off); off = ntfs_btocnoff(off); @@ -1442,6 +1619,11 @@ ntfs_readntvattr_plain( return (error); } +/* + * This is one of read routines. + * + * ntnode should be locked. + */ int ntfs_readattr_plain( struct ntfsmount * ntmp, @@ -1493,6 +1675,11 @@ ntfs_readattr_plain( return (error); } +/* + * This is one of read routines. + * + * ntnode should be locked. + */ int ntfs_readattr( struct ntfsmount * ntmp, @@ -1574,6 +1761,7 @@ ntfs_readattr( return (error); } +#if UNUSED_CODE int ntfs_parserun( cn_t * cn, @@ -1616,7 +1804,11 @@ ntfs_parserun( return (0); } +#endif +/* + * Process fixup routine on given buffer. + */ int ntfs_procfixups( struct ntfsmount * ntmp, @@ -1659,6 +1851,7 @@ ntfs_procfixups( return (0); } +#if UNUSED_CODE int ntfs_runtocn( cn_t * cn, @@ -1701,3 +1894,4 @@ ntfs_runtocn( *cn = ccn + vcn; return (0); } +#endif diff --git a/sys/fs/ntfs/ntfs_subr.h b/sys/fs/ntfs/ntfs_subr.h index 692bb544c570..3cfc783eb432 100644 --- a/sys/fs/ntfs/ntfs_subr.h +++ b/sys/fs/ntfs/ntfs_subr.h @@ -30,7 +30,7 @@ #define VA_PRELOADED 0x0002 struct ntvattr { - struct ntvattr *va_nextp; + LIST_ENTRY(ntvattr) va_list; u_int32_t va_vflag; struct vnode *va_vp; @@ -99,12 +99,14 @@ 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 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_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_ntlookup __P((struct ntfsmount *, ino_t, struct ntnode **)); +int ntfs_ntget __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 *, char *, int, int *, char **); int ntfs_writentvattr_plain(struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *, size_t *); diff --git a/sys/fs/ntfs/ntfs_vfsops.c b/sys/fs/ntfs/ntfs_vfsops.c index a371319a9de1..7d1f91dc323c 100644 --- a/sys/fs/ntfs/ntfs_vfsops.c +++ b/sys/fs/ntfs/ntfs_vfsops.c @@ -102,13 +102,6 @@ static int ntfs_init () #endif { - static first=1; - - if(!first) return (0); - first = 1; - - printf("ntfs_init(): \n"); - ntfs_nthashinit(); return 0; @@ -384,6 +377,12 @@ ntfs_mountfs(devvp, mp, argsp, p) brelse( bp ); bp = NULL; + if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) { + error = EINVAL; + printf("ntfs_mountfs: invalid boot block\n"); + goto out; + } + { int8_t cpr = ntmp->ntm_mftrecsz; if( cpr > 0 ) @@ -391,11 +390,11 @@ ntfs_mountfs(devvp, mp, argsp, p) else ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps; } - printf("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n", + dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n", ntmp->ntm_bps,ntmp->ntm_spc,ntmp->ntm_bootfile.bf_media, - ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec); - printf("ntfs_mountfs(): mftcn: 0x%x|0x%x\n", - (u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn); + ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec)); + dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n", + (u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn)); ntmp->ntm_mountp = mp; ntmp->ntm_dev = dev; @@ -406,51 +405,64 @@ ntfs_mountfs(devvp, mp, argsp, p) ntmp->ntm_flag = argsp->flag; mp->mnt_data = (qaddr_t)ntmp; - printf("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n", + dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n", (ntmp->ntm_flag & NTFS_MFLAG_CASEINS)?"insens.":"sens.", (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)?" allnames,":"", - ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode); + ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode)); - printf("ntfs_mountfs(): reading system nodes...\n"); + /* + * We read in some system nodes to do not allow + * reclaim them and to have everytime access to them. + */ { - i = NTFS_MFTINO; - 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]); - vput(ntmp->ntm_sysvn[i]); + int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO }; + for (i=0; i<3; i++) { + error = VFS_VGET(mp, pi[i], &(ntmp->ntm_sysvn[pi[i]])); + if(error) + goto out1; + ntmp->ntm_sysvn[pi[i]]->v_flag |= VSYSTEM; + VREF(ntmp->ntm_sysvn[pi[i]]); + vput(ntmp->ntm_sysvn[pi[i]]); + } } - MALLOC( ntmp->ntm_upcase, wchar *, 65536 * sizeof(wchar), + /* + * Read in WHOLE lowcase -> upcase translation + * file. + */ + MALLOC(ntmp->ntm_upcase, wchar *, 65536 * sizeof(wchar), M_NTFSMNT, M_WAITOK); - printf("ntfs_mountfs(): opening $UpCase\n"); - error = VFS_VGET(mp, NTFS_UPCASEINO, &vp ); + error = VFS_VGET(mp, NTFS_UPCASEINO, &vp); if(error) goto out1; - printf("ntfs_mountfs(): reading $UpCase\n"); - error = ntfs_readattr( 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); if(error) goto out1; + /* + * Scan $BitMap and count free clusters + */ + error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree); + if(error) + goto out1; + + /* + * Read and translate to internal format attribute + * definition file. + */ { int num,j; struct attrdef ad; - printf("ntfs_mountfs(): opening $AttrDef\n"); + /* Open $AttrDef */ error = VFS_VGET(mp, NTFS_ATTRDEFINO, &vp ); if(error) goto out1; + /* Count valid entries */ for(num=0;;num++) { error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, @@ -461,14 +473,15 @@ ntfs_mountfs(devvp, mp, argsp, p) if (ad.ad_name[0] == 0) break; } - printf("ntfs_mountfs(): reading %d attrdefs\n",num); + /* Alloc memory for attribute definitions */ MALLOC(ntmp->ntm_ad, struct ntvattrdef *, num * sizeof(struct ntvattrdef), M_NTFSMNT, M_WAITOK); ntmp->ntm_adnum = num; + /* Read them and translate */ for(i=0;intm_ad[i].ad_namelen = j - 1; ntmp->ntm_ad[i].ad_type = ad.ad_type; - printf("ntfs_mountfs(): attribute: %s, type: 0x%x\n", - ntmp->ntm_ad[i].ad_name, - ntmp->ntm_ad[i].ad_type); } - printf("ntfs_mountfs(): closing $AttrDef\n"); + vput(vp); } @@ -504,9 +514,14 @@ ntfs_mountfs(devvp, mp, argsp, p) devvp->v_specflags |= SI_MOUNTEDON; #endif return (0); + out1: for(i=0;intm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); + + if (vflush(mp,NULLVP,0)) + printf("ntfs_mountfs: vflush failed\n"); + out: #if __FreeBSD_version >= 300000 devvp->v_specmountpoint = NULL; @@ -525,7 +540,6 @@ ntfs_start ( int flags, struct proc *p ) { - printf("\nntfs_start():\n"); return (0); } @@ -538,24 +552,33 @@ ntfs_unmount( register struct ntfsmount *ntmp; int error, ronly = 0, flags, i; - printf("ntfs_unmount: unmounting...\n"); + dprintf(("ntfs_unmount: unmounting...\n")); ntmp = VFSTONTFS(mp); flags = 0; if(mntflags & MNT_FORCE) flags |= FORCECLOSE; - printf("ntfs_unmount: vflushing...\n"); + dprintf(("ntfs_unmount: vflushing...\n")); error = vflush(mp,NULLVP,flags | SKIPSYSTEM); if (error) { printf("ntfs_unmount: vflush failed: %d\n",error); return (error); } + + /* Check if only system vnodes are rest */ + for(i=0;intm_sysvn[i]) && + (ntmp->ntm_sysvn[i]->v_usecount > 1)) return (EBUSY); + + /* Derefernce all system vnodes */ for(i=0;intm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); + + /* vflush system vnodes */ error = vflush(mp,NULLVP,flags); if (error) - printf("ntfs_unmount: vflush failed: %d\n",error); + printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error); #if __FreeBSD_version >= 300000 ntmp->ntm_devvp->v_specmountpoint = NULL; @@ -573,7 +596,7 @@ ntfs_unmount( vrele(ntmp->ntm_devvp); - printf("ntfs_umount: freeing memory...\n"); + dprintf(("ntfs_umount: freeing memory...\n")); mp->mnt_data = (qaddr_t)0; mp->mnt_flag &= ~MNT_LOCAL; FREE(ntmp->ntm_ad, M_NTFSMNT); @@ -614,6 +637,41 @@ ntfs_quotactl ( return EOPNOTSUPP; } +int +ntfs_calccfree( + struct ntfsmount *ntmp, + cn_t *cfreep) +{ + struct vnode *vp; + u_int8_t *tmp; + int j, error; + long cfree = 0; + size_t bmsize, i; + + vp = ntmp->ntm_sysvn[NTFS_BITMAPINO]; + + bmsize = VTOF(vp)->f_size; + + 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); + } + + for(i=0;intm_sysvn[NTFS_MFTINO]), - &mftsize, &mftallocated); - - error = VFS_VGET(mp, NTFS_BITMAPINO, &vp); - if(error) - return (error); - - ntfs_filesize(ntmp, VTOF(vp), &bmsize, &bmallocated); - - 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); - vput(vp); - return (error); - } - vput(vp); - - sbp->f_bfree = 0; - for(i=0;if_bfree++; - - FREE(tmp, M_TEMP); + mftsize = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_size; + mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated; #if __FreeBSD_version >= 300000 sbp->f_type = mp->mnt_vfc->vfc_typenum; @@ -663,7 +694,7 @@ ntfs_statfs( sbp->f_bsize = ntmp->ntm_bps; sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc; sbp->f_blocks = ntmp->ntm_bootfile.bf_spv; - sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(sbp->f_bfree); + sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree); sbp->f_ffree = sbp->f_bfree / ntmp->ntm_bpmftrec; sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) + sbp->f_ffree; @@ -746,41 +777,63 @@ ntfs_vgetex( *vpp = NULL; /* Get ntnode */ - error = ntfs_ntget(ntmp, ino, &ip); + error = ntfs_ntlookup(ntmp, ino, &ip); if (error) { printf("ntfs_vget: ntfs_ntget failed\n"); return (error); } + /* It may be not initialized fully, so force load it */ + if (!(flags & VG_DONTLOADIN) && !(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_ntput(ip); + return (error); + } + } + error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp); if (error) { printf("ntfs_vget: ntfs_fget failed\n"); - ntfs_ntrele(ip); + ntfs_ntput(ip); return (error); } + 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; + } else { + fp->f_type = VREG; + + error = ntfs_filesize(ntmp, fp, + &fp->f_size, &fp->f_allocated); + if (error) { + ntfs_ntput(ip); + return (error); + } + } + + fp->f_flag |= FN_VALID; + } + if (FTOV(fp)) { vget(FTOV(fp), lkflags, p); *vpp = FTOV(fp); - ntfs_ntrele(ip); + ntfs_ntput(ip); return (0); } - /* 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 = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, &vp); if(error) { ntfs_frele(fp); - ntfs_ntrele(ip); + ntfs_ntput(ip); return (error); } dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino)); @@ -788,18 +841,12 @@ ntfs_vgetex( 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; + vp->v_type = fp->f_type; if (ino == NTFS_ROOTINO) vp->v_flag |= VROOT; - if (ino < NTFS_SYSNODESNUM) - vp->v_flag |= VSYSTEM; - ntfs_ntrele(ip); + ntfs_ntput(ip); if (lkflags & LK_TYPE_MASK) { error = vn_lock(vp, lkflags, p); diff --git a/sys/fs/ntfs/ntfs_vfsops.h b/sys/fs/ntfs/ntfs_vfsops.h index c8788c480be4..af5ce9d7e135 100644 --- a/sys/fs/ntfs/ntfs_vfsops.h +++ b/sys/fs/ntfs/ntfs_vfsops.h @@ -25,9 +25,13 @@ * * $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 */ +#define VG_DONTLOADIN 0x0001 /* Tells ntfs_vgetex to do not call */ /* ntfs_loadnode on ntnode, even if */ /* ntnode not loaded */ +#define VG_DONTVALIDFN 0x0002 /* Tells ntfs_vgetex to do not validate */ + /* fnode */ +#define VG_EXT 0x0004 /* This is not main record */ int ntfs_vgetex(struct mount *, ino_t, u_int32_t, char *, u_long, u_long, struct proc *, struct vnode **); +int ntfs_calccfree(struct ntfsmount *, cn_t *); diff --git a/sys/fs/ntfs/ntfs_vnops.c b/sys/fs/ntfs/ntfs_vnops.c index f1a822a5935c..d22ea5fa80a3 100644 --- a/sys/fs/ntfs/ntfs_vnops.c +++ b/sys/fs/ntfs/ntfs_vnops.c @@ -156,7 +156,8 @@ 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, fp, &toread, NULL); + toread = fp->f_size; + dprintf(("ntfs_read: filesize: %d",(u_int32_t)toread)); toread = min( uio->uio_resid, toread - uio->uio_offset ); @@ -165,7 +166,7 @@ ntfs_read(ap) MALLOC(data, u_int8_t *, toread, M_TEMP,M_WAITOK); - error = ntfs_readattr( ntmp, ip, fp->f_attrtype, + error = ntfs_readattr(ntmp, ip, fp->f_attrtype, fp->f_attrname, uio->uio_offset, toread, data); if(error) { printf("ntfs_read: ntfs_readattr failed: %d\n",error); @@ -245,9 +246,7 @@ ntfs_inactive(ap) } */ *ap; { register struct vnode *vp = ap->a_vp; -#if defined(NTFS_DEBUG) || defined(DISGNOSTIC) register struct ntnode *ip = VTONT(vp); -#endif int error; dprintf(("ntfs_inactive: vnode: %p, ntnode: %d\n", vp, ip->i_number)); @@ -262,7 +261,7 @@ ntfs_inactive(ap) #else #ifdef DIAGNOSTIC if (VOP_ISLOCKED(vp)) - panic("ntfs_inactive: locked ntnode"); + panic("ntfs_inactive: locked vnode"); if (curproc) ip->i_lockholder = curproc->p_pid; else @@ -275,7 +274,7 @@ ntfs_inactive(ap) * If we are done with the ntnode, reclaim it * so that it can be reused immediately. */ - if (vp->v_usecount == 0 /*&& ip->i_mode == 0*/) + if (vp->v_usecount == 0 && ip->i_mode == 0) #if __FreeBSD_version >= 300000 vrecycle(vp, (struct simplelock *)0, ap->a_p); #else @@ -295,12 +294,15 @@ ntfs_reclaim(ap) { register struct vnode *vp = ap->a_vp; register struct fnode *fp = VTOF(vp); -#if NTFS_DEBUG register struct ntnode *ip = FTONT(fp); -#endif + int error; dprintf(("ntfs_reclaim: vnode: %p, ntnode: %d\n", vp, ip->i_number)); + error = ntfs_ntget(ip); + if (error) + return (error); + #if __FreeBSD_version >= 300000 VOP_UNLOCK(vp,0,ap->a_p); #endif @@ -316,6 +318,8 @@ ntfs_reclaim(ap) vp->v_data = NULL; + ntfs_ntput(ip); + return (0); } @@ -428,15 +432,15 @@ ntfs_write(ap) 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)); - ntfs_filesize(ntmp, fp, &towrite, NULL); + 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"); return (EFBIG); } - dprintf(("ntfs_write: filesize: %d",(u_int32_t)towrite)); - towrite = min(uio->uio_resid, towrite - uio->uio_offset); off = uio->uio_offset; @@ -948,7 +952,7 @@ ntfs_lookup(ap) } return (error); } else { - error = ntfs_ntlookup(ntmp, dvp, cnp, ap->a_vpp); + error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp); if(error) return (error); @@ -961,6 +965,8 @@ ntfs_lookup(ap) #else VOP_UNLOCK(dvp); #endif + if (cnp->cn_flags & MAKEENTRY) + cache_enter(dvp, *ap->a_vpp, cnp); } return (error); diff --git a/sys/ntfs/ntfs.h b/sys/ntfs/ntfs.h index e2bda5e7f779..e9fa1b3fcdc8 100644 --- a/sys/ntfs/ntfs.h +++ b/sys/ntfs/ntfs.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ntfs.h,v 1.2 1999/02/19 12:31:02 semenu Exp $ + * $Id: ntfs.h,v 1.9 1999/02/02 01:54:54 semen Exp $ */ /*#define NTFS_DEBUG 1*/ @@ -213,6 +213,8 @@ struct ntvattrdef { u_int32_t ad_type; }; +#define NTFS_BBID "NTFS " +#define NTFS_BBIDLEN 8 struct bootfile { u_int8_t reserved1[3]; /* asm jmp near ... */ u_int8_t bf_sysid[8]; /* 'NTFS ' */ @@ -246,6 +248,7 @@ struct ntfsmount { gid_t ntm_gid; mode_t ntm_mode; u_long ntm_flag; + cn_t ntm_cfree; struct ntvattrdef *ntm_ad; int ntm_adnum; }; diff --git a/sys/ntfs/ntfs_inode.h b/sys/ntfs/ntfs_inode.h index 2e6fb788fa96..bf1e26c73808 100644 --- a/sys/ntfs/ntfs_inode.h +++ b/sys/ntfs/ntfs_inode.h @@ -55,17 +55,18 @@ #define IN_PRELOADED 0x4000 /* loaded from directory entry */ struct ntnode { - LIST_ENTRY(ntnode) i_hash; + LIST_ENTRY(ntnode) i_hash; struct ntnode *i_next; struct ntnode **i_prev; - struct ntfsmount *i_mp; + struct ntfsmount *i_mp; ino_t i_number; dev_t i_dev; u_int32_t i_flag; + int i_lock; int i_usecount; - LIST_HEAD(,fnode) i_fnlist; - struct ntvattr *i_vattrp; /* ntvattrs list */ + LIST_HEAD(,fnode) i_fnlist; + LIST_HEAD(,ntvattr) i_valist; long i_nlink; /* MFR */ ino_t i_mainrec; /* MFR */ @@ -77,7 +78,7 @@ struct ntnode { }; #define FN_PRELOADED 0x0001 -#define FN_DEFAULT 0x0002 +#define FN_VALID 0x0002 #define FN_AATTRNAME 0x0004 /* space allocated for f_attrname */ struct fnode { struct lock f_lock; /* Must be first */ diff --git a/sys/ntfs/ntfs_subr.c b/sys/ntfs/ntfs_subr.c index 901ea6940310..cecc00af4e24 100644 --- a/sys/ntfs/ntfs_subr.c +++ b/sys/ntfs/ntfs_subr.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998, 1999 Semen Ustimenko + * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,6 +58,9 @@ MALLOC_DEFINE(M_NTFSRUN, "NTFS vrun", "NTFS vrun storage"); MALLOC_DEFINE(M_NTFSDECOMP, "NTFS decomp", "NTFS decompression temporary"); #endif +/* + * + */ int ntfs_ntvattrrele( struct ntvattr * vap) @@ -70,6 +73,13 @@ ntfs_ntvattrrele( return (0); } +/* + * 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). + * + * ntnode should be locked + */ int ntfs_ntvattrget( struct ntfsmount * ntmp, @@ -113,7 +123,7 @@ ntfs_ntvattrget( } } - for (vap = ip->i_vattrp; vap; vap = vap->va_nextp) { + 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)); @@ -171,14 +181,20 @@ ntfs_ntvattrget( dprintf(("ntfs_ntvattrget: attrbute 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)); @@ -190,7 +206,7 @@ ntfs_ntvattrget( goto out; } } - for (vap = newip->i_vattrp; vap; vap = vap->va_nextp) { + 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) && @@ -219,10 +235,14 @@ ntfs_ntvattrget( ip->i_number, type, name, (u_int32_t) vcn)); out: FREE(alpool, M_TEMP); - return (error); } +/* + * Read ntnode from disk, make ntvattr list. + * + * ntnode should be locked + */ int ntfs_loadntnode( struct ntfsmount * ntmp, @@ -232,7 +252,7 @@ ntfs_loadntnode( daddr_t bn; int error,off; struct attr *ap; - struct ntvattr**vapp; + struct ntvattr *nvap; dprintf(("ntfs_loadnode: loading ino: %d\n",ip->i_number)); @@ -269,6 +289,7 @@ ntfs_loadntnode( goto out; } } + /* Check if magic and fixups are correct */ error = ntfs_procfixups(ntmp, NTFS_FILEMAGIC, (caddr_t)mfrp, ntfs_bntob(ntmp->ntm_bpmftrec)); @@ -281,16 +302,16 @@ ntfs_loadntnode( 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"); + + LIST_INIT(&ip->i_valist); - vapp = &ip->i_vattrp; while (ap->a_hdr.a_type != -1) { - error = ntfs_attrtontvattr(ntmp, vapp, ap); + error = ntfs_attrtontvattr(ntmp, &nvap, ap); if (error) break; - (*vapp)->va_ip = ip; - vapp = &((*vapp)->va_nextp); + nvap->va_ip = ip; + + LIST_INSERT_HEAD(&ip->i_valist, nvap, va_list); off += ap->a_hdr.reclen; ap = (struct attr *) ((caddr_t)mfrp + off); @@ -312,44 +333,74 @@ out: return (error); } - -static int ntfs_ntnode_hash_lock; +/* + * Routine locks ntnode and increase usecount, just opposite of + * ntfs_ntput. + */ int ntfs_ntget( + struct ntnode *ip) +{ + dprintf(("ntfs_ntget: get ntnode %d: %p, usecount: %d\n", + ip->i_number, ip, ip->i_usecount)); + + 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; + + return 0; +} + +/* + * Routine search ntnode in hash, if found: lock, inc usecount and return. + * If not in hash allocate structure for ntnode, prefill it, lock, + * inc count and return. + * + * ntnode returned locked + */ +static int ntfs_ntnode_hash_lock; +int +ntfs_ntlookup( struct ntfsmount * ntmp, ino_t ino, struct ntnode ** ipp) { struct ntnode *ip; - dprintf(("ntfs_ntget: ntget ntnode %d\n", ino)); + dprintf(("ntfs_ntlookup: for ntnode %d\n", ino)); *ipp = NULL; restart: - ip = ntfs_nthashlookup(ntmp->ntm_dev, ino); + ip = ntfs_nthashlookup(ntmp->ntm_dev, ino); /* XXX */ if (ip) { - ip->i_usecount++; + ntfs_ntget(ip); *ipp = ip; - dprintf(("ntfs_ntget: ntnode %d: %p, usecount: %d\n", + dprintf(("ntfs_ntlookup: 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_NTFSNTNODE, M_WAITOK); - ddprintf(("ntfs_ntget: allocating ntnode: %d: %p\n", ino, ip)); + ddprintf(("ntfs_ntlookup: allocating ntnode: %d: %p\n", ino, ip)); bzero((caddr_t) ip, sizeof(struct ntnode)); /* Generic initialization */ @@ -361,6 +412,8 @@ restart: ip->i_mode = ntmp->ntm_mode; ip->i_usecount++; + ip->i_lock = 1; + LIST_INIT(&ip->i_fnlist); ntfs_nthashins(ip); @@ -371,45 +424,77 @@ restart: *ipp = ip; - dprintf(("ntfs_ntget: ntnode %d: %p, usecount: %d\n", + dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n", ino, ip, ip->i_usecount)); return (0); } +/* + * Decrement usecount of ntnode and unlock it, if usecount reach zero, + * deallocate ntnode. + * + * ntnode should be locked on entry, and unlocked on return. + */ void -ntfs_ntrele( - struct ntnode * ip) +ntfs_ntput( + struct ntnode *ip) { struct ntvattr *vap; - dprintf(("ntfs_ntrele: rele ntnode %d: %p, usecount: %d\n", + 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)); ip->i_usecount--; if (ip->i_usecount < 0) { - panic("ntfs_ntrele: ino: %d usecount: %d \n", + panic("ntfs_ntput: ino: %d usecount: %d \n", ip->i_number,ip->i_usecount); } else if (ip->i_usecount == 0) { - dprintf(("ntfs_ntrele: deallocating ntnode: %d\n", + dprintf(("ntfs_ntput: deallocating ntnode: %d\n", ip->i_number)); if (ip->i_fnlist.lh_first) - panic("ntfs_ntrele: ntnode has fnodes\n"); + panic("ntfs_ntput: ntnode has fnodes\n"); ntfs_nthashrem(ip); - while (ip->i_vattrp) { - vap = ip->i_vattrp; - ip->i_vattrp = vap->va_nextp; + while (ip->i_valist.lh_first != NULL) { + vap = ip->i_valist.lh_first; + LIST_REMOVE(vap,va_list); ntfs_freentvattr(vap); } FREE(ip, M_NTFSNTNODE); + } else { + if (ip->i_lock < 0) + wakeup(&ip->i_lock); + ip->i_lock = 0; } - dprintf(("ntfs_ntrele: rele ok\n")); } +/* + * Decrement usecount of ntnode. + */ +void +ntfs_ntrele( + struct ntnode * ip) +{ + 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); +} + +/* + * Deallocate all memory allocated for ntvattr by call to + * ntfs_attrtontvattr and some other functions. + */ void ntfs_freentvattr( struct ntvattr * vap) @@ -426,6 +511,10 @@ ntfs_freentvattr( FREE(vap, M_NTFSNTVATTR); } +/* + * Convert disk image of attribute into ntvattr structure, + * runs are expanded also. + */ int ntfs_attrtontvattr( struct ntfsmount * ntmp, @@ -493,6 +582,9 @@ ntfs_attrtontvattr( return (error); } +/* + * Expand run into more utilizable and more memory eating format. + */ int ntfs_runtovrun( cn_t ** rcnp, @@ -552,7 +644,9 @@ ntfs_runtovrun( return (0); } - +/* + * Convert wchar to uppercase wchar, should be macros? + */ wchar ntfs_toupper( struct ntfsmount * ntmp, @@ -561,6 +655,9 @@ ntfs_toupper( return (ntmp->ntm_upcase[wc & 0xFF]); } +/* + * Compare to unicode strings case insensible. + */ int ntfs_uustricmp( struct ntfsmount * ntmp, @@ -581,6 +678,9 @@ ntfs_uustricmp( return (str1len - str2len); } +/* + * Compare unicode and ascii string case insens. + */ int ntfs_uastricmp( struct ntfsmount * ntmp, @@ -601,6 +701,9 @@ ntfs_uastricmp( return (str1len - str2len); } +/* + * Compare unicode and ascii string case sens. + */ int ntfs_uastrcmp( struct ntfsmount * ntmp, @@ -620,6 +723,11 @@ ntfs_uastrcmp( return (str1len - str2len); } +/* + * Search fnode in ntnode, if not found allocate and preinitialize. + * + * ntnode should be locked on entry. + */ int ntfs_fget( struct ntfsmount *ntmp, @@ -628,7 +736,6 @@ ntfs_fget( char *attrname, struct fnode **fpp) { - int error; struct fnode *fp; dprintf(("ntfs_fget: ino: %d, attrtype: 0x%x, attrname: %s\n", @@ -662,15 +769,6 @@ ntfs_fget( 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); @@ -681,6 +779,11 @@ ntfs_fget( return (0); } +/* + * Deallocate fnode, remove it from ntnode's fnode list. + * + * ntnode should be locked. + */ void ntfs_frele( struct fnode *fp) @@ -699,6 +802,11 @@ ntfs_frele( ntfs_ntrele(ip); } +/* + * Lookup attribute name in format: [[:$ATTR_TYPE]:$ATTR_NAME], + * $ATTR_TYPE is searched in attrdefs read from $AttrDefs. + * If $ATTR_TYPE nott specifed, ATTR_A_DATA assumed. + */ int ntfs_ntlookupattr( struct ntfsmount * ntmp, @@ -753,12 +861,13 @@ ntfs_ntlookupattr( return (0); } + /* * Lookup specifed node for filename, matching cnp, * return fnode filled. */ int -ntfs_ntlookup( +ntfs_ntlookupfile( struct ntfsmount * ntmp, struct vnode * vp, struct componentname * cnp, @@ -776,6 +885,10 @@ ntfs_ntlookup( char *fname,*aname; u_int32_t aoff; + error = ntfs_ntget(ip); + if (error) + return (error); + error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap); if (error || (vap->va_flag & NTFS_AF_INRUN)) return (ENOTDIR); @@ -783,6 +896,10 @@ ntfs_ntlookup( blsize = vap->va_a_iroot->ir_size; rdsize = vap->va_datalen; + /* + * Divide file name into: foofilefoofilefoofile[:attrspec] + * Store like this: fname:fnamelen [aname:anamelen] + */ fname = cnp->cn_nameptr; aname = NULL; anamelen = 0; @@ -790,12 +907,12 @@ ntfs_ntlookup( if(fname[fnamelen] == ':') { aname = fname + fnamelen + 1; anamelen = cnp->cn_namelen - fnamelen - 1; - dprintf(("ntfs_ntlookup: file %s (%d), attr: %s (%d)\n", + dprintf(("ntfs_ntlookupfile: %s (%d), attr: %s (%d)\n", fname, fnamelen, aname, anamelen)); break; } - dprintf(("ntfs_ntlookup: blocksize: %d, rdsize: %d\n", blsize, rdsize)); + dprintf(("ntfs_ntlookupfile: blksz: %d, rdsz: %d\n", blsize, rdsize)); MALLOC(rdbuf, caddr_t, blsize, M_TEMP, M_WAITOK); @@ -856,7 +973,8 @@ ntfs_ntlookup( attrtype, attrname, LK_EXCLUSIVE, - VG_DONTLOAD, + VG_DONTLOADIN | + VG_DONTVALIDFN, curproc, &nvp); if(error) @@ -864,6 +982,11 @@ ntfs_ntlookup( 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; @@ -883,7 +1006,17 @@ ntfs_ntlookup( 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; + } } + + nfp->f_flag &= ~FN_VALID; *vpp = nvp; goto fail; } @@ -896,7 +1029,7 @@ ntfs_ntlookup( /* Dive if possible */ if (iep->ie_flag & NTFS_IEFLAG_SUBNODE) { - dprintf(("ntfs_ntlookup: diving\n")); + dprintf(("ntfs_ntlookupfile: diving\n")); cn = *(cn_t *) (rdbuf + aoff + iep->reclen - sizeof(cn_t)); @@ -915,7 +1048,7 @@ ntfs_ntlookup( aoff = (((struct attr_indexalloc *) rdbuf)->ia_hdrsize + 0x18); } else { - dprintf(("ntfs_ntlookup: nowhere to dive :-(\n")); + dprintf(("ntfs_ntlookupfile: nowhere to dive :-(\n")); error = ENOENT; break; } @@ -925,10 +1058,14 @@ ntfs_ntlookup( fail: ntfs_ntvattrrele(vap); + ntfs_ntput(ip); FREE(rdbuf, M_TEMP); return (error); } +/* + * Check if name type is permitted to show. + */ int ntfs_isnamepermitted( struct ntfsmount * ntmp, @@ -942,9 +1079,7 @@ ntfs_isnamepermitted( case 2: ddprintf(("ntfs_isnamepermitted: skiped DOS name\n")); return 0; - case 0: - case 1: - case 3: + case 0: case 1: case 3: return 1; default: printf("ntfs_isnamepermitted: " \ @@ -955,6 +1090,14 @@ ntfs_isnamepermitted( return 0; } +/* + * Read ntfs dir like stream of attr_indexentry, not like btree of them. + * This is done by scaning $BITMAP:$I30 for busy clusters and reading them. + * Ofcouse $INDEX_ROOT:$I30 is read before. Last read values are stored in + * fnode, so we can skip toward record number num almost immediatly. + * Anyway this is rather slow routine. The problem is that we don't know + * how many records are there in $INDEX_ALLOCATION:$I30 block. + */ int ntfs_ntreaddir( struct ntfsmount * ntmp, @@ -978,6 +1121,10 @@ ntfs_ntreaddir( u_int32_t aoff, cnum; dprintf(("ntfs_ntreaddir: read ino: %d, num: %d\n", ip->i_number, num)); + error = ntfs_ntget(ip); + if (error) + return (error); + error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap); if (error) return (ENOTDIR); @@ -1106,12 +1253,14 @@ fail: ntfs_ntvattrrele(iavap); if (bmp) FREE(bmp, M_TEMP); + ntfs_ntput(ip); return (error); } -/* - * #undef dprintf #define dprintf(a) - */ +/* + * Convert NTFS times that are in 100 ns units and begins from + * 1601 Jan 1 into unix times. + */ struct timespec ntfs_nttimetounix( u_int64_t nt) @@ -1126,6 +1275,9 @@ ntfs_nttimetounix( return (t); } +/* + * Get file times from NTFS_A_NAME attribute. + */ int ntfs_times( struct ntfsmount * ntmp, @@ -1136,15 +1288,28 @@ ntfs_times( int error; dprintf(("ntfs_times: ino: %d...\n", ip->i_number)); - error = ntfs_ntvattrget(ntmp, ip, NTFS_A_NAME, NULL, 0, &vap); + + error = ntfs_ntget(ip); if (error) return (error); + + error = ntfs_ntvattrget(ntmp, ip, NTFS_A_NAME, NULL, 0, &vap); + if (error) { + ntfs_ntput(ip); + return (error); + } *tm = vap->va_a_name->n_times; ntfs_ntvattrrele(vap); + ntfs_ntput(ip); return (0); } +/* + * Get file sizes from corresponding attribute. + * + * ntnode under fnode should be locked. + */ int ntfs_filesize( struct ntfsmount * ntmp, @@ -1158,15 +1323,12 @@ ntfs_filesize( int error; dprintf(("ntfs_filesize: ino: %d\n", ip->i_number)); - 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); - } + + error = ntfs_ntvattrget(ntmp, ip, + fp->f_attrtype, fp->f_attrname, 0, &vap); if (error) return (error); + bn = vap->va_allocated; sz = vap->va_datalen; @@ -1183,6 +1345,11 @@ ntfs_filesize( return (0); } +/* + * This is one of write routine. + * + * ntnode should be locked. + */ int ntfs_writeattr_plain( struct ntfsmount * ntmp, @@ -1234,6 +1401,11 @@ ntfs_writeattr_plain( return (error); } +/* + * This is one of write routine. + * + * ntnode should be locked. + */ int ntfs_writentvattr_plain( struct ntfsmount * ntmp, @@ -1313,7 +1485,7 @@ ntfs_writentvattr_plain( } } memcpy(bp->b_data + off, data, tocopy); - bwrite(bp); + bawrite(bp); data = data + tocopy; *initp += tocopy; off = 0; @@ -1336,6 +1508,11 @@ ntfs_writentvattr_plain( return (error); } +/* + * This is one of read routines. + * + * ntnode should be locked. + */ int ntfs_readntvattr_plain( struct ntfsmount * ntmp, @@ -1379,7 +1556,7 @@ ntfs_readntvattr_plain( cnt++; continue; } - if (ccn || ip->i_number == NTFS_BOOTINO) { /* XXX */ + if (ccn || ip->i_number == NTFS_BOOTINO) { ccl -= ntfs_btocn(off); cn = ccn + ntfs_btocn(off); off = ntfs_btocnoff(off); @@ -1442,6 +1619,11 @@ ntfs_readntvattr_plain( return (error); } +/* + * This is one of read routines. + * + * ntnode should be locked. + */ int ntfs_readattr_plain( struct ntfsmount * ntmp, @@ -1493,6 +1675,11 @@ ntfs_readattr_plain( return (error); } +/* + * This is one of read routines. + * + * ntnode should be locked. + */ int ntfs_readattr( struct ntfsmount * ntmp, @@ -1574,6 +1761,7 @@ ntfs_readattr( return (error); } +#if UNUSED_CODE int ntfs_parserun( cn_t * cn, @@ -1616,7 +1804,11 @@ ntfs_parserun( return (0); } +#endif +/* + * Process fixup routine on given buffer. + */ int ntfs_procfixups( struct ntfsmount * ntmp, @@ -1659,6 +1851,7 @@ ntfs_procfixups( return (0); } +#if UNUSED_CODE int ntfs_runtocn( cn_t * cn, @@ -1701,3 +1894,4 @@ ntfs_runtocn( *cn = ccn + vcn; return (0); } +#endif diff --git a/sys/ntfs/ntfs_subr.h b/sys/ntfs/ntfs_subr.h index 692bb544c570..3cfc783eb432 100644 --- a/sys/ntfs/ntfs_subr.h +++ b/sys/ntfs/ntfs_subr.h @@ -30,7 +30,7 @@ #define VA_PRELOADED 0x0002 struct ntvattr { - struct ntvattr *va_nextp; + LIST_ENTRY(ntvattr) va_list; u_int32_t va_vflag; struct vnode *va_vp; @@ -99,12 +99,14 @@ 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 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_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_ntlookup __P((struct ntfsmount *, ino_t, struct ntnode **)); +int ntfs_ntget __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 *, char *, int, int *, char **); int ntfs_writentvattr_plain(struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *, size_t *); diff --git a/sys/ntfs/ntfs_vfsops.c b/sys/ntfs/ntfs_vfsops.c index a371319a9de1..7d1f91dc323c 100644 --- a/sys/ntfs/ntfs_vfsops.c +++ b/sys/ntfs/ntfs_vfsops.c @@ -102,13 +102,6 @@ static int ntfs_init () #endif { - static first=1; - - if(!first) return (0); - first = 1; - - printf("ntfs_init(): \n"); - ntfs_nthashinit(); return 0; @@ -384,6 +377,12 @@ ntfs_mountfs(devvp, mp, argsp, p) brelse( bp ); bp = NULL; + if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) { + error = EINVAL; + printf("ntfs_mountfs: invalid boot block\n"); + goto out; + } + { int8_t cpr = ntmp->ntm_mftrecsz; if( cpr > 0 ) @@ -391,11 +390,11 @@ ntfs_mountfs(devvp, mp, argsp, p) else ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps; } - printf("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n", + dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n", ntmp->ntm_bps,ntmp->ntm_spc,ntmp->ntm_bootfile.bf_media, - ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec); - printf("ntfs_mountfs(): mftcn: 0x%x|0x%x\n", - (u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn); + ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec)); + dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n", + (u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn)); ntmp->ntm_mountp = mp; ntmp->ntm_dev = dev; @@ -406,51 +405,64 @@ ntfs_mountfs(devvp, mp, argsp, p) ntmp->ntm_flag = argsp->flag; mp->mnt_data = (qaddr_t)ntmp; - printf("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n", + dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n", (ntmp->ntm_flag & NTFS_MFLAG_CASEINS)?"insens.":"sens.", (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)?" allnames,":"", - ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode); + ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode)); - printf("ntfs_mountfs(): reading system nodes...\n"); + /* + * We read in some system nodes to do not allow + * reclaim them and to have everytime access to them. + */ { - i = NTFS_MFTINO; - 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]); - vput(ntmp->ntm_sysvn[i]); + int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO }; + for (i=0; i<3; i++) { + error = VFS_VGET(mp, pi[i], &(ntmp->ntm_sysvn[pi[i]])); + if(error) + goto out1; + ntmp->ntm_sysvn[pi[i]]->v_flag |= VSYSTEM; + VREF(ntmp->ntm_sysvn[pi[i]]); + vput(ntmp->ntm_sysvn[pi[i]]); + } } - MALLOC( ntmp->ntm_upcase, wchar *, 65536 * sizeof(wchar), + /* + * Read in WHOLE lowcase -> upcase translation + * file. + */ + MALLOC(ntmp->ntm_upcase, wchar *, 65536 * sizeof(wchar), M_NTFSMNT, M_WAITOK); - printf("ntfs_mountfs(): opening $UpCase\n"); - error = VFS_VGET(mp, NTFS_UPCASEINO, &vp ); + error = VFS_VGET(mp, NTFS_UPCASEINO, &vp); if(error) goto out1; - printf("ntfs_mountfs(): reading $UpCase\n"); - error = ntfs_readattr( 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); if(error) goto out1; + /* + * Scan $BitMap and count free clusters + */ + error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree); + if(error) + goto out1; + + /* + * Read and translate to internal format attribute + * definition file. + */ { int num,j; struct attrdef ad; - printf("ntfs_mountfs(): opening $AttrDef\n"); + /* Open $AttrDef */ error = VFS_VGET(mp, NTFS_ATTRDEFINO, &vp ); if(error) goto out1; + /* Count valid entries */ for(num=0;;num++) { error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, @@ -461,14 +473,15 @@ ntfs_mountfs(devvp, mp, argsp, p) if (ad.ad_name[0] == 0) break; } - printf("ntfs_mountfs(): reading %d attrdefs\n",num); + /* Alloc memory for attribute definitions */ MALLOC(ntmp->ntm_ad, struct ntvattrdef *, num * sizeof(struct ntvattrdef), M_NTFSMNT, M_WAITOK); ntmp->ntm_adnum = num; + /* Read them and translate */ for(i=0;intm_ad[i].ad_namelen = j - 1; ntmp->ntm_ad[i].ad_type = ad.ad_type; - printf("ntfs_mountfs(): attribute: %s, type: 0x%x\n", - ntmp->ntm_ad[i].ad_name, - ntmp->ntm_ad[i].ad_type); } - printf("ntfs_mountfs(): closing $AttrDef\n"); + vput(vp); } @@ -504,9 +514,14 @@ ntfs_mountfs(devvp, mp, argsp, p) devvp->v_specflags |= SI_MOUNTEDON; #endif return (0); + out1: for(i=0;intm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); + + if (vflush(mp,NULLVP,0)) + printf("ntfs_mountfs: vflush failed\n"); + out: #if __FreeBSD_version >= 300000 devvp->v_specmountpoint = NULL; @@ -525,7 +540,6 @@ ntfs_start ( int flags, struct proc *p ) { - printf("\nntfs_start():\n"); return (0); } @@ -538,24 +552,33 @@ ntfs_unmount( register struct ntfsmount *ntmp; int error, ronly = 0, flags, i; - printf("ntfs_unmount: unmounting...\n"); + dprintf(("ntfs_unmount: unmounting...\n")); ntmp = VFSTONTFS(mp); flags = 0; if(mntflags & MNT_FORCE) flags |= FORCECLOSE; - printf("ntfs_unmount: vflushing...\n"); + dprintf(("ntfs_unmount: vflushing...\n")); error = vflush(mp,NULLVP,flags | SKIPSYSTEM); if (error) { printf("ntfs_unmount: vflush failed: %d\n",error); return (error); } + + /* Check if only system vnodes are rest */ + for(i=0;intm_sysvn[i]) && + (ntmp->ntm_sysvn[i]->v_usecount > 1)) return (EBUSY); + + /* Derefernce all system vnodes */ for(i=0;intm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); + + /* vflush system vnodes */ error = vflush(mp,NULLVP,flags); if (error) - printf("ntfs_unmount: vflush failed: %d\n",error); + printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error); #if __FreeBSD_version >= 300000 ntmp->ntm_devvp->v_specmountpoint = NULL; @@ -573,7 +596,7 @@ ntfs_unmount( vrele(ntmp->ntm_devvp); - printf("ntfs_umount: freeing memory...\n"); + dprintf(("ntfs_umount: freeing memory...\n")); mp->mnt_data = (qaddr_t)0; mp->mnt_flag &= ~MNT_LOCAL; FREE(ntmp->ntm_ad, M_NTFSMNT); @@ -614,6 +637,41 @@ ntfs_quotactl ( return EOPNOTSUPP; } +int +ntfs_calccfree( + struct ntfsmount *ntmp, + cn_t *cfreep) +{ + struct vnode *vp; + u_int8_t *tmp; + int j, error; + long cfree = 0; + size_t bmsize, i; + + vp = ntmp->ntm_sysvn[NTFS_BITMAPINO]; + + bmsize = VTOF(vp)->f_size; + + 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); + } + + for(i=0;intm_sysvn[NTFS_MFTINO]), - &mftsize, &mftallocated); - - error = VFS_VGET(mp, NTFS_BITMAPINO, &vp); - if(error) - return (error); - - ntfs_filesize(ntmp, VTOF(vp), &bmsize, &bmallocated); - - 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); - vput(vp); - return (error); - } - vput(vp); - - sbp->f_bfree = 0; - for(i=0;if_bfree++; - - FREE(tmp, M_TEMP); + mftsize = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_size; + mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated; #if __FreeBSD_version >= 300000 sbp->f_type = mp->mnt_vfc->vfc_typenum; @@ -663,7 +694,7 @@ ntfs_statfs( sbp->f_bsize = ntmp->ntm_bps; sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc; sbp->f_blocks = ntmp->ntm_bootfile.bf_spv; - sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(sbp->f_bfree); + sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree); sbp->f_ffree = sbp->f_bfree / ntmp->ntm_bpmftrec; sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) + sbp->f_ffree; @@ -746,41 +777,63 @@ ntfs_vgetex( *vpp = NULL; /* Get ntnode */ - error = ntfs_ntget(ntmp, ino, &ip); + error = ntfs_ntlookup(ntmp, ino, &ip); if (error) { printf("ntfs_vget: ntfs_ntget failed\n"); return (error); } + /* It may be not initialized fully, so force load it */ + if (!(flags & VG_DONTLOADIN) && !(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_ntput(ip); + return (error); + } + } + error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp); if (error) { printf("ntfs_vget: ntfs_fget failed\n"); - ntfs_ntrele(ip); + ntfs_ntput(ip); return (error); } + 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; + } else { + fp->f_type = VREG; + + error = ntfs_filesize(ntmp, fp, + &fp->f_size, &fp->f_allocated); + if (error) { + ntfs_ntput(ip); + return (error); + } + } + + fp->f_flag |= FN_VALID; + } + if (FTOV(fp)) { vget(FTOV(fp), lkflags, p); *vpp = FTOV(fp); - ntfs_ntrele(ip); + ntfs_ntput(ip); return (0); } - /* 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 = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, &vp); if(error) { ntfs_frele(fp); - ntfs_ntrele(ip); + ntfs_ntput(ip); return (error); } dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino)); @@ -788,18 +841,12 @@ ntfs_vgetex( 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; + vp->v_type = fp->f_type; if (ino == NTFS_ROOTINO) vp->v_flag |= VROOT; - if (ino < NTFS_SYSNODESNUM) - vp->v_flag |= VSYSTEM; - ntfs_ntrele(ip); + ntfs_ntput(ip); if (lkflags & LK_TYPE_MASK) { error = vn_lock(vp, lkflags, p); diff --git a/sys/ntfs/ntfs_vfsops.h b/sys/ntfs/ntfs_vfsops.h index c8788c480be4..af5ce9d7e135 100644 --- a/sys/ntfs/ntfs_vfsops.h +++ b/sys/ntfs/ntfs_vfsops.h @@ -25,9 +25,13 @@ * * $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 */ +#define VG_DONTLOADIN 0x0001 /* Tells ntfs_vgetex to do not call */ /* ntfs_loadnode on ntnode, even if */ /* ntnode not loaded */ +#define VG_DONTVALIDFN 0x0002 /* Tells ntfs_vgetex to do not validate */ + /* fnode */ +#define VG_EXT 0x0004 /* This is not main record */ int ntfs_vgetex(struct mount *, ino_t, u_int32_t, char *, u_long, u_long, struct proc *, struct vnode **); +int ntfs_calccfree(struct ntfsmount *, cn_t *); diff --git a/sys/ntfs/ntfs_vnops.c b/sys/ntfs/ntfs_vnops.c index f1a822a5935c..d22ea5fa80a3 100644 --- a/sys/ntfs/ntfs_vnops.c +++ b/sys/ntfs/ntfs_vnops.c @@ -156,7 +156,8 @@ 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, fp, &toread, NULL); + toread = fp->f_size; + dprintf(("ntfs_read: filesize: %d",(u_int32_t)toread)); toread = min( uio->uio_resid, toread - uio->uio_offset ); @@ -165,7 +166,7 @@ ntfs_read(ap) MALLOC(data, u_int8_t *, toread, M_TEMP,M_WAITOK); - error = ntfs_readattr( ntmp, ip, fp->f_attrtype, + error = ntfs_readattr(ntmp, ip, fp->f_attrtype, fp->f_attrname, uio->uio_offset, toread, data); if(error) { printf("ntfs_read: ntfs_readattr failed: %d\n",error); @@ -245,9 +246,7 @@ ntfs_inactive(ap) } */ *ap; { register struct vnode *vp = ap->a_vp; -#if defined(NTFS_DEBUG) || defined(DISGNOSTIC) register struct ntnode *ip = VTONT(vp); -#endif int error; dprintf(("ntfs_inactive: vnode: %p, ntnode: %d\n", vp, ip->i_number)); @@ -262,7 +261,7 @@ ntfs_inactive(ap) #else #ifdef DIAGNOSTIC if (VOP_ISLOCKED(vp)) - panic("ntfs_inactive: locked ntnode"); + panic("ntfs_inactive: locked vnode"); if (curproc) ip->i_lockholder = curproc->p_pid; else @@ -275,7 +274,7 @@ ntfs_inactive(ap) * If we are done with the ntnode, reclaim it * so that it can be reused immediately. */ - if (vp->v_usecount == 0 /*&& ip->i_mode == 0*/) + if (vp->v_usecount == 0 && ip->i_mode == 0) #if __FreeBSD_version >= 300000 vrecycle(vp, (struct simplelock *)0, ap->a_p); #else @@ -295,12 +294,15 @@ ntfs_reclaim(ap) { register struct vnode *vp = ap->a_vp; register struct fnode *fp = VTOF(vp); -#if NTFS_DEBUG register struct ntnode *ip = FTONT(fp); -#endif + int error; dprintf(("ntfs_reclaim: vnode: %p, ntnode: %d\n", vp, ip->i_number)); + error = ntfs_ntget(ip); + if (error) + return (error); + #if __FreeBSD_version >= 300000 VOP_UNLOCK(vp,0,ap->a_p); #endif @@ -316,6 +318,8 @@ ntfs_reclaim(ap) vp->v_data = NULL; + ntfs_ntput(ip); + return (0); } @@ -428,15 +432,15 @@ ntfs_write(ap) 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)); - ntfs_filesize(ntmp, fp, &towrite, NULL); + 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"); return (EFBIG); } - dprintf(("ntfs_write: filesize: %d",(u_int32_t)towrite)); - towrite = min(uio->uio_resid, towrite - uio->uio_offset); off = uio->uio_offset; @@ -948,7 +952,7 @@ ntfs_lookup(ap) } return (error); } else { - error = ntfs_ntlookup(ntmp, dvp, cnp, ap->a_vpp); + error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp); if(error) return (error); @@ -961,6 +965,8 @@ ntfs_lookup(ap) #else VOP_UNLOCK(dvp); #endif + if (cnp->cn_flags & MAKEENTRY) + cache_enter(dvp, *ap->a_vpp, cnp); } return (error);