return NULL;
}
-/*
- * print appropriate error message for segment_load()/segment_type()
- * return code
- */
-static void
-dcssblk_segment_warn(int rc, char* seg_name)
-{
- switch (rc) {
- case -ENOENT:
- PRINT_WARN("cannot load/query segment %s, does not exist\n",
- seg_name);
- break;
- case -ENOSYS:
- PRINT_WARN("cannot load/query segment %s, not running on VM\n",
- seg_name);
- break;
- case -EIO:
- PRINT_WARN("cannot load/query segment %s, hardware error\n",
- seg_name);
- break;
- case -ENOTSUPP:
- PRINT_WARN("cannot load/query segment %s, is a multi-part "
- "segment\n", seg_name);
- break;
- case -ENOSPC:
- PRINT_WARN("cannot load/query segment %s, overlaps with "
- "storage\n", seg_name);
- break;
- case -EBUSY:
- PRINT_WARN("cannot load/query segment %s, overlaps with "
- "already loaded dcss\n", seg_name);
- break;
- case -EPERM:
- PRINT_WARN("cannot load/query segment %s, already loaded in "
- "incompatible mode\n", seg_name);
- break;
- case -ENOMEM:
- PRINT_WARN("cannot load/query segment %s, out of memory\n",
- seg_name);
- break;
- case -ERANGE:
- PRINT_WARN("cannot load/query segment %s, exceeds kernel "
- "mapping range\n", seg_name);
- break;
- default:
- PRINT_WARN("cannot load/query segment %s, return value %i\n",
- seg_name, rc);
- break;
- }
-}
-
/*
* device attribute for switching shared/nonshared (exclusive)
* operation (show + store)
if (atomic_read(&dev_info->use_count)) {
PRINT_ERR("share: segment %s is busy!\n",
dev_info->segment_name);
- rc = -EBUSY;
- goto out;
+ up_write(&dcssblk_devices_sem);
+ return -EBUSY;
+ }
+ if ((inbuf[0] == '1') && (dev_info->is_shared == 1)) {
+ PRINT_WARN("Segment %s already loaded in shared mode!\n",
+ dev_info->segment_name);
+ up_write(&dcssblk_devices_sem);
+ return count;
+ }
+ if ((inbuf[0] == '0') && (dev_info->is_shared == 0)) {
+ PRINT_WARN("Segment %s already loaded in exclusive mode!\n",
+ dev_info->segment_name);
+ up_write(&dcssblk_devices_sem);
+ return count;
}
if (inbuf[0] == '1') {
// reload segment in shared mode
- rc = segment_modify_shared(dev_info->segment_name,
- SEGMENT_SHARED);
+ segment_unload(dev_info->segment_name);
+ rc = segment_load(dev_info->segment_name, SEGMENT_SHARED_RO,
+ &dev_info->start, &dev_info->end);
if (rc < 0) {
- BUG_ON(rc == -EINVAL);
- if (rc == -EIO || rc == -ENOENT)
- goto removeseg;
- } else {
- dev_info->is_shared = 1;
- switch (dev_info->segment_type) {
- case SEG_TYPE_SR:
- case SEG_TYPE_ER:
- case SEG_TYPE_SC:
- set_disk_ro(dev_info->gd,1);
- }
+ PRINT_ERR("Segment %s not reloaded, rc=%d\n",
+ dev_info->segment_name, rc);
+ goto removeseg;
}
+ dev_info->is_shared = 1;
+ PRINT_INFO("Segment %s reloaded, shared mode.\n",
+ dev_info->segment_name);
} else if (inbuf[0] == '0') {
// reload segment in exclusive mode
- if (dev_info->segment_type == SEG_TYPE_SC) {
- PRINT_ERR("Segment type SC (%s) cannot be loaded in "
- "non-shared mode\n", dev_info->segment_name);
- rc = -EINVAL;
- goto out;
- }
- rc = segment_modify_shared(dev_info->segment_name,
- SEGMENT_EXCLUSIVE);
+ segment_unload(dev_info->segment_name);
+ rc = segment_load(dev_info->segment_name, SEGMENT_EXCLUSIVE_RW,
+ &dev_info->start, &dev_info->end);
if (rc < 0) {
- BUG_ON(rc == -EINVAL);
- if (rc == -EIO || rc == -ENOENT)
- goto removeseg;
- } else {
- dev_info->is_shared = 0;
- set_disk_ro(dev_info->gd, 0);
+ PRINT_ERR("Segment %s not reloaded, rc=%d\n",
+ dev_info->segment_name, rc);
+ goto removeseg;
}
+ dev_info->is_shared = 0;
+ PRINT_INFO("Segment %s reloaded, exclusive (read-write) mode.\n",
+ dev_info->segment_name);
} else {
+ up_write(&dcssblk_devices_sem);
PRINT_WARN("Invalid value, must be 0 or 1\n");
- rc = -EINVAL;
- goto out;
+ return -EINVAL;
}
+ dev_info->segment_type = rc;
rc = count;
+
+ switch (dev_info->segment_type) {
+ case SEGMENT_SHARED_RO:
+ case SEGMENT_EXCLUSIVE_RO:
+ set_disk_ro(dev_info->gd, 1);
+ break;
+ case SEGMENT_SHARED_RW:
+ case SEGMENT_EXCLUSIVE_RW:
+ set_disk_ro(dev_info->gd, 0);
+ break;
+ }
+ if ((inbuf[0] == '1') &&
+ ((dev_info->segment_type == SEGMENT_EXCLUSIVE_RO) ||
+ (dev_info->segment_type == SEGMENT_EXCLUSIVE_RW))) {
+ PRINT_WARN("Could not get shared copy of segment %s\n",
+ dev_info->segment_name);
+ rc = -EPERM;
+ }
+ if ((inbuf[0] == '0') &&
+ ((dev_info->segment_type == SEGMENT_SHARED_RO) ||
+ (dev_info->segment_type == SEGMENT_SHARED_RW))) {
+ PRINT_WARN("Could not get exclusive copy of segment %s\n",
+ dev_info->segment_name);
+ rc = -EPERM;
+ }
+ up_write(&dcssblk_devices_sem);
goto out;
removeseg:
put_disk(dev_info->gd);
device_unregister(dev);
put_device(dev);
-out:
up_write(&dcssblk_devices_sem);
+out:
return rc;
}
// device is idle => we save immediately
PRINT_INFO("Saving segment %s\n",
dev_info->segment_name);
- segment_save(dev_info->segment_name);
+ segment_replace(dev_info->segment_name);
} else {
// device is busy => we save it when it becomes
// idle in dcssblk_release
/*
* load the segment
*/
- rc = segment_load(local_buf, SEGMENT_SHARED,
+ rc = segment_load(local_buf, SEGMENT_SHARED_RO,
&dev_info->start, &dev_info->end);
if (rc < 0) {
- dcssblk_segment_warn(rc, dev_info->segment_name);
+ PRINT_ERR("Segment %s not loaded, rc=%d\n", local_buf, rc);
goto dealloc_gendisk;
}
seg_byte_size = (dev_info->end - dev_info->start + 1);
set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors
- PRINT_INFO("Loaded segment %s, size = %lu Byte, "
- "capacity = %lu (512 Byte) sectors\n", local_buf,
- seg_byte_size, seg_byte_size >> 9);
+ PRINT_INFO("Loaded segment %s from %p to %p, size = %lu Byte, "
+ "capacity = %lu sectors (512 Byte)\n", local_buf,
+ (void *) dev_info->start, (void *) dev_info->end,
+ seg_byte_size, seg_byte_size >> 9);
dev_info->segment_type = rc;
dev_info->save_pending = 0;
blk_queue_hardsect_size(dev_info->dcssblk_queue, 4096);
switch (dev_info->segment_type) {
- case SEG_TYPE_SR:
- case SEG_TYPE_ER:
- case SEG_TYPE_SC:
+ case SEGMENT_SHARED_RO:
+ case SEGMENT_EXCLUSIVE_RO:
set_disk_ro(dev_info->gd,1);
break;
- default:
+ case SEGMENT_SHARED_RW:
+ case SEGMENT_EXCLUSIVE_RW:
set_disk_ro(dev_info->gd,0);
break;
}
&& (dev_info->save_pending)) {
PRINT_INFO("Segment %s became idle and is being saved now\n",
dev_info->segment_name);
- segment_save(dev_info->segment_name);
+ segment_replace(dev_info->segment_name);
dev_info->save_pending = 0;
}
up_write(&dcssblk_devices_sem);