Exemple #1
0
static int
VGCDel(struct cmd_syndesc * as, void * rock)
{
    afs_int32 code;
    struct fssync_state state;
    char * partName;
    VolumeId parent, child;
    struct cmd_item *ti;
    SYNC_response res;

    if (!(ti = as->parms[CUSTOM_PARMS_OFFSET+0].items)) {	/* -partition */
	return -1;
    }
    partName = ti->data;

    if (!(ti = as->parms[CUSTOM_PARMS_OFFSET+1].items)) {	/* -parent */
	return -1;
    }
    parent = atoi(ti->data);

    if (!(ti = as->parms[CUSTOM_PARMS_OFFSET+2].items)) {	/* -child */
	return -1;
    }
    child = atoi(ti->data);

    common_prolog(as, &state);
    fprintf(stderr, "calling FSYNC_VCGDel\n");
    code = FSYNC_VGCDel(partName, parent, child, state.reason, &res);
    debug_response(code, &res);

    VDisconnectFS();

    return 0;
}
static int
VolOpQuery(struct cmd_syndesc * as, void * rock)
{
    struct state state;
    SYNC_PROTO_BUF_DECL(res_buf);
    SYNC_response res;
    FSSYNC_VolOp_info vop;
    int i;

    res.hdr.response_len = sizeof(res.hdr);
    res.payload.buf = res_buf;
    res.payload.len = SYNC_PROTO_MAX_LEN;

    common_prolog(as, &state);
    common_volop_prolog(as, &state);

    do_volop(&state, FSYNC_VOL_QUERY_VOP, &res);

    if (!(res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS)) {
	printf("*** file server not compiled with demand attach extensions.\n");
	printf("*** pending volume operation metadata not available.\n");
    }

    if (res.hdr.response == SYNC_OK) {
	memcpy(&vop, res.payload.buf, sizeof(FSSYNC_VolOp_info));

	printf("pending_vol_op = {\n");

	printf("\tcom = {\n");
	printf("\t\tproto_version  = %u\n", vop.com.proto_version);
	printf("\t\tpkt_seq        = %u\n", vop.com.pkt_seq);
	printf("\t\tcom_seq        = %u\n", vop.com.com_seq);
	printf("\t\tprogramType    = %d (%s)\n", 
	       vop.com.programType, program_type_to_string(vop.com.programType));
	printf("\t\tpid            = %d\n", vop.com.pid);
	printf("\t\ttid            = %d\n", vop.com.tid);
	printf("\t\tcommand        = %d (%s)\n", 
	       vop.com.command, command_code_to_string(vop.com.command));
	printf("\t\treason         = %d (%s)\n", 
	       vop.com.reason, reason_code_to_string(vop.com.reason));
	printf("\t\tcommand_len    = %u\n", vop.com.command_len);
	printf("\t\tflags          = 0x%x\n", vop.com.flags);
	printf("\t}\n");

	printf("\tvop = {\n");
	printf("\t\tvolume         = %u\n", vop.vop.volume);
	if (afs_strnlen(vop.vop.partName, sizeof(vop.vop.partName)) <
	    sizeof(vop.vop.partName)) {
	    printf("\t\tpartName       = '%s'\n", vop.vop.partName);
	} else {
	    printf("\t\tpartName       = (illegal string)\n");
	}
	printf("\t}\n");

	printf("}\n");
    }

    return 0;
}
Exemple #3
0
static int
OpQuery(struct cmd_syndesc * as, void * rock)
{
    struct fssync_state state;

    common_prolog(as, &state);
    common_salv_prolog(as, &state);

    do_salvop(&state, SALVSYNC_QUERY, NULL);

    return 0;
}
Exemple #4
0
static int
OpRaisePrio(struct cmd_syndesc * as, void * rock)
{
    struct fssync_state state;

    common_prolog(as, &state);
    common_salv_prolog(as, &state);

    do_salvop(&state, SALVSYNC_RAISEPRIO, NULL);

    return 0;
}
Exemple #5
0
static int
VolDetach(struct cmd_syndesc * as, void * rock)
{
    struct fssync_state state;

    common_prolog(as, &state);
    common_volop_prolog(as, &state);

    do_volop(&state, FSYNC_VOL_DONE, NULL);

    return 0;
}
Exemple #6
0
static int
OpSalvage(struct cmd_syndesc * as, void * rock)
{
    struct fssync_state state;

    common_prolog(as, &state);
    common_salv_prolog(as, &state);

    do_salvop(&state, SALVSYNC_SALVAGE, NULL);

    return 0;
}
static int
VolForceAttach(struct cmd_syndesc * as, void * rock)
{
    struct state state;

    common_prolog(as, &state);
    common_volop_prolog(as, &state);

    do_volop(&state, FSYNC_VOL_ATTACH, NULL);

    return 0;
}
static int
VolForceError(struct cmd_syndesc * as, void * rock)
{
    struct state state;

    common_prolog(as, &state);
    common_volop_prolog(as, &state);

    do_volop(&state, FSYNC_VOL_FORCE_ERROR, NULL);

    return 0;
}
static int
VolList(struct cmd_syndesc * as, void * rock)
{
    struct state state;

    common_prolog(as, &state);
    common_volop_prolog(as, &state);

    do_volop(&state, FSYNC_VOL_LISTVOLUMES, NULL);

    return 0;
}
static int
VolLeaveOff(struct cmd_syndesc * as, void * rock)
{
    struct state state;

    common_prolog(as, &state);
    common_volop_prolog(as, &state);

    do_volop(&state, FSYNC_VOL_LEAVE_OFF, NULL);

    return 0;
}
static int
VolBreakCBKs(struct cmd_syndesc * as, void * rock)
{
    struct state state;

    common_prolog(as, &state);
    common_volop_prolog(as, &state);

    do_volop(&state, FSYNC_VOL_BREAKCBKS, NULL);

    return 0;
}
static int
VolMove(struct cmd_syndesc * as, void * rock)
{
    struct state state;

    common_prolog(as, &state);
    common_volop_prolog(as, &state);

    do_volop(&state, FSYNC_VOL_MOVE, NULL);

    return 0;
}
Exemple #13
0
static int
OpCancelAll(struct cmd_syndesc * as, void * rock)
{
    struct fssync_state state;

    common_prolog(as, &state);
    common_salv_prolog(as, &state);

    do_salvop(&state, SALVSYNC_CANCELALL, NULL);

    return 0;
}
Exemple #14
0
static int
VGCScanAll(struct cmd_syndesc * as, void * rock)
{
    afs_int32 code;
    struct fssync_state state;

    common_prolog(as, &state);
    fprintf(stderr, "calling FSYNC_VCGScanAll\n");
    code = FSYNC_VGCScan(NULL, state.reason);
    debug_response(code, NULL);

    VDisconnectFS();

    return 0;
}
Exemple #15
0
static int
VolOnline(struct cmd_syndesc * as, void * rock)
{
    struct fssync_state state;

    common_prolog(as, &state);
    common_volop_prolog(as, &state);

    if (state.vop->partName==0 || *(state.vop->partName)==0) {
	fprintf(stderr, "required argument -partition not given\n");
	return -1;
    }
    do_volop(&state, FSYNC_VOL_ON, NULL);

    return 0;
}
Exemple #16
0
/**
 * query VGC.
 *
 * @notes args:
 *    - CUSTOM_PARMS_OFFSET+0 is partition string
 *    - CUSTOM_PARMS_OFFSET+1 is volume id
 *
 * @return operation status
 *    @retval 0 success
 */
static int
VGCQuery(struct cmd_syndesc * as, void * rock)
{
    afs_int32 code;
    struct fssync_state state;
    char * partName;
    VolumeId volid;
    FSSYNC_VGQry_response_t q_res;
    SYNC_response res;
    int i;
    struct cmd_item *ti;

    if (!(ti = as->parms[CUSTOM_PARMS_OFFSET+0].items)) {	/* -partition */
	return -1;
    }
    partName = ti->data;

    if (!(ti = as->parms[CUSTOM_PARMS_OFFSET+1].items)) {	/* -volumeid */
	return -1;
    }
    volid = atoi(ti->data);

    common_prolog(as, &state);

    fprintf(stderr, "calling FSYNC_VCGQuery\n");

    code = FSYNC_VGCQuery(partName, volid, &q_res, &res);

    debug_response(code, &res);

    if (code == SYNC_OK) {
	printf("VG = {\n");
	printf("\trw\t=\t%u\n", q_res.rw);
	printf("\tchildren\t= (\n");
	for (i = 0; i < VOL_VG_MAX_VOLS; i++) {
	    if (q_res.children[i]) {
		printf("\t\t%u\n", q_res.children[i]);
	    }
	}
	printf("\t)\n");
    }

    VDisconnectFS();

    return 0;
}
Exemple #17
0
static int
VGCScan(struct cmd_syndesc * as, void * rock)
{
    afs_int32 code;
    struct fssync_state state;
    char * partName;
    struct cmd_item *ti;

    if (!(ti = as->parms[CUSTOM_PARMS_OFFSET+0].items)) {	/* -partition */
	return -1;
    }
    partName = ti->data;

    common_prolog(as, &state);
    fprintf(stderr, "calling FSYNC_VCGScan\n");
    code = FSYNC_VGCScan(partName, state.reason);
    debug_response(code, NULL);

    VDisconnectFS();

    return 0;
}
static int
VolHdrQuery(struct cmd_syndesc * as, void * rock)
{
    struct state state;
    SYNC_PROTO_BUF_DECL(res_buf);
    SYNC_response res;
    VolumeDiskData v;
    int i;

    res.hdr.response_len = sizeof(res.hdr);
    res.payload.buf = res_buf;
    res.payload.len = SYNC_PROTO_MAX_LEN;

    common_prolog(as, &state);
    common_volop_prolog(as, &state);

    do_volop(&state, FSYNC_VOL_QUERY_HDR, &res);

    if (res.hdr.response == SYNC_OK) {
	memcpy(&v, res.payload.buf, sizeof(VolumeDiskData));

	printf("VolumeDiskData = {\n");
	printf("\tstamp = {\n");
	printf("\t\tmagic   = 0x%x\n", v.stamp.magic);
	printf("\t\tversion = %u\n", v.stamp.version);
	printf("\t}\n");
	
	printf("\tid               = %u\n", v.id);
	printf("\tname             = '%s'\n", v.name);
	if (v.inUse != 0) {
	    printf("\tinUse            = %d (%s)\n", v.inUse, program_type_to_string(v.inUse));
	} else {
	    printf("\tinUse            = %d (no)\n", v.inUse);
	}
	printf("\tinService        = %d\n", v.inService);
	printf("\tblessed          = %d\n", v.blessed);
	printf("\tneedsSalvaged    = %d\n", v.needsSalvaged);
	printf("\tuniquifier       = %u\n", v.uniquifier);
	printf("\ttype             = %d\n", v.type);
	printf("\tparentId         = %u\n", v.parentId);
	printf("\tcloneId          = %u\n", v.cloneId);
	printf("\tbackupId         = %u\n", v.backupId);
	printf("\trestoredFromId   = %u\n", v.restoredFromId);
	printf("\tneedsCallback    = %d\n", v.needsCallback);
	printf("\tdestroyMe        = %d\n", v.destroyMe);
	printf("\tdontSalvage      = %d\n", v.dontSalvage);
	printf("\tmaxquota         = %d\n", v.maxquota);
	printf("\tminquota         = %d\n", v.minquota);
	printf("\tmaxfiles         = %d\n", v.maxfiles);
	printf("\taccountNumber    = %u\n", v.accountNumber);
	printf("\towner            = %u\n", v.owner);
	printf("\tfilecount        = %d\n", v.filecount);
	printf("\tdiskused         = %d\n", v.diskused);
	printf("\tdayUse           = %d\n", v.dayUse);
	for (i = 0; i < 7; i++) {
	    printf("\tweekUse[%d]       = %d\n", i, v.weekUse[i]);
	}
	printf("\tdayUseDate       = %u\n", v.dayUseDate);
	printf("\tcreationDate     = %u\n", v.creationDate);
	printf("\taccessDate       = %u\n", v.accessDate);
	printf("\tupdateDate       = %u\n", v.updateDate);
	printf("\texpirationDate   = %u\n", v.expirationDate);
	printf("\tbackupDate       = %u\n", v.backupDate);
	printf("\tcopyDate         = %u\n", v.copyDate);
#ifdef OPENAFS_VOL_STATS
	printf("\tstat_initialized = %d\n", v.stat_initialized);
#else
        printf("\tmtd              = '%s'\n", v.motd);
#endif
	printf("}\n");
    }

    return 0;
}
static int
VolQuery(struct cmd_syndesc * as, void * rock)
{
    struct state state;
    SYNC_PROTO_BUF_DECL(res_buf);
    SYNC_response res;
    Volume v;
    int hi, lo;

    res.hdr.response_len = sizeof(res.hdr);
    res.payload.buf = res_buf;
    res.payload.len = SYNC_PROTO_MAX_LEN;

    common_prolog(as, &state);
    common_volop_prolog(as, &state);

    do_volop(&state, FSYNC_VOL_QUERY, &res);

    if (res.hdr.response == SYNC_OK) {
	memcpy(&v, res.payload.buf, sizeof(Volume));

	printf("volume = {\n");
	printf("\thashid          = %u\n", v.hashid);
	printf("\theader          = 0x%x\n", v.header);
	printf("\tdevice          = %d\n", v.device);
	printf("\tpartition       = 0x%x\n", v.partition);
	printf("\tlinkHandle      = 0x%x\n", v.linkHandle);
	printf("\tnextVnodeUnique = %u\n", v.nextVnodeUnique);
	printf("\tdiskDataHandle  = 0x%x\n", v.diskDataHandle);
	printf("\tvnodeHashOffset = %u\n", v.vnodeHashOffset);
	printf("\tshuttingDown    = %d\n", v.shuttingDown);
	printf("\tgoingOffline    = %d\n", v.goingOffline);
	printf("\tcacheCheck      = %u\n", v.cacheCheck);
	printf("\tnUsers          = %d\n", v.nUsers);
	printf("\tneedsPutBack    = %d\n", v.needsPutBack);
	printf("\tspecialStatus   = %d\n", v.specialStatus);
	printf("\tupdateTime      = %u\n", v.updateTime);
	
	printf("\tvnodeIndex[vSmall] = {\n");
        printf("\t\thandle       = 0x%x\n", v.vnodeIndex[vSmall].handle);
        printf("\t\tbitmap       = 0x%x\n", v.vnodeIndex[vSmall].bitmap);
	printf("\t\tbitmapSize   = %u\n", v.vnodeIndex[vSmall].bitmapSize);
	printf("\t\tbitmapOffset = %u\n", v.vnodeIndex[vSmall].bitmapOffset);
	printf("\t}\n");
	printf("\tvnodeIndex[vLarge] = {\n");
        printf("\t\thandle       = 0x%x\n", v.vnodeIndex[vLarge].handle);
        printf("\t\tbitmap       = 0x%x\n", v.vnodeIndex[vLarge].bitmap);
	printf("\t\tbitmapSize   = %u\n", v.vnodeIndex[vLarge].bitmapSize);
	printf("\t\tbitmapOffset = %u\n", v.vnodeIndex[vLarge].bitmapOffset);
	printf("\t}\n");
#ifdef AFS_DEMAND_ATTACH_FS
	if (res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS) {
	    printf("\tupdateTime      = %u\n", v.updateTime);
	    printf("\tattach_state    = %s\n", vol_state_to_string(v.attach_state));
	    printf("\tattach_flags    = %s\n", vol_flags_to_string(v.attach_flags));
	    printf("\tnWaiters        = %d\n", v.nWaiters);
	    printf("\tchainCacheCheck = %d\n", v.chainCacheCheck);
	    
	    /* online salvage structure */
	    printf("\tsalvage = {\n");
	    printf("\t\tprio      = %u\n", v.salvage.prio);
	    printf("\t\treason    = %d\n", v.salvage.reason);
	    printf("\t\trequested = %d\n", v.salvage.requested);
	    printf("\t\tscheduled = %d\n", v.salvage.scheduled);
	    printf("\t}\n");
	    
	    /* statistics structure */
	    printf("\tstats = {\n");

	    printf("\t\thash_lookups = {\n");
	    SplitInt64(v.stats.hash_lookups,hi,lo);
	    printf("\t\t\thi = %u\n", hi);
	    printf("\t\t\tlo = %u\n", lo);
	    printf("\t\t}\n");

	    printf("\t\thash_short_circuits = {\n");
	    SplitInt64(v.stats.hash_short_circuits,hi,lo);
	    printf("\t\t\thi = %u\n", hi);
	    printf("\t\t\tlo = %u\n", lo);
	    printf("\t\t}\n");

	    printf("\t\thdr_loads = {\n");
	    SplitInt64(v.stats.hdr_loads,hi,lo);
	    printf("\t\t\thi = %u\n", hi);
	    printf("\t\t\tlo = %u\n", lo);
	    printf("\t\t}\n");

	    printf("\t\thdr_gets = {\n");
	    SplitInt64(v.stats.hdr_gets,hi,lo);
	    printf("\t\t\thi = %u\n", hi);
	    printf("\t\t\tlo = %u\n", lo);
	    printf("\t\t}\n");
	    
	    printf("\t\tattaches         = %u\n", v.stats.attaches);
	    printf("\t\tsoft_detaches    = %u\n", v.stats.soft_detaches);
	    printf("\t\tsalvages         = %u\n", v.stats.salvages);
	    printf("\t\tvol_ops          = %u\n", v.stats.vol_ops);
	    
	    printf("\t\tlast_attach      = %u\n", v.stats.last_attach);
	    printf("\t\tlast_get         = %u\n", v.stats.last_get);
	    printf("\t\tlast_promote     = %u\n", v.stats.last_promote);
	    printf("\t\tlast_hdr_get     = %u\n", v.stats.last_hdr_get);
	    printf("\t\tlast_hdr_load    = %u\n", v.stats.last_hdr_load);
	    printf("\t\tlast_salvage     = %u\n", v.stats.last_salvage);
	    printf("\t\tlast_salvage_req = %u\n", v.stats.last_salvage_req);
	    printf("\t\tlast_vol_op      = %u\n", v.stats.last_vol_op);
	    printf("\t}\n");
	    
	    /* VLRU state */
	    printf("\tvlru = {\n");
	    printf("\t\tidx = %d (%s)\n", 
		   v.vlru.idx, vlru_idx_to_string(v.vlru.idx));
	    printf("\t}\n");

	    /* volume op state */
	    printf("\tpending_vol_op  = 0x%x\n", v.pending_vol_op);
	}
#else /* !AFS_DEMAND_ATTACH_FS */
	if (res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS) {
	    printf("*** server asserted demand attach extensions. fssync-debug not built to\n");
	    printf("*** recognize those extensions. please recompile fssync-debug if you need\n");
	    printf("*** to dump dafs extended state\n");
	}
#endif /* !AFS_DEMAND_ATTACH_FS */
	printf("}\n");
    }

    return 0;
}
static int
VnQuery(struct cmd_syndesc * as, void * rock)
{
    struct state state;
    SYNC_PROTO_BUF_DECL(res_buf);
    SYNC_response res;
    Vnode v;
    int hi, lo;

    res.hdr.response_len = sizeof(res.hdr);
    res.payload.buf = res_buf;
    res.payload.len = SYNC_PROTO_MAX_LEN;

    common_prolog(as, &state);
    vn_prolog(as, &state);

    do_vnqry(&state, &res);

    if (res.hdr.response == SYNC_OK) {
	memcpy(&v, res.payload.buf, sizeof(Volume));

	printf("vnode = {\n");

	printf("\tvid_hash = {\n");
	printf("\t\tnext = 0x%lx\n", v.vid_hash.next);
	printf("\t\tprev = 0x%lx\n", v.vid_hash.prev);
	printf("\t}\n");

	printf("\thashNext        = 0x%lx\n", v.hashNext);
	printf("\tlruNext         = 0x%lx\n", v.lruNext);
	printf("\tlruPrev         = 0x%lx\n", v.lruPrev);
	printf("\thashIndex       = %hu\n", v.hashIndex);
	printf("\tchanged_newTime = %u\n", (unsigned int) v.changed_newTime);
	printf("\tchanged_oldTime = %u\n", (unsigned int) v.changed_oldTime);
	printf("\tdelete          = %u\n", (unsigned int) v.delete);
	printf("\tvnodeNumber     = %u\n", v.vnodeNumber);
	printf("\tvolumePtr       = 0x%lx\n", v.volumePtr);
	printf("\tnUsers          = %u\n", v.nUsers);
	printf("\tcacheCheck      = %u\n", v.cacheCheck);

#ifdef AFS_DEMAND_ATTACH_FS
	if (!(res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS)) {
	    printf("*** fssync-debug built to expect demand attach extensions.  server asserted\n");
	    printf("*** that it was not compiled with demand attach turned on.  please recompile\n");
	    printf("*** fssync-debug to match your server\n");
	    goto done;
	}

	printf("\tnReaders        = %u\n", v.nReaders);
	printf("\tvn_state_flags  = %s\n", vn_flags_to_string(v.vn_state_flags));
	printf("\tvn_state        = %s\n", vn_state_to_string(v.vn_state));
#else
	if (res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS) {
	    printf("*** server asserted demand attach extensions. fssync-debug not built to\n");
	    printf("*** recognize those extensions. please recompile fssync-debug if you need\n");
	    printf("*** to dump dafs extended state\n");
	    goto done;
	}
#endif /* !AFS_DEMAND_ATTACH_FS */

	printf("\twriter          = %u\n", v.writer);
	printf("\tvcp             = 0x%lx\n", v.vcp);
	printf("\thandle          = 0x%lx\n", v.handle);

	printf("\tdisk = {\n");
	printf("\t\ttype              = %u\n", v.disk.type);
	printf("\t\tcloned            = %u\n", v.disk.cloned);
	printf("\t\tmodeBits          = %u\n", v.disk.modeBits);
	printf("\t\tlinkCount         = %d\n", v.disk.linkCount);
	printf("\t\tlength            = %u\n", v.disk.length);
	printf("\t\tuniquifier        = %u\n", v.disk.uniquifier);
	printf("\t\tdataVersion       = %u\n", v.disk.dataVersion);
	printf("\t\tvn_ino_lo         = %u\n", v.disk.vn_ino_lo);
	printf("\t\tunixModifyTime    = %u\n", v.disk.unixModifyTime);
	printf("\t\tauthor            = %u\n", v.disk.author);
	printf("\t\towner             = %u\n", v.disk.owner);
	printf("\t\tparent            = %u\n", v.disk.parent);
	printf("\t\tvnodeMagic        = %u\n", v.disk.vnodeMagic);

	printf("\t\tlock = {\n");
	printf("\t\t\tlockCount   = %d\n", v.disk.lock.lockCount);
	printf("\t\t\tlockTime    = %d\n", v.disk.lock.lockTime);
	printf("\t\t}\n");

	printf("\t\tserverModifyTime  = %u\n", v.disk.serverModifyTime);
	printf("\t\tgroup             = %d\n", v.disk.group);
	printf("\t\tvn_ino_hi         = %d\n", v.disk.vn_ino_hi);
	printf("\t\treserved6         = %u\n", v.disk.reserved6);
	printf("\t}\n");

	printf("}\n");
    }
static int
StatsQuery(struct cmd_syndesc * as, void * rock)
{
    afs_int32 code;
    int command;
    struct cmd_item *ti;
    struct state state;
    SYNC_PROTO_BUF_DECL(res_buf);
    SYNC_response res;
    FSSYNC_StatsOp_hdr scom;
    union {
	void * ptr;
	struct VolPkgStats * vol_stats;
	struct VolumeHashChainStats * hash_stats;
#ifdef AFS_DEMAND_ATTACH_FS
	struct volume_hdr_LRU_stats * hdr_stats;
#endif
	struct DiskPartitionStats64 * vicep_stats;
    } sres;

    sres.ptr = res_buf;
    res.hdr.response_len = sizeof(res.hdr);
    res.payload.buf = res_buf;
    res.payload.len = SYNC_PROTO_MAX_LEN;

    if ((ti = as->parms[CUSTOM_PARMS_OFFSET].items)) {	/* -subcommand */
	if (!strcasecmp(ti->data, "vicep")) {
	    command = FSYNC_VOL_STATS_VICEP;
	} else if (!strcasecmp(ti->data, "hash")) {
	    command = FSYNC_VOL_STATS_HASH;
#ifdef AFS_DEMAND_ATTACH_FS
	} else if (!strcasecmp(ti->data, "hdr")) {
	    command = FSYNC_VOL_STATS_HDR;
	} else if (!strcasecmp(ti->data, "vlru")) {
	    command = FSYNC_VOL_STATS_VLRU;
#endif
	} else if (!strcasecmp(ti->data, "pkg")) {
	    command = FSYNC_VOL_STATS_GENERAL;
	} else if (!strcasecmp(ti->data, "help")) {
	    fprintf(stderr, "fssync-debug stats subcommands:\n");
	    fprintf(stderr, "\tpkg\tgeneral volume package stats\n");
	    fprintf(stderr, "\tvicep\tvice partition stats\n");
	    fprintf(stderr, "\thash\tvolume hash chain stats\n");
#ifdef AFS_DEMAND_ATTACH_FS
	    fprintf(stderr, "\thdr\tvolume header cache stats\n");
	    fprintf(stderr, "\tvlru\tvlru generation stats\n");
#endif
	    exit(0);
	} else {
	    fprintf(stderr, "invalid stats subcommand");
	    exit(1);
	}
    } else {
	command = FSYNC_VOL_STATS_GENERAL;
    }

    if ((ti = as->parms[CUSTOM_PARMS_OFFSET+1].items)) {	/* -arg1 */
	switch (command) {
	case FSYNC_VOL_STATS_VICEP:
	    strlcpy(scom.args.partName, ti->data, sizeof(state.vop->partName));
	    break;
	case FSYNC_VOL_STATS_HASH:
	    scom.args.hash_bucket = atoi(ti->data);
	    break;
	case FSYNC_VOL_STATS_VLRU:
	    scom.args.vlru_generation = atoi(ti->data);
	    break;
	default:
	    fprintf(stderr, "unrecognized arguments\n");
	    exit(1);
	}
    } else {
	switch (command) {
	case FSYNC_VOL_STATS_VICEP:
	case FSYNC_VOL_STATS_HASH:
	case FSYNC_VOL_STATS_VLRU:
	    fprintf(stderr, "this subcommand requires more parameters\n");
	    exit(1);
	}
    }

    common_prolog(as, &state);

    fprintf(stderr, "calling FSYNC_askfs with command code %d (%s)\n", 
	    command, command_code_to_string(command));

    code = FSYNC_StatsOp(&scom, command, FSYNC_WHATEVER, &res);

    switch (code) {
    case SYNC_OK:
    case SYNC_DENIED:
	break;
    default:
	fprintf(stderr, "possible sync protocol error. return code was %d\n", code);
    }

    fprintf(stderr, "FSYNC_VolOp returned %d (%s)\n", code, response_code_to_string(code));
    fprintf(stderr, "protocol response code was %d (%s)\n", 
	    res.hdr.response, response_code_to_string(res.hdr.response));
    fprintf(stderr, "protocol reason code was %d (%s)\n", 
	    res.hdr.reason, reason_code_to_string(res.hdr.reason));

    VDisconnectFS();

    if (res.hdr.response == SYNC_OK) {
	switch (command) {
	case FSYNC_VOL_STATS_GENERAL:
	    print_vol_stats_general(sres.vol_stats);
	    break;
	case FSYNC_VOL_STATS_VICEP:
	    print_vol_stats_viceP(sres.vicep_stats);
	    break;
	case FSYNC_VOL_STATS_HASH:
	    print_vol_stats_hash(sres.hash_stats);
	    break;
#ifdef AFS_DEMAND_ATTACH_FS
	case FSYNC_VOL_STATS_HDR:
	    print_vol_stats_hdr(sres.hdr_stats);
	    break;
#endif /* AFS_DEMAND_ATTACH_FS */
	}
    }

    return 0;
}