Annotation of Net2/pcfs/pcfs_vfsops.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *  Written by Paul Popelka ([email protected])
                      3:  *
                      4:  *  You can do anything you want with this software,
                      5:  *    just don't say you wrote it,
                      6:  *    and don't remove this notice.
                      7:  *
                      8:  *  This software is provided "as is".
                      9:  *
                     10:  *  The author supplies this software to be publicly
                     11:  *  redistributed on the understanding that the author
                     12:  *  is not responsible for the correct functioning of
                     13:  *  this software in any circumstances and is not liable
                     14:  *  for any damages caused by this software.
                     15:  *
                     16:  *  October 1992
                     17:  *
                     18:  *  April 6, 1993:
                     19:  *     Changed MOUNT_PCFS to MOUNT_MSDOS, this whole package should be renamed
                     20:  *     to msdosfs, but I did not have the time to do it.  Some one please do
                     21:  *     this and resubmit it to the patchkit!
                     22:  *     Rodney W. Grimes
                     23:  *
                     24:  *     pcfs_vfsops.c,v 1.4.2.1 1993/08/05 02:37:21 cgd Exp
                     25:  */
                     26: 
                     27: #include "param.h"
                     28: #include "systm.h"
                     29: #include "namei.h"
                     30: #include "proc.h"
                     31: #include "kernel.h"
                     32: #include "vnode.h"
                     33: #include "specdev.h"   /* defines v_rdev       */
                     34: #include "mount.h"
                     35: #include "buf.h"
                     36: #include "file.h"
                     37: #include "malloc.h"
                     38: 
                     39: #include "bpb.h"
                     40: #include "bootsect.h"
                     41: #include "direntry.h"
                     42: #include "denode.h"
                     43: #include "pcfsmount.h"
                     44: #include "fat.h"
                     45: 
                     46: int pcfsdoforce = 0;   /* 1 = force unmount */
                     47: 
                     48: /*
                     49:  *  mp -
                     50:  *  path - addr in user space of mount point (ie /usr or whatever)
                     51:  *  data - addr in user space of mount params including the
                     52:  *         name of the block special file to treat as a filesystem.
                     53:  *  ndp  - 
                     54:  *  p    -
                     55:  */
                     56: int
                     57: pcfs_mount(mp, path, data, ndp, p)
                     58:        struct mount *mp;
                     59:        char *path;
                     60:        caddr_t data;
                     61:        struct nameidata *ndp;
                     62:        struct proc *p;
                     63: {
                     64:        struct vnode *devvp;    /* vnode for blk device to mount        */
                     65:        struct pcfs_args args;  /* will hold data from mount request    */
                     66:        struct pcfsmount *pmp;  /* pcfs specific mount control block    */
                     67:        int error;
                     68:        u_int size;
                     69: 
                     70: /*
                     71:  *  Copy in the args for the mount request.
                     72:  */
                     73:        if (error = copyin(data, (caddr_t)&args, sizeof(struct pcfs_args)))
                     74:                return error;
                     75: 
                     76: /*
                     77:  *  Check to see if they want it to be an exportable
                     78:  *  filesystem via nfs.  And, if they do, should it
                     79:  *  be read only, and what uid is root to be mapped
                     80:  *  to.
                     81:  */
                     82:        if ((args.exflags & MNT_EXPORTED)  ||  (mp->mnt_flag & MNT_EXPORTED)) {
                     83:                if (args.exflags & MNT_EXPORTED)
                     84:                        mp->mnt_flag |= MNT_EXPORTED;
                     85:                else
                     86:                        mp->mnt_flag &= ~MNT_EXPORTED;
                     87:                if (args.exflags & MNT_EXRDONLY)
                     88:                        mp->mnt_flag |= MNT_EXRDONLY;
                     89:                else
                     90:                        mp->mnt_flag &= ~MNT_EXRDONLY;
                     91:                mp->mnt_exroot = args.exroot;
                     92:        }
                     93: 
                     94: /*
                     95:  *  If they just want to update then be sure we can
                     96:  *  do what is asked.  Can't change a filesystem from
                     97:  *  read/write to read only.  Why?
                     98:  *  And if they've supplied a new device file name then we
                     99:  *  continue, otherwise return.
                    100:  */
                    101:        if (mp->mnt_flag & MNT_UPDATE) {
                    102:                pmp = (struct pcfsmount *)mp->mnt_data;
                    103:                if (pmp->pm_ronly  &&  (mp->mnt_flag & MNT_RDONLY) == 0)
                    104:                        pmp->pm_ronly = 0;
                    105:                if (args.fspec == 0)
                    106:                        return 0;
                    107:        }
                    108: 
                    109: /*
                    110:  *  Now, lookup the name of the block device this
                    111:  *  mount or name update request is to apply to.
                    112:  */
                    113:        ndp->ni_nameiop = LOOKUP | FOLLOW;
                    114:        ndp->ni_segflg  = UIO_USERSPACE;
                    115:        ndp->ni_dirp    = args.fspec;
                    116:        if (error = namei(ndp, p))
                    117:                return error;
                    118: 
                    119: /*
                    120:  *  Be sure they've given us a block device to treat
                    121:  *  as a filesystem.  And, that its major number is
                    122:  *  within the bdevsw table.
                    123:  */
                    124:        devvp = ndp->ni_vp;
                    125:        if (devvp->v_type != VBLK) {
                    126:                vrele(devvp);           /* namei() acquires this?       */
                    127:                return ENOTBLK;
                    128:        }
                    129:        if (major(devvp->v_rdev) >= nblkdev) {
                    130:                vrele(devvp);
                    131:                return ENXIO;
                    132:        }
                    133: 
                    134: /*
                    135:  *  If this is an update, then make sure the vnode
                    136:  *  for the block special device is the same as the
                    137:  *  one our filesystem is in.
                    138:  */
                    139:        if (mp->mnt_flag & MNT_UPDATE) {
                    140:                if (devvp != pmp->pm_devvp)
                    141:                        error = EINVAL;
                    142:                else
                    143:                        vrele(devvp);
                    144:        } else {
                    145: 
                    146: /*
                    147:  *  Well, it's not an update, it's a real mount request.
                    148:  *  Time to get dirty.
                    149:  */
                    150:                error = mountpcfs(devvp, mp, p);
                    151:        }
                    152:        if (error) {
                    153:                vrele(devvp);
                    154:                return error;
                    155:        }
                    156: 
                    157: /*
                    158:  *  Copy in the name of the directory the filesystem
                    159:  *  is to be mounted on.
                    160:  *  Then copy in the name of the block special file
                    161:  *  representing the filesystem being mounted.
                    162:  *  And we clear the remainder of the character strings
                    163:  *  to be tidy.
                    164:  *  Then, we try to fill in the filesystem stats structure
                    165:  *  as best we can with whatever applies from a dos file
                    166:  *  system.
                    167:  */
                    168:        pmp = (struct pcfsmount *)mp->mnt_data;
                    169:        copyinstr(path, (caddr_t)mp->mnt_stat.f_mntonname,
                    170:                sizeof(mp->mnt_stat.f_mntonname)-1, &size);
                    171:        bzero(mp->mnt_stat.f_mntonname + size,
                    172:                sizeof(mp->mnt_stat.f_mntonname) - size);
                    173:        copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN-1, &size);
                    174:        bzero(mp->mnt_stat.f_mntfromname + size,
                    175:                MNAMELEN - size);
                    176:        (void)pcfs_statfs(mp, &mp->mnt_stat, p);
                    177: #if defined(PCFSDEBUG)
                    178: printf("pcfs_mount(): mp %x, pmp %x, inusemap %x\n", mp, pmp, pmp->pm_inusemap);
                    179: #endif /* defined(PCFSDEBUG) */
                    180:        return 0;
                    181: }
                    182: 
                    183: int
                    184: mountpcfs(devvp, mp, p)
                    185:        struct vnode *devvp;
                    186:        struct mount *mp;
                    187:        struct proc *p;
                    188: {
                    189:        int i;
                    190:        u_long bpc;
                    191:        int bit;
                    192:        int error = 0;
                    193:        int needclose;
                    194:        int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
                    195:        dev_t dev = devvp->v_rdev;
                    196:        union bootsector *bsp;
                    197:        struct pcfsmount *pmp = NULL;
                    198:        struct buf *bp0 = NULL;
                    199:        struct byte_bpb33 *b33;
                    200:        struct byte_bpb50 *b50;
                    201: 
                    202: /*
                    203:  *  Multiple mounts of the same block special file
                    204:  *  aren't allowed.  Make sure no one else has the
                    205:  *  special file open.  And flush any old buffers
                    206:  *  from this filesystem.  Presumably this prevents
                    207:  *  us from running into buffers that are the wrong
                    208:  *  blocksize.
                    209:  *  NOTE: mountedon() is a part of the ufs filesystem.
                    210:  *  If the ufs filesystem is not gen'ed into the system
                    211:  *  we will get an unresolved reference.
                    212:  */
                    213:        if (error = mountedon(devvp))
                    214:                return error;
                    215:        if (vcount(devvp) > 1)
                    216:                return EBUSY;
                    217:        vinvalbuf(devvp, 1);
                    218: 
                    219: /*
                    220:  *  Now open the block special file.
                    221:  */
                    222:        if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p))
                    223:                return error;
                    224:        needclose = 1;
                    225: 
                    226: /*
                    227:  *  Read the boot sector of the filesystem, and then
                    228:  *  check the boot signature.  If not a dos boot sector
                    229:  *  then error out.  We could also add some checking on
                    230:  *  the bsOemName field.  So far I've seen the following
                    231:  *  values:
                    232:  *    "IBM  3.3"
                    233:  *    "MSDOS3.3"
                    234:  *    "MSDOS5.0"
                    235:  */
                    236:        if (error = bread(devvp, 0, 512, NOCRED, &bp0))
                    237:                goto error_exit;
                    238:        bp0->b_flags |= B_AGE;
                    239:        bsp = (union bootsector *)bp0->b_un.b_addr;
                    240:        b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB;
                    241:        b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB;
                    242:        if (bsp->bs50.bsBootSectSig != BOOTSIG) {
                    243:                error = EINVAL;
                    244:                goto error_exit;
                    245:        }
                    246: 
                    247:        pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK);
                    248:        pmp->pm_inusemap = NULL;
                    249:        pmp->pm_mountp = mp;
                    250: 
                    251: /*
                    252:  *  Compute several useful quantities from the bpb in
                    253:  *  the bootsector.  Copy in the dos 5 variant of the
                    254:  *  bpb then fix up the fields that are different between
                    255:  *  dos 5 and dos 3.3.
                    256:  */
                    257:        pmp->pm_BytesPerSec  = getushort(b50->bpbBytesPerSec);
                    258:        pmp->pm_SectPerClust = b50->bpbSecPerClust;
                    259:        pmp->pm_ResSectors   = getushort(b50->bpbResSectors);
                    260:        pmp->pm_FATs         = b50->bpbFATs;
                    261:        pmp->pm_RootDirEnts  = getushort(b50->bpbRootDirEnts);
                    262:        pmp->pm_Sectors      = getushort(b50->bpbSectors);
                    263:        pmp->pm_Media        = b50->bpbMedia;
                    264:        pmp->pm_FATsecs      = getushort(b50->bpbFATsecs);
                    265:        pmp->pm_SecPerTrack  = getushort(b50->bpbSecPerTrack);
                    266:        pmp->pm_Heads        = getushort(b50->bpbHeads);
                    267:        if (pmp->pm_Sectors == 0) {
                    268:                pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
                    269:                pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);
                    270:        } else {
                    271:                pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs);
                    272:                pmp->pm_HugeSectors = pmp->pm_Sectors;
                    273:        }
                    274:        pmp->pm_fatblk = pmp->pm_ResSectors;
                    275:        pmp->pm_rootdirblk = pmp->pm_fatblk +
                    276:                (pmp->pm_FATs * pmp->pm_FATsecs);
                    277:        pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry))
                    278:                                        /
                    279:                                pmp->pm_BytesPerSec; /* in sectors */
                    280:        pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;
                    281:        pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) /
                    282:                pmp->pm_SectPerClust;
                    283:        pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1;
                    284:        pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec;
                    285:        if (FAT12(pmp))
                    286:                /* This will usually be a floppy disk.
                    287:                 * This size makes sure that one fat entry will not be split
                    288:                 * across multiple blocks. */
                    289:                pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec;
                    290:        else
                    291:                /* This will usually be a hard disk.
                    292:                 * Reading or writing one block should be quite fast. */
                    293:                pmp->pm_fatblocksize = MAXBSIZE;
                    294:        pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec;
                    295:                
                    296:        if ((pmp->pm_rootdirsize % pmp->pm_SectPerClust) != 0)
                    297:                printf("mountpcfs(): root directory is not a multiple of the clustersize in length\n");
                    298: 
                    299: /*
                    300:  *  Compute mask and shift value for isolating cluster relative
                    301:  *  byte offsets and cluster numbers from a file offset.
                    302:  */
                    303:        bpc = pmp->pm_SectPerClust * pmp->pm_BytesPerSec;
                    304:        if (!bpc || (bpc & (bpc - 1))) {
                    305:                error = EINVAL;
                    306:                goto error_exit;
                    307:        }
                    308:        pmp->pm_bpcluster = bpc;
                    309:        pmp->pm_depclust  = bpc/sizeof(struct direntry);
                    310:        pmp->pm_crbomask = bpc - 1;
                    311:        pmp->pm_cnshift = ffs(bpc) - 1;
                    312: 
                    313:        pmp->pm_brbomask = 0x01ff;      /* 512 byte blocks only (so far) */
                    314:        pmp->pm_bnshift = 9;            /* shift right 9 bits to get bn */
                    315: 
                    316: /*
                    317:  *  Release the bootsector buffer.
                    318:  */
                    319:        brelse(bp0);
                    320:        bp0 = NULL;
                    321: 
                    322: /*
                    323:  *  Allocate memory for the bitmap of allocated clusters,
                    324:  *  and then fill it in.
                    325:  */
                    326:        pmp->pm_inusemap = malloc((pmp->pm_maxcluster / 8) + 1,
                    327:                M_MSDOSFSFAT, M_WAITOK);
                    328: 
                    329: /*
                    330:  *  fillinusemap() needs pm_devvp.
                    331:  */
                    332:        pmp->pm_dev = dev;
                    333:        pmp->pm_devvp = devvp;
                    334: 
                    335: /*
                    336:  *  Have the inuse map filled in.
                    337:  */
                    338:        error = fillinusemap(pmp);
                    339:        if (error)
                    340:                goto error_exit;
                    341: 
                    342: /*
                    343:  *  If they want fat updates to be synchronous then let
                    344:  *  them suffer the performance degradation in exchange
                    345:  *  for the on disk copy of the fat being correct just
                    346:  *  about all the time.  I suppose this would be a good
                    347:  *  thing to turn on if the kernel is still flakey.
                    348:  */
                    349:        pmp->pm_waitonfat = mp->mnt_flag & MNT_SYNCHRONOUS;
                    350: 
                    351: /*
                    352:  *  Finish up.
                    353:  */
                    354:        pmp->pm_ronly = ronly;
                    355:        if (ronly == 0)
                    356:                pmp->pm_fmod = 1;
                    357:        mp->mnt_data = (qaddr_t)pmp;
                    358:        mp->mnt_stat.f_fsid.val[0] = (long)dev;
                    359:        mp->mnt_stat.f_fsid.val[1] = MOUNT_MSDOS;
                    360:        mp->mnt_flag |= MNT_LOCAL;
                    361: #if defined(QUOTA)
                    362: /*
                    363:  *  If we ever do quotas for DOS filesystems this would
                    364:  *  be a place to fill in the info in the pcfsmount
                    365:  *  structure.
                    366:  *  You dolt, quotas on dos filesystems make no sense
                    367:  *  because files have no owners on dos filesystems.
                    368:  *  of course there is some empty space in the directory
                    369:  *  entry where we could put uid's and gid's.
                    370:  */
                    371: #endif /* defined(QUOTA) */
                    372:        devvp->v_specflags |= SI_MOUNTEDON;
                    373: 
                    374:        return 0;
                    375: 
                    376: error_exit:;
                    377:        if (bp0)
                    378:                brelse(bp0);
                    379:        if (needclose)
                    380:                (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE,
                    381:                        NOCRED, p);
                    382:        if (pmp) {
                    383:                if (pmp->pm_inusemap)
                    384:                        free((caddr_t)pmp->pm_inusemap, M_MSDOSFSFAT);
                    385:                free((caddr_t)pmp, M_MSDOSFSMNT);
                    386:                mp->mnt_data = (qaddr_t)0;
                    387:        }
                    388:        return error;
                    389: }
                    390: 
                    391: int
                    392: pcfs_start(mp, flags, p)
                    393:        struct mount *mp;
                    394:        int flags;
                    395:        struct proc *p;
                    396: {
                    397:        return 0;
                    398: }
                    399: 
                    400: /*
                    401:  *  Unmount the filesystem described by mp.
                    402:  */
                    403: int
                    404: pcfs_unmount(mp, mntflags, p)
                    405:        struct mount *mp;
                    406:        int mntflags;
                    407:        struct proc *p;
                    408: {
                    409:        int flags = 0;
                    410:        int error;
                    411:        struct pcfsmount *pmp = (struct pcfsmount *)mp->mnt_data;
                    412:        struct vnode *vp = pmp->pm_devvp;
                    413: 
                    414:        if (mntflags & MNT_FORCE) {
                    415:                if (!pcfsdoforce)
                    416:                        return EINVAL;
                    417:                flags |= FORCECLOSE;
                    418:        }
                    419:        mntflushbuf(mp, 0);
                    420:        if (mntinvalbuf(mp))
                    421:                return EBUSY;
                    422: #if defined(QUOTA)
                    423: #endif /* defined(QUOTA) */
                    424:        if (error = vflush(mp, NULLVP, flags))
                    425:                return error;
                    426:        pmp->pm_devvp->v_specflags &= ~SI_MOUNTEDON;
                    427: #if defined(PCFSDEBUG)
                    428: printf("pcfs_umount(): just before calling VOP_CLOSE()\n");
                    429: printf("flag %08x, usecount %d, writecount %d, holdcnt %d\n",
                    430:        vp->v_flag, vp->v_usecount, vp->v_writecount, vp->v_holdcnt);
                    431: printf("lastr %d, id %d, mount %08x, op %08x\n",
                    432:        vp->v_lastr, vp->v_id, vp->v_mount, vp->v_op);
                    433: printf("freef %08x, freeb %08x, mountf %08x, mountb %08x\n",
                    434:        vp->v_freef, vp->v_freeb, vp->v_mountf, vp->v_mountb);
                    435: printf("cleanblkhd %08x, dirtyblkhd %08x, numoutput %d, type %d\n",
                    436:        vp->v_cleanblkhd, vp->v_dirtyblkhd, vp->v_numoutput, vp->v_type);
                    437: printf("union %08x, tag %d, data[0] %08x, data[1] %08x\n",
                    438:        vp->v_socket, vp->v_tag, vp->v_data[0], vp->v_data[1]);
                    439: #endif /* defined(PCFSDEBUG) */
                    440:        error = VOP_CLOSE(pmp->pm_devvp, pmp->pm_ronly ? FREAD : FREAD|FWRITE,
                    441:                NOCRED, p);
                    442:        vrele(pmp->pm_devvp);
                    443:        free((caddr_t)pmp->pm_inusemap, M_MSDOSFSFAT);
                    444:        free((caddr_t)pmp, M_MSDOSFSMNT);
                    445:        mp->mnt_data = (qaddr_t)0;
                    446:        mp->mnt_flag &= ~MNT_LOCAL;
                    447:        return error;
                    448: }
                    449: 
                    450: int
                    451: pcfs_root(mp, vpp)
                    452:        struct mount *mp;
                    453:        struct vnode **vpp;
                    454: {
                    455:        struct denode *ndep;
                    456:        struct pcfsmount *pmp = (struct pcfsmount *)(mp->mnt_data);
                    457:        int error;
                    458: 
                    459:        error = deget(pmp, PCFSROOT, PCFSROOT_OFS, NULL, &ndep);
                    460: #if defined(PCFSDEBUG)
                    461: printf("pcfs_root(); mp %08x, pmp %08x, ndep %08x, vp %08x\n",
                    462:  mp, pmp, ndep, DETOV(ndep));
                    463: #endif /* defined(PCFSDEBUG) */
                    464:        if (error == 0)
                    465:                *vpp = DETOV(ndep);
                    466:        return error;
                    467: }
                    468: 
                    469: int
                    470: pcfs_quotactl(mp, cmds, uid, arg, p)
                    471:        struct mount *mp;
                    472:        int cmds;
                    473:        uid_t uid;
                    474:        caddr_t arg;
                    475:        struct proc *p;
                    476: {
                    477: #if defined(QUOTA)
                    478: #else
                    479:        return EOPNOTSUPP;
                    480: #endif /* defined(QUOTA) */
                    481: }
                    482: 
                    483: int
                    484: pcfs_statfs(mp, sbp, p)
                    485:        struct mount *mp;
                    486:        struct statfs *sbp;
                    487:        struct proc *p;
                    488: {
                    489:        struct pcfsmount *pmp = (struct pcfsmount *)mp->mnt_data;
                    490: 
                    491: /*
                    492:  *  Fill in the stat block.
                    493:  */
                    494:        sbp->f_type   = MOUNT_MSDOS;
                    495:        sbp->f_fsize  = pmp->pm_bpcluster;
                    496:        sbp->f_bsize  = pmp->pm_bpcluster;
                    497:        sbp->f_blocks = pmp->pm_nmbrofclusters;
                    498:        sbp->f_bfree  = pmp->pm_freeclustercount;
                    499:        sbp->f_bavail = pmp->pm_freeclustercount;
                    500:        sbp->f_files  = pmp->pm_RootDirEnts;
                    501:        sbp->f_ffree  = 0;              /* what to put in here? */
                    502: 
                    503: /*
                    504:  *  Copy the mounted on and mounted from names into
                    505:  *  the passed in stat block, if it is not the one
                    506:  *  in the mount structure.
                    507:  */
                    508:        if (sbp != &mp->mnt_stat) {
                    509:                bcopy((caddr_t)mp->mnt_stat.f_mntonname,
                    510:                        (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
                    511:                bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
                    512:                        (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
                    513:        }
                    514:        return 0;
                    515: }
                    516: 
                    517: int
                    518: pcfs_sync(mp, waitfor)
                    519:        struct mount *mp;
                    520:        int waitfor;
                    521: {
                    522:        struct vnode *vp;
                    523:        struct denode *dep;
                    524:        struct pcfsmount *pmp;
                    525:        int error;
                    526:        int allerror = 0;
                    527: 
                    528:        pmp = (struct pcfsmount *)mp->mnt_data;
                    529: 
                    530: /*
                    531:  *  If we ever switch to not updating all of the fats
                    532:  *  all the time, this would be the place to update them
                    533:  *  from the first one.
                    534:  */
                    535:        if (pmp->pm_fmod) {
                    536:                if (pmp->pm_ronly) {
                    537:                        printf("pcfs_sync(): writing to readonly filesystem\n");
                    538:                        return EINVAL;
                    539:                } else {
                    540:                        /* update fats here */
                    541:                }
                    542:        }
                    543: 
                    544: /*
                    545:  *  Go thru in memory denodes and write them out along
                    546:  *  with unwritten file blocks.
                    547:  */
                    548: loop:
                    549:        for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) {
                    550:                if (vp->v_mount != mp)  /* not ours anymore     */
                    551:                        goto loop;
                    552:                if (VOP_ISLOCKED(vp))   /* file is busy         */
                    553:                        continue;
                    554:                dep = VTODE(vp);
                    555:                if ((dep->de_flag & DEUPD) == 0  &&  vp->v_dirtyblkhd == NULL)
                    556:                        continue;
                    557:                if (vget(vp))           /* not there anymore?   */
                    558:                        goto loop;
                    559:                if (vp->v_dirtyblkhd)   /* flush dirty file blocks */
                    560:                        vflushbuf(vp, 0);
                    561:                if ((dep->de_flag & DEUPD)  &&
                    562:                    (error = deupdat(dep, &time, 0)))
                    563:                        allerror = error;
                    564:                vput(vp);               /* done with this one   */
                    565:        }
                    566: 
                    567: /*
                    568:  *  Flush filesystem control info.
                    569:  */
                    570:        vflushbuf(pmp->pm_devvp, waitfor == MNT_WAIT ? B_SYNC : 0);
                    571:        return allerror;
                    572: }
                    573: 
                    574: int
                    575: pcfs_fhtovp (mp, fhp, vpp)
                    576:        struct mount *mp;
                    577:        struct fid *fhp;
                    578:        struct vnode **vpp;
                    579: {
                    580:        struct pcfsmount *pmp = (struct pcfsmount *)mp->mnt_data;
                    581:        struct defid *defhp = (struct defid *)fhp;
                    582:        struct denode *dep;
                    583:        int error;
                    584: 
                    585:        error = deget (pmp, defhp->defid_dirclust, defhp->defid_dirofs,
                    586:                        NULL, &dep);
                    587:        if (error)
                    588:                return (error);
                    589:        *vpp = DETOV (dep);
                    590:        return (0);
                    591: }
                    592: 
                    593: 
                    594: int
                    595: pcfs_vptofh (vp, fhp)
                    596:        struct vnode *vp;
                    597:        struct fid *fhp;
                    598: {
                    599:        struct denode *dep = VTODE(vp);
                    600:        struct defid *defhp = (struct defid *)fhp;
                    601: 
                    602:        defhp->defid_len = sizeof(struct defid);
                    603:        defhp->defid_dirclust = dep->de_dirclust;
                    604:        defhp->defid_dirofs = dep->de_diroffset;
                    605: /*     defhp->defid_gen = ip->i_gen; */
                    606:        return (0);
                    607: }
                    608: 
                    609: struct vfsops pcfs_vfsops = {
                    610:        pcfs_mount,
                    611:        pcfs_start,
                    612:        pcfs_unmount,
                    613:        pcfs_root,
                    614:        pcfs_quotactl,
                    615:        pcfs_statfs,
                    616:        pcfs_sync,
                    617:        pcfs_fhtovp,
                    618:        pcfs_vptofh,
                    619:        pcfs_init
                    620: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.