int (*o_set_info)(struct obd_conn *, int keylen, void *key, int vallen, void *val);
int (*o_migrate)(struct obd_conn *, obdattr *src, obdattr *dst);
int (*o_copy)(struct obd_conn *dev, obdattr *source, obdattr *target);
+ int (*o_iocontrol)(int cmd, int len, void *karg, void *uarg);
};
/*
* ioctl commands
*/
-struct oic_attach {
+struct oic_generic {
int att_typelen;
void *att_type;
int att_datalen;
#define OBD_SNAP_MAGIC 0x47224722
-#define SNAP_MAX 8 /* must fit in "u" area of struct inode */
+
+/* maximum number of snapshot tables we maintain in the kernel */
+#define SNAP_MAX_TABLES 8
+
+
+/* maximum number of snapshots per device
+ must fit in "u" area of struct inode */
+#define SNAP_MAX 8
+
+
+/* ioctls for manipulating snapshots 40 - 50 */
+#define OBD_SNAP_SETTABLE _IOWR('f', 40, long)
+#define OBD_SNAP_PRINTTABLE _IOWR('f', 41, long)
+
+
/* if time is 0 this designates the "current" snapshot, i.e.
the head of the tree
*/
-
struct snap {
time_t time;
int index;
};
-/* snap ioctl data for attach */
+/* snap ioctl data for attach: current always in first slot of this array */
struct snap_obd_data {
- int snap_dev; /* which device contains the data */
- unsigned int snap_no; /* which snapshot are we accessing */
- unsigned int snap_count; /* how many snapshots exist */
- struct snap snap_snaps[SNAP_MAX]; /* times must be incr or attach will fail */
+ int snap_dev; /* which device contains the data */
+ unsigned int snap_index;/* which snapshot is ours */
+ unsigned int snap_table;/* which table do we use */
+};
+
+
+/* snap ioctl data for table fiddling */
+struct snap_table_data {
+ int tblcmd_no; /* which table */
+ unsigned int tblcmd_count; /* how many snaps */
+ struct snap tblcmd_snaps[SNAP_MAX]; /* sorted times! */
+};
+
+
+struct snap_table {
+ spinlock_t tbl_lock;
+ unsigned int tbl_count; /* how many snapshots exist in this table*/
+ int tbl_used; /* bitmap of snaps in use by a device */
+ time_t tbl_times[SNAP_MAX];
+ int tbl_index[SNAP_MAX];
};
-/* this is the obd device descriptor */
+/* this is the obd device descriptor:
+ - current snapshot ends up in first slot of this array
+ */
struct snap_obd {
- unsigned int snap_no; /* which snapshot index are we accessing */
- unsigned int snap_current;
- unsigned int snap_count; /* how many snapshots exist */
- time_t snap_times[SNAP_MAX];
- int snap_index[SNAP_MAX];
+ unsigned int snap_index; /* which snapshot index are we accessing */
+ int snap_tableno;
};
unsigned long od_ids[SNAP_MAX + 1];
};
+#define this_snapidx(obd) (obd->u.snap.snap_index)
+extern int snap_iocontrol(int cmd, int len, void *karg, void *uarg);
+void snap_use(int table_no, int snap_index) ;
+void snap_unuse(int table_no, int snap_index) ;
+int snap_is_used(int table_no, int snap_index) ;
+int snap_table_attach(int tableno, int snap_index);
#endif
switch (cmd) {
case OBD_IOC_ATTACH: {
struct obd_type *type;
- struct oic_attach input;
+ struct oic_generic input;
/* have we attached a type to this device */
if ( obddev->obd_type || (obddev->obd_flags & OBD_ATTACHED) ){
return rc;
}
- default:
- printk("invalid ioctl: cmd = %x, arg = %lx\n", cmd, arg);
- return -ENOTTY;
+ default: {
+ struct obd_type *type;
+ struct oic_generic input;
+ void *karg;
+
+ /* get data structures */
+ err = copy_from_user(&input, (void *) arg, sizeof(input));
+ if (err) {
+ EXIT;
+ return err;
+ }
+
+ if ( (err = getdata(input.att_typelen + 1, &input.att_type))){
+ EXIT;
+ return err;
+ }
+
+ /* find the type */
+ err = -EINVAL;
+ type = obd_nm_to_type(input.att_type);
+ OBD_FREE(input.att_type, input.att_typelen + 1);
+ if ( !type ) {
+ printk("Unknown obd type dev %d\n", dev);
+ EXIT;
+ return err;
+ }
+
+ if ( !type->typ_ops->o_iocontrol ) {
+ EXIT;
+ return -EINVAL;
+ }
+
+
+ CDEBUG(D_IOCTL, "Calling ioctl %x for type %s, len %d\n",
+ cmd, type->typ_name, input.att_datalen);
+
+ /* get the generic data */
+ if ( (err = getdata(input.att_datalen, &karg)) ) {
+ EXIT;
+ return err;
+ }
+
+ err = type->typ_ops->o_iocontrol(cmd, input.att_datalen,
+ karg, input.att_data);
+ OBD_FREE(karg, input.att_datalen);
+
+ EXIT;
+ return err;
+ }
}
}
defined(&OBD_IOC_COPY);
eval 'sub OBD_IOC_MIGR () { &_IOC(3, ord(\'f\'), 23, 4);}' unless
defined(&OBD_IOC_MIGR);
+eval 'sub OBD_SNAP_SETTABLE () { &_IOC(3, ord(\'f\'), 40, 4);}' unless
+ defined(&OBD_SNAP_SETTABLE);
+eval 'sub OBD_SNAP_PRINTTABLE () { &_IOC(3, ord(\'f\'), 41, 4);}' unless
+ defined(&OBD_SNAP_PRINTTABLE);
eval 'sub ATTR_MODE () {1;}' unless defined(&ATTR_MODE);
eval 'sub ATTR_UID () {2;}' unless defined(&ATTR_UID);
'create' => {func => "Create", doc => "create: creates a new inode"},
'attach' => {func => "Attach", doc => "attach type [adapter bus tid lun]"},
'detach' => {func => "Detach", doc => "detach this device"},
- 'snapattach' => {func => "SnapAttach", doc => "snapattach snapno snapcount time1 index1 .... timek indexk"},
+ 'snapattach' => {func => "SnapAttach", doc => "snapattach snapno table"},
+ 'snapset' => {func => "SnapSetTable", doc => "snapset tableno file" },
+ 'snapprint' => {func => "SnapPrint", doc => "snapprint tableno"},
+
'snaptable' => {func => "SnapShotTable", doc => "snaptable: build a snapshot table (interactive)"},
'copy' => {func => "Copy", doc => "copy srcid tgtid"},
'migrate' => {func => "Migrate", doc => "migrate srcid tgtid"},
}
-sub SnapAttach {
+sub SnapPrint {
my $err = 0;
my $type = "snap_obd";
- my $snapdev = shift;
- my $snapno = shift;
+ my $snaptableno = shift;
+
+ $data = pack("i", $snaptableno);
+ $datalen = 4;
+
+ my $len = length($type);
+ my $cl = length($data);
+ my $add = pack("p", $data);
+ print "type $type (len $len), datalen $datalen ($cl)\n";
+ my $packed = pack("ipip", length($type), $type, $datalen, $data);
+
+ my $rc = ioctl(DEV_OBD, &OBD_SNAP_PRINTTABLE, $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+sub SnapSetTable {
+ my $err = 0;
+ my $type = "snap_obd";
+ my $snaptableno = shift;
my $file = shift;
my $snapcount;
my $table = {};
print "No current snapshot in table! First make one\n";
return ;
}
- $data = pack("iii", $snapdev, $snapno, $snapcount);
- $datalen = 3 * 4;
+ $data = pack("ii", $snaptableno, $snapcount);
+ $datalen = 2 * 4;
foreach my $time (sort keys %{$table}) {
$data .= pack("Ii", $time, $table->{$time});
$datalen += 8;
print "type $type (len $len), datalen $datalen ($cl)\n";
my $packed = pack("ipip", length($type), $type, $datalen, $data);
+ my $rc = ioctl(DEV_OBD, &OBD_SNAP_SETTABLE, $packed);
+
+ if (!defined $rc) {
+ print STDERR "ioctl failed: $!\n";
+ } elsif ($rc eq "0 but true") {
+ print "Finished (success)\n";
+ } else {
+ print "ioctl returned error code $rc.\n";
+ }
+}
+
+
+sub SnapAttach {
+ my $err = 0;
+ my $type = "snap_obd";
+ my $snapdev = shift;
+ my $snapno = shift;
+ my $tableno = shift;
+ my $snapcount;
+ my $data;
+ my $datalen = 0;
+
+ if ( ! -f $file ) {
+ print "No such file $file\n";
+ }
+
+ $table = ReadSnapShotTable($file);
+ $data = pack("iii", $snapdev, $snapno, $tableno);
+ $datalen = 3 * 4;
+
+ my $len = length($type);
+ my $cl = length($data);
+ my $add = pack("p", $data);
+ print "type $type (len $len), datalen $datalen ($cl)\n";
+ my $packed = pack("ipip", length($type), $type, $datalen, $data);
+
my $rc = ioctl(DEV_OBD, &OBD_IOC_ATTACH, $packed);
if (!defined $rc) {