#include <sys/param.h>
#include <ufs/ffs/fs.h>
#ifdef _KERNEL
#include <sys/systm.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/buf.h>
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/ufs_extern.h>
#include <ufs/ffs/ffs_extern.h>
int
ffs_bufatoff(struct inode *ip, off_t offset, char **res, struct buf **bpp)
{
struct fs *fs;
struct vnode *vp;
struct buf *bp;
daddr_t lbn;
int bsize, error;
vp = ITOV(ip);
fs = ip->i_fs;
lbn = lblkno(fs, offset);
bsize = blksize(fs, ip, lbn);
*bpp = NULL;
if ((error = bread(vp, lbn, fs->fs_bsize, &bp)) != 0) {
brelse(bp);
return (error);
}
buf_adjcnt(bp, bsize);
if (res)
*res = (char *)bp->b_data + blkoff(fs, offset);
*bpp = bp;
return (0);
}
#else
void ffs_fragacct(struct fs *, int, int32_t[], int);
int ffs_isfreeblock(struct fs *, u_char *, daddr_t);
int ffs_isblock(struct fs *, u_char *, daddr_t);
void ffs_clrblock(struct fs *, u_char *, daddr_t);
void ffs_setblock(struct fs *, u_char *, daddr_t);
__dead void panic(const char *, ...);
#endif
void
ffs_fragacct(struct fs *fs, int fragmap, int32_t fraglist[], int cnt)
{
int inblk;
int field, subfield;
int siz, pos;
inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
fragmap <<= 1;
for (siz = 1; siz < fs->fs_frag; siz++) {
if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
continue;
field = around[siz];
subfield = inside[siz];
for (pos = siz; pos <= fs->fs_frag; pos++) {
if ((fragmap & field) == subfield) {
fraglist[siz] += cnt;
pos += siz;
field <<= siz;
subfield <<= siz;
}
field <<= 1;
subfield <<= 1;
}
}
}
int
ffs_isblock(struct fs *fs, u_char *cp, daddr_t h)
{
u_char mask;
switch (fs->fs_frag) {
default:
case 8:
return (cp[h] == 0xff);
case 4:
mask = 0x0f << ((h & 0x1) << 2);
return ((cp[h >> 1] & mask) == mask);
case 2:
mask = 0x03 << ((h & 0x3) << 1);
return ((cp[h >> 2] & mask) == mask);
case 1:
mask = 0x01 << (h & 0x7);
return ((cp[h >> 3] & mask) == mask);
}
}
void
ffs_clrblock(struct fs *fs, u_char *cp, daddr_t h)
{
switch (fs->fs_frag) {
default:
case 8:
cp[h] = 0;
return;
case 4:
cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
return;
case 2:
cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
return;
case 1:
cp[h >> 3] &= ~(0x01 << (h & 0x7));
return;
}
}
void
ffs_setblock(struct fs *fs, u_char *cp, daddr_t h)
{
switch (fs->fs_frag) {
default:
case 8:
cp[h] = 0xff;
return;
case 4:
cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
return;
case 2:
cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
return;
case 1:
cp[h >> 3] |= (0x01 << (h & 0x7));
return;
}
}
int
ffs_isfreeblock(struct fs *fs, u_char *cp, daddr_t h)
{
switch (fs->fs_frag) {
default:
case 8:
return (cp[h] == 0);
case 4:
return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0);
case 2:
return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0);
case 1:
return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0);
}
}
#ifdef _KERNEL
int
ffs_vinit(struct mount *mntp, struct vnode **vpp)
{
struct inode *ip;
struct vnode *vp, *nvp;
struct timeval mtv;
vp = *vpp;
ip = VTOI(vp);
switch(vp->v_type = IFTOVT(DIP(ip, mode))) {
case VCHR:
case VBLK:
vp->v_op = &ffs_specvops;
if ((nvp = checkalias(vp, DIP(ip, rdev), mntp)) != NULL) {
nvp->v_data = vp->v_data;
vp->v_data = NULL;
vp->v_op = &spec_vops;
#ifdef VFSLCKDEBUG
vp->v_flag &= ~VLOCKSWORK;
#endif
vrele(vp);
vgone(vp);
vp = nvp;
ip->i_vnode = vp;
}
break;
case VFIFO:
#ifdef FIFO
vp->v_op = &ffs_fifovops;
break;
#else
return (EOPNOTSUPP);
#endif
case VNON:
case VBAD:
case VSOCK:
case VLNK:
case VDIR:
case VREG:
break;
}
if (ip->i_number == ROOTINO)
vp->v_flag |= VROOT;
getmicrouptime(&mtv);
ip->i_modrev = (u_quad_t)mtv.tv_sec << 32;
ip->i_modrev |= (u_quad_t)mtv.tv_usec * 4294;
*vpp = vp;
return (0);
}
#endif