/* DF-4801 helper: send ONE VINUM_SETSTATE(object_up, blocksize) ioctl.
 *
 * `vinum setstate -f up sd` (userland) loops the ioctl until the revive
 * finishes; we need exactly ONE revive_block call to prime the sd into
 * sd_reviving with the cursor at byte 64k, then stop driving it.
 *
 * Build: cc -O -o /tmp/prime /tmp/prime.c
 * Run:   /tmp/prime <sdno>   -> expect reply error=35 (EAGAIN), sd reviving
 */
#include <sys/ioccom.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

#define L 'F'
#define MAX_IOCTL_REPLY 256

struct vimsg {
    int index;
    int type;            /* 1 = sd_object */
    int state;           /* 3 = object_up */
    int op;
    int force;
    int recurse;
    int verify;
    int otherobject;
    int rename;
    long long offset;
    int blocksize;
};

struct virep { int error; char msg[MAX_IOCTL_REPLY - sizeof(int)]; };

#define VINUM_SETSTATE_DF _IOC(IOC_IN | IOC_OUT, L, 76, MAX_IOCTL_REPLY)

int
main(int argc, char **argv)
{
    struct vimsg msg;
    struct virep *rep = (struct virep *)&msg;
    int fd;

    if (argc < 2) { fprintf(stderr, "usage: %s sdno\n", argv[0]); return 2; }
    fd = open("/dev/vinum/controld", O_RDWR);
    if (fd < 0) { perror("controld"); return 1; }
    memset(&msg, 0, sizeof(msg));
    msg.index = atoi(argv[1]);
    msg.type = 1;             /* sd_object */
    msg.state = 3;            /* object_up -> start_object -> revive_block */
    msg.force = 1;
    msg.blocksize = 65536;    /* one 64k block: cursor lands at byte 64k */
    ioctl(fd, VINUM_SETSTATE_DF, &msg);
    printf("prime: error=%d msg=%s\n", rep->error, rep->msg);
    return 0;
}
