summaryrefslogtreecommitdiffstats
path: root/sys/ntfs/ntfs_vfsops.c
diff options
context:
space:
mode:
authorsemenu <semenu@FreeBSD.org>1999-04-20 21:06:44 +0000
committersemenu <semenu@FreeBSD.org>1999-04-20 21:06:44 +0000
commit42e01703dca788bba764956ba12647f3dcdd7ec9 (patch)
tree94575bff8659b4709ed4f7205ce68df7fce0790e /sys/ntfs/ntfs_vfsops.c
parentc8cbbb76c7dbcc506d7786d8a80159d227b2cf4c (diff)
downloadFreeBSD-src-42e01703dca788bba764956ba12647f3dcdd7ec9.zip
FreeBSD-src-42e01703dca788bba764956ba12647f3dcdd7ec9.tar.gz
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!
Diffstat (limited to 'sys/ntfs/ntfs_vfsops.c')
-rw-r--r--sys/ntfs/ntfs_vfsops.c225
1 files changed, 136 insertions, 89 deletions
diff --git a/sys/ntfs/ntfs_vfsops.c b/sys/ntfs/ntfs_vfsops.c
index a371319..7d1f91d 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;i<num;i++){
error = ntfs_readattr(ntmp, VTONT(vp),
NTFS_A_DATA, NULL,
@@ -482,11 +495,8 @@ ntfs_mountfs(devvp, mp, argsp, p)
} while(ad.ad_name[j++]);
ntmp->ntm_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;i<NTFS_SYSNODESNUM;i++)
if(ntmp->ntm_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;i<NTFS_SYSNODESNUM;i++)
+ if((ntmp->ntm_sysvn[i]) &&
+ (ntmp->ntm_sysvn[i]->v_usecount > 1)) return (EBUSY);
+
+ /* Derefernce all system vnodes */
for(i=0;i<NTFS_SYSNODESNUM;i++)
if(ntmp->ntm_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,47 +637,55 @@ ntfs_quotactl (
return EOPNOTSUPP;
}
-static int
-ntfs_statfs(
- struct mount *mp,
- struct statfs *sbp,
- struct proc *p)
+int
+ntfs_calccfree(
+ struct ntfsmount *ntmp,
+ cn_t *cfreep)
{
- struct ntfsmount *ntmp = VFSTONTFS(mp);
- u_int64_t mftsize,mftallocated,bmsize,bmallocated;
struct vnode *vp;
- int error,j,i;
u_int8_t *tmp;
+ int j, error;
+ long cfree = 0;
+ size_t bmsize, i;
- dprintf(("ntfs_statfs():"));
-
- ntfs_filesize(ntmp, VTOF(ntmp->ntm_sysvn[NTFS_MFTINO]),
- &mftsize, &mftallocated);
-
- error = VFS_VGET(mp, NTFS_BITMAPINO, &vp);
- if(error)
- return (error);
+ vp = ntmp->ntm_sysvn[NTFS_BITMAPINO];
- ntfs_filesize(ntmp, VTOF(vp), &bmsize, &bmallocated);
+ bmsize = VTOF(vp)->f_size;
- MALLOC(tmp, u_int8_t *, bmsize,M_TEMP, M_WAITOK);
+ 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;i<bmsize;i++)
for(j=0;j<8;j++)
- if(~tmp[i] & (1 << j)) sbp->f_bfree++;
+ if(~tmp[i] & (1 << j)) cfree++;
FREE(tmp, M_TEMP);
+ *cfreep = cfree;
+
+ return(0);
+}
+
+static int
+ntfs_statfs(
+ struct mount *mp,
+ struct statfs *sbp,
+ struct proc *p)
+{
+ struct ntfsmount *ntmp = VFSTONTFS(mp);
+ u_int64_t mftsize,mftallocated;
+
+ dprintf(("ntfs_statfs():\n"));
+
+ 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;
#else
@@ -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);
OpenPOWER on IntegriCloud