1
0
Files
irix-657m-src/irix/cmd/icrash_old/lib/libutil/buf.c
2022-09-29 17:59:04 +03:00

599 lines
16 KiB
C

#ident "$Header: /proj/irix6.5.7m/isms/irix/cmd/icrash_old/lib/libutil/RCS/buf.c,v 1.1 1999/05/25 19:19:20 tjm Exp $"
#define _KERNEL 1
#include <sys/types.h>
#include <sys/param.h>
#include <sys/var.h>
#include <sys/vnode.h>
#include <sys/pfdat.h>
#include <sys/buf.h>
#include <sys/sysmacros.h>
#include <sys/stream.h>
#include <stdio.h>
#include <errno.h>
#include "icrash.h"
extern int active;
extern int debug; /* Global debug flag */
extern struct var *varp; /* pointer to var structure */
extern buf_t *_hbuf; /* pointer to buffer hash table */
#define BHASH(d,b) \
((struct hbuf *)((unsigned)_hbuf + \
(((int)(d)+(int)(b))&varp->v_hmask) * sizeof (struct hbuf)))
#define GET_BUF(addr, buffp) GET_STRUCT(buf_t, addr, buffp, "buf")
#define GET_HBUF(addr, buffp) GET_STRUCT(struct hbuf, addr, buffp, "hbuf")
#ifndef IRIX5_3
extern cbucket_t *_cbucket; /* pointer to chunk hash table */
#define GET_CBUKET(addr, buffp) GET_STRUCT(cbucket_t, addr, buffp, "cbucket")
#define BKTSHFT 7
#define lbucket(BB) ((BB) >> BKTSHFT)
/*
* bkthash() -- Set bucket hash.
*/
cbucket_t *
bkthash(struct vnode *vp, unsigned start)
{
cbucket_t *bktp;
if (debug > 3) {
fprintf(stderr, "bkthash: vp=0x%x, start=%d\n", vp, start);
}
bktp = (cbucket_t*)((unsigned)_cbucket + ((vp->v_number +
lbucket(start)) & varp->v_hmask) * sizeof (cbucket_t));
if (debug > 4) {
fprintf(stderr, "bkthash: bktp=0x%x", bktp);
}
return (bktp);
}
#endif
/*
* find_chunk() -- Returns the kernel address of the buf struct for
* 'vnode' that starts at 'offset.' The contents of
* the found buf are placed in the buf struct pointed
* to by bufp.
*/
buf_t *
find_chunk(struct vnode *vn, unsigned offset, buf_t *bufp)
{
buf_t *bp, *bpp;
struct vnode *vp, vbuf, *get_vnode();
#ifndef IRIX5_3
cbucket_t *bktp, *cp, cbuf;
#endif
if (debug > 3) {
fprintf(stderr, "find_chunk: vn=0x%x, offset=%d, bufp=0x%x\n",
vn, offset, bufp);
}
if ((vp = get_vnode(vn, &vbuf)) == 0) {
if (debug) {
fprintf(stderr, "find_chunk: couldn't get vnode at 0x%x\n", vn);
}
return((buf_t *)0);
}
#ifdef IRIX5_3
bpp = vp->v_buf;
while (bpp) {
bp = GET_BUF(bpp, bufp);
/*
* See if offset is within buf range.
*/
if (bp->b_offset < offset) {
bp = bp->b_forw;
continue;
}
if (bp->b_offset > offset) {
bp = bp->b_back;
continue;
}
#else
if ((bktp = bkthash(vp, offset)) == 0) {
if (debug) {
fprintf(stderr,
"find_chunk: could not locate cbucket for 0x%x/%d\n",
vp, offset);
}
return((buf_t *)0);
}
if ((cp = GET_CBUKET(bktp, &cbuf)) == 0) {
if (debug) {
fprintf(stderr, "find_chunk: couldn't get cbucket at 0x%x\n",
bktp);
}
return((buf_t *)0);
}
bpp = cp->b_forw;
while (bpp != (buf_t *)bktp) {
bp = GET_BUF(bpp, bufp);
/*
* See if it's valid and matches exactly.
*/
if ((bp->b_flags & B_STALE) || (bp->b_vp != vn) ||
(bp->b_offset != offset)) {
bpp = bp->b_forw;
continue;
}
#endif
return (bpp);
}
return ((buf_t*)0);
}
/*
* find_buf() -- Find a buffer for device number (MAJOR/MINOR) and
* block number on device.
*/
buf_t *
find_buf(unsigned device, unsigned blkno, buf_t *bufp)
{
buf_t *bp, *bpp;
struct hbuf *bhashp, *bhp, bhbuf;
if (debug > 3) {
fprintf(stderr, "find_buf: device=0x%x, blkno=%d, bufp=0x%x\n",
device, blkno, bufp);
}
bhashp = BHASH(device, blkno >> BIO_BBSPERBUCKETSHIFT);
if ((bhp = GET_HBUF(bhashp, &bhbuf)) == 0) {
if (debug) {
fprintf(stderr, "find_buf: couldn't get hbuf at 0x%x\n",
bhashp);
}
return((buf_t *)0);
}
bpp = bhp->b_forw;
while (bpp != (buf_t *)bhashp) {
bp = GET_BUF(bpp, bufp);
/*
* See if it's valid and matches exactly.
*/
if ((bp->b_flags & B_STALE) || (bp->b_edev != device) ||
(bp->b_blkno != blkno)) {
bpp = bp->b_forw;
continue;
}
return (bpp);
}
return ((buf_t*)0);
}
/*
* dobuf() -- Print out the information in a buffer. This will also
* try to dump out the struct proc * / struct vnode *, if
* possible.
*/
int
dobuf(command_t cmd)
{
int i, buf_cnt = 0, firsttime = 1;
buf_t *bpp, *bp, *nbp, bbuf;
struct vnode *vn, *vp, vbuf;
fprintf(cmd.ofp, " BUF EDEV PROC/VP SIZE OFFSET BCOUNT FLAGS\n");
fprintf(cmd.ofp, "====================================================================\n");
for (i = 0; i < cmd.nargs; i++) {
bpp = (buf_t*)GET_VALUE(cmd.args[i]);
if (bp = GET_BUF(bpp, &bbuf)) {
if (debug > 1 || (cmd.flags & (C_FULL|C_NEXT))) {
if (!firsttime) {
fprintf (cmd.ofp, "\n");
fprintf (cmd.ofp, " BUF EDEV PROC/VP SIZE OFFSET BCOUNT FLAGS\n");
fprintf (cmd.ofp, "====================================================================\n");
} else {
firsttime = 0;
}
}
print_buf(bpp, bp, cmd.flags, cmd.ofp);
buf_cnt++;
if (cmd.flags & C_NEXT) {
buf_cnt += print_bufchain(bpp, bp,
((cmd.flags & C_AVAIL) ? 1 : 0), cmd.flags, cmd.ofp);
}
} else {
if (debug) {
fprintf(stderr, "Could not read buf at 0x%x\n", bpp);
}
continue;
}
}
fprintf (cmd.ofp, "====================================================================\n");
fprintf(cmd.ofp, "%d buf struct%s found\n",
buf_cnt, (buf_cnt != 1) ? "s" : "");
}
/* XXX -- Not finished */
int
dobfree(command_t cmd)
{
int i, buf_cnt = 0, firsttime = 1;
buf_t *bpp, *bp, *nbp, bbuf;
struct vnode *vn, *vp, vbuf;
fprintf (cmd.ofp, " BUF EDEV PROC/VP SIZE OFFSET BCOUNT FLAGS\n");
fprintf (cmd.ofp, "====================================================================\n");
buf_cnt += print_bufchain(bpp, bp, 1, cmd.flags, cmd.ofp);
fprintf (cmd.ofp, "====================================================================\n");
fprintf(cmd.ofp, "%d buf struct%s found\n",
buf_cnt, (buf_cnt != 1) ? "s" : "");
}
#ifndef IRIX5_3
/*
* dochunkhash() -- Dump out the chunk hash data. Note that this isn't
* in 5.3, so don't expect the command to be there.
*/
int
dochunkhash(command_t cmd)
{
int i, mode, bkt = 0, firsttime = 1, buf_cnt = 0;
unsigned b;
char *loc;
cbucket_t *bktp, *cp, cbuf;
if (cmd.nargs == 0) {
for (i = 0; i < varp->v_hbuf; i++) {
bktp = (cbucket_t*)((unsigned)_cbucket +
(i * sizeof (cbucket_t)));
if (debug > 2) {
fprintf(stderr, "dochunkhash: i=%d, bktp=0x%x\n", i, bktp);
}
cp = GET_CBUKET(bktp, &cbuf);
fprintf(cmd.ofp,
"\nCBUCKET[%d]: 0x%x, FORW: 0x%x, BACK: 0x%x\n\n",
i, bktp, cp->b_forw, cp->b_back);
if (cp->b_forw != (buf_t*)bktp) {
fprintf (cmd.ofp, " BUF EDEV PROC/VP SIZE OFFSET BCOUNT FLAGS\n");
fprintf (cmd.ofp, "====================================================================\n");
buf_cnt += print_bufchain(bktp, cp, 0, cmd.flags, cmd.ofp);
}
}
} else {
for (i = 0; i < cmd.nargs; i++) {
b = get_value(cmd.args[i], &mode, varp->v_hbuf);
if (mode == 2) { /* hex value */
bktp = (cbucket_t*)b;
} else {
bktp = (cbucket_t*)((unsigned)_cbucket +
(b * sizeof (cbucket_t)));
}
if ((cp = GET_CBUKET(bktp, &cbuf)) == 0) {
fprintf(stderr, "dochunkhash: couldn't read cbucket at 0x%x\n",
bktp);
continue;
}
bkt = ((unsigned)bktp - (unsigned)_cbucket) / sizeof (cbucket_t);
if ((bkt < 0) || (bkt >= varp->v_hbuf)) {
fprintf(stderr, "0x%x is not a valid cbucket pointer\n", bktp);
if (debug > 2) {
fprintf(stderr, "dochunkhash: bkt=%d\n", bkt);
}
continue;
}
fprintf(cmd.ofp,
"\nCBUCKET[%d]: 0x%x, FORW: 0x%x, BACK: 0x%x\n\n",
bkt, bktp, cp->b_forw, cp->b_back);
if (cp->b_forw != (buf_t*)bktp) {
fprintf (cmd.ofp, " BUF EDEV PROC/VP SIZE OFFSET BCOUNT FLAGS\n");
fprintf (cmd.ofp, "====================================================================\n");
buf_cnt += print_bufchain(bktp, cp, 0, cmd.flags, cmd.ofp);
}
}
}
fprintf (cmd.ofp, "\n====================================================================\n");
fprintf(cmd.ofp, "%d buf struct%s found\n",
buf_cnt, (buf_cnt != 1) ? "s" : "");
}
#endif
/*
* dobufhash() -- Print out the hash buffer information.
*/
int
dobufhash(command_t cmd)
{
int i, mode, bhi = 0, firsttime = 1, buf_cnt = 0;
unsigned b;
char *loc;
struct hbuf *bhashp, *bhp, bhbuf;
if (cmd.nargs == 0) {
for (i = 0; i < varp->v_hbuf; i++) {
bhashp = (struct hbuf*)((unsigned)_hbuf +
(i * sizeof (struct hbuf)));
if (debug) {
fprintf(stderr, "dobufhash: sizeof (hbuf) == %d, ",
sizeof (struct hbuf));
fprintf(stderr, "bhashp == 0x%x (0x%x)\n", bhashp,
((unsigned)_hbuf + (i * sizeof (struct hbuf))));
}
if (debug > 2) {
fprintf(stderr, "dobufhash: i=%d, bhashp=0x%x\n", i, bhashp);
}
bhp = GET_HBUF(bhashp, &bhbuf);
fprintf(cmd.ofp, "\nBHASH[%d]: 0x%x, FORW: 0x%x, BACK: 0x%x\n\n",
i, bhashp, bhp->b_forw, bhp->b_back);
if (bhp->b_forw != (buf_t*)bhashp) {
fprintf (cmd.ofp, " BUF EDEV PROC/VP SIZE OFFSET BCOUNT FLAGS\n");
fprintf (cmd.ofp, "====================================================================\n");
buf_cnt += print_bufchain(bhashp, bhp, 0, cmd.flags, cmd.ofp);
}
}
} else {
for (i = 0; i < cmd.nargs; i++) {
b = get_value(cmd.args[i], &mode, varp->v_hbuf);
if (mode == 2) { /* hex addr */
bhashp = (struct hbuf*)b;
} else {
bhashp = (struct hbuf*)((unsigned)_hbuf +
(b * sizeof (struct hbuf)));
}
if ((bhp = GET_HBUF(bhashp, &bhbuf)) == 0) {
fprintf(stderr, "bufhash: couldn't read buf at 0x%x\n",
bhashp);
continue;
}
bhi = ((unsigned)bhashp - (unsigned)_hbuf) / sizeof (struct hbuf);
if ((bhi < 0) || (bhi >= varp->v_hbuf)) {
fprintf(stderr, "0x%x is not a valid buf pointer\n", bhashp);
if (debug > 2) {
fprintf(stderr, "dobufhash: bhi=%d\n", bhi);
}
continue;
}
fprintf(cmd.ofp, "\nBHASH[%d]: 0x%x, FORW: 0x%x, BACK: 0x%x\n\n",
bhi, bhashp, bhp->b_forw, bhp->b_back);
if (bhp->b_forw != (buf_t*)bhashp) {
fprintf (cmd.ofp, " BUF EDEV PROC/VP SIZE OFFSET BCOUNT FLAGS\n");
fprintf (cmd.ofp, "====================================================================\n");
buf_cnt += print_bufchain(bhashp, bhp, 0, cmd.flags, cmd.ofp);
}
}
}
fprintf (cmd.ofp, "\n====================================================================\n");
fprintf(cmd.ofp, "%d buf struct%s found\n",
buf_cnt, (buf_cnt != 1) ? "s" : "");
}
#ifndef IRIX5_3
/*
* docfind() -- Look for cbucket information.
*/
int
docfind(cmd)
command_t cmd;
{
int i, firsttime = 1, value = 0, buf_cnt = 0;
unsigned offset;
struct vnode *vn, *vp, vbuf;
buf_t *bp, *bpp, bbuf, *hbufp;
cbucket_t *bktp, *cp, cbuf;
vn = (struct vnode*)GET_VALUE(cmd.args[0]);
if (cmd.nargs == 2) {
offset = GET_VALUE(cmd.args[1]);
if ((bp = find_chunk(vn, offset, &bbuf)) == 0) {
fprintf(stderr, "Could not locate buf for 0x%x/%d\n",
vn, offset);
return 1;
}
fprintf (cmd.ofp, " BUF EDEV PROC/VP SIZE OFFSET BCOUNT FLAGS\n");
fprintf (cmd.ofp, "====================================================================\n");
print_buf(bp, &bbuf, cmd.flags, cmd.ofp);
} else {
if ((vp = GET_VNODE(vn, &vbuf)) == 0) {
fprintf(stderr, "couldn't get vnode at 0x%x\n", vn);
return 1;
}
fprintf (cmd.ofp, " BUF EDEV PROC/VP SIZE OFFSET BCOUNT FLAGS\n");
fprintf (cmd.ofp, "====================================================================\n");
for (i = 0; i < varp->v_hbuf; i++) {
bktp = (cbucket_t*)((unsigned)_cbucket +
(i * sizeof (cbucket_t)));
if (debug > 2) {
fprintf(stderr, "docfind: i=%d, bktp=0x%x\n", i, bktp);
}
cp = GET_CBUKET(bktp, &cbuf);
bpp = cp->b_forw;
while (bpp != (buf_t *)bktp) {
if (debug > 2) {
fprintf(stderr, "cfind: bpp=0x%x\n", bpp);
}
/* this should never happen (but it did once!) */
if ((bp = GET_BUF(bpp, &bbuf)) == 0) {
fprintf(stderr,
"WARNING: 0x%x is not a valid buf pointer\n", bpp);
break;
}
/*
* See if it's valid and vnode matches.
*/
if ((bp->b_flags & B_STALE) || (bp->b_vp != vn)) {
bpp = bp->b_forw;
continue;
}
print_buf(bpp, bp, cmd.flags, cmd.ofp);
bpp = bp->b_forw;
}
}
}
}
#endif
/*
* dobfind() -- Find a buffer, plain and simple.
*/
int
dobfind(command_t cmd)
{
int i, firsttime = 1, value = 0, buf_cnt = 0;
unsigned device, blkno;
buf_t *bp, *bpp, bbuf;
struct hbuf *hbufp, *bhp, bhbuf;
device = GET_VALUE(cmd.args[0]);
if (cmd.nargs == 2) {
blkno = GET_VALUE(cmd.args[1]);
if ((bp = find_buf(device, blkno, &bbuf)) == 0) {
fprintf(stderr, "Could not locate buf for 0x%x/%d\n",
device, blkno);
return 1;
}
fprintf (cmd.ofp, " BUF EDEV PROC/VP SIZE OFFSET BCOUNT FLAGS\n");
fprintf (cmd.ofp, "====================================================================\n");
print_buf(bp, &bbuf, cmd.flags, cmd.ofp);
} else {
fprintf (cmd.ofp, " BUF EDEV PROC/VP SIZE OFFSET BCOUNT FLAGS\n");
fprintf (cmd.ofp, "====================================================================\n");
for (i = 0; i < varp->v_hbuf; i++) {
hbufp = (struct hbuf*)((unsigned)_hbuf +
(i * sizeof (struct hbuf)));
if (debug > 2) {
fprintf(stderr, "dobfind: i=%d, hbufp=0x%x\n", i, hbufp);
}
bhp = GET_HBUF(hbufp, &bhbuf);
bpp = bhp->b_forw;
while (bpp != (buf_t*)hbufp) {
if (debug > 2) {
fprintf(stderr, "bfind: bpp=0x%x\n", bpp);
}
/* this should never happen (but it did once!) */
if ((bp = GET_BUF(bpp, &bbuf)) == 0) {
fprintf(stderr,
"WARNING: 0x%x is not a valid buf pointer\n", bpp);
break;
}
/*
* See if it's valid and device matches.
*/
if ((bp->b_flags & B_STALE) || (bp->b_edev != device)) {
bpp = bp->b_forw;
continue;
}
print_buf(bpp, bp, cmd.flags, cmd.ofp);
bpp = bp->b_forw;
}
}
}
}
/*
* print_buf() -- Print out the data inside a buffer, normally called from
* one of the buffer routines.
*/
int
print_buf(unsigned bp, buf_t *bufp, int flags, FILE *ofp)
{
fprintf(ofp, "%8x %8x %8x %8d %8d %8d %8x\n",
bp, bufp->b_edev, bufp->b_vp, bufp->b_bufsize,
bufp->b_offset, bufp->b_bcount, bufp->b_flags);
if (flags & C_FULL) {
fprintf(ofp, "\n");
fprintf(ofp, " B_FORW=0x%x, B_BACK=0x%x\n",
bufp->b_forw, bufp->b_back);
fprintf(ofp, " AV_FORW=0x%x, AV_BACK=0x%x\n",
bufp->av_forw, bufp->av_back);
#ifdef IRIX5_3
fprintf(ofp, " B_DFORW=0x%x, B_DBACK=0x%x\n",
bufp->b_dforw, bufp->b_dback);
#else
fprintf(ofp, " B_VFORW=0x%x, B_VBACK=0x%x\n",
bufp->b_vforw, bufp->b_vback);
#endif
fprintf(ofp, " B_UN=0x%x, B_PAGES=0x%x\n",
bufp->b_un.b_addr, bufp->b_pages);
fprintf(ofp, " B_BLKNO=%d\n", bufp->b_blkno);
fprintf(ofp, "\n");
}
}
/*
* print_bufchain() -- Print out the chain of buffers, handle if
* it is a live system (don't recurse!)
*/
int
print_bufchain(buf_t *buf, buf_t *bp, int avlist, int flags, FILE *ofp)
{
int buf_cnt = 0, loop_trap = 0;
buf_t *nbp, *b, nbbuf;
if (debug > 3) {
fprintf(stderr, "buf=0x%x, bp=0x%x, avlist=%d, flags=0x%x\n",
buf, bp, avlist, flags);
}
if (avlist) {
nbp = bp->av_forw;
} else {
nbp = bp->b_forw;
}
while (nbp != buf) {
if (debug > 2) {
fprintf(stderr, "print_bufchain: nbp=0x%x\n", nbp);
}
/* Make sure we can at least read a buf (valid or not) */
if ((b = GET_BUF(nbp, &nbbuf)) == 0) {
fprintf(stderr, "WARNING: 0x%x is not a valid buf pointer\n",
nbp);
break;
}
if (b->b_flags) {
print_buf((unsigned)nbp, b, flags, ofp);
buf_cnt++;
} else {
if (loop_trap) {
fprintf(stderr, "possible endless loop (live system)!\n");
}
fprintf(ofp, "BUF: 0x%x, FORW: 0x%x, BACK: 0x%x\n",
nbp, b->b_forw, b->b_back);
if (active)
loop_trap++;
}
/*
* Make sure buf doesn't point to a NULL buf and
* that it doen't point to itself.
*/
if (avlist) {
if (!b->av_forw || (b->av_forw == nbp))
break;
nbp = b->av_forw;
} else {
if (!b->b_forw || (b->b_forw == nbp))
break;
nbp = b->b_forw;
}
}
return(buf_cnt);
}