00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <libstoragemgmt/libstoragemgmt_plug_interface.h>
00021 #include <string.h>
00022 #define _XOPEN_SOURCE
00023 #include <unistd.h>
00024 #include <crypt.h>
00025 #include <glib.h>
00026 #include <assert.h>
00027 #include <time.h>
00028 #include <stdlib.h>
00029 #include <stdio.h>
00030 #include <openssl/md5.h>
00031
00032 #include "libstoragemgmt/libstoragemgmt_targetport.h"
00033
00034 #ifdef __cplusplus
00035 extern "C" {
00036 #endif
00037
00038 static char name[] = "Compiled plug-in example";
00039 static char version[] = "0.2.0";
00040 static char sys_id[] = "sim-01";
00041
00042 #define BS 512
00043 #define MAX_SYSTEMS 1
00044 #define MAX_FS 32
00045 #define MAX_EXPORT 32
00046
00052 char *md5(const char *data)
00053 {
00054 int i = 0;
00055 MD5_CTX c;
00056 unsigned char digest[16];
00057 static char digest_str[33];
00058
00059 MD5_Init(&c);
00060 MD5_Update(&c, data, strlen(data));
00061 MD5_Final(digest, &c);
00062
00063 for (i = 0; i < sizeof(digest); ++i) {
00064 sprintf(&digest_str[i * 2], "%02x", (unsigned int) digest[i]);
00065 } return digest_str;
00066 }
00067
00076 void remove_item(void *array, int remove_index, int num_elems,
00077 size_t elem_size)
00078 {
00079 if (array && (num_elems > 0) && (remove_index < num_elems) && elem_size) {
00080
00081 if (remove_index + 1 == num_elems) {
00082 memset(array + (elem_size * (num_elems - 1)), 0, elem_size);
00083 return;
00084 }
00085
00086
00087 void *src_addr = (void *) (array + ((remove_index + 1) * elem_size));
00088
00089
00090 void *dest_addr = (void *) (array + (remove_index * elem_size));
00091
00092
00093 memmove(dest_addr, src_addr, ((num_elems - 1) - remove_index) *
00094 elem_size);
00095
00096 memset(array + (elem_size * (num_elems - 1)), 0, elem_size);
00097 }
00098 }
00099
00100 struct allocated_volume {
00101 lsm_volume *v;
00102 lsm_pool *p;
00103 };
00104
00105 struct allocated_fs {
00106 lsm_fs *fs;
00107 lsm_pool *p;
00108 GHashTable *ss;
00109 GHashTable *exports;
00110 };
00111
00112 struct allocated_ag {
00113 lsm_access_group *ag;
00114 lsm_access_group_init_type ag_type;
00115 };
00116
00117 struct plugin_data {
00118 uint32_t tmo;
00119 uint32_t num_systems;
00120 lsm_system *system[MAX_SYSTEMS];
00121
00122 GHashTable *access_groups;
00123 GHashTable *group_grant;
00124 GHashTable *fs;
00125 GHashTable *jobs;
00126 GHashTable *pools;
00127 GHashTable *volumes;
00128 GHashTable *disks;
00129 };
00130
00131 struct allocated_job {
00132 int polls;
00133 lsm_data_type type;
00134 void *return_data;
00135 };
00136
00137 struct allocated_job *alloc_allocated_job(lsm_data_type type,
00138 void *return_data)
00139 {
00140 struct allocated_job *rc = malloc(sizeof(struct allocated_job));
00141 if (rc) {
00142 rc->polls = 0;
00143 rc->type = type;
00144 rc->return_data = return_data;
00145 }
00146 return rc;
00147 }
00148
00149 void free_allocated_job(void *j)
00150 {
00151 struct allocated_job *job = j;
00152
00153 if (job && job->return_data) {
00154 switch (job->type) {
00155 case (LSM_DATA_TYPE_ACCESS_GROUP):
00156 lsm_access_group_record_free((lsm_access_group *)
00157 job->return_data);
00158 break;
00159 case (LSM_DATA_TYPE_BLOCK_RANGE):
00160 lsm_block_range_record_free((lsm_block_range *)
00161 job->return_data);
00162 break;
00163 case (LSM_DATA_TYPE_FS):
00164 lsm_fs_record_free((lsm_fs *) job->return_data);
00165 break;
00166 case (LSM_DATA_TYPE_NFS_EXPORT):
00167 lsm_nfs_export_record_free((lsm_nfs_export *) job->return_data);
00168 break;
00169 case (LSM_DATA_TYPE_POOL):
00170 lsm_pool_record_free((lsm_pool *) job->return_data);
00171 break;
00172 case (LSM_DATA_TYPE_SS):
00173 lsm_fs_ss_record_free((lsm_fs_ss *) job->return_data);
00174 break;
00175 case (LSM_DATA_TYPE_STRING_LIST):
00176 lsm_string_list_free((lsm_string_list *) job->return_data);
00177 break;
00178 case (LSM_DATA_TYPE_SYSTEM):
00179 lsm_system_record_free((lsm_system *) job->return_data);
00180 break;
00181 case (LSM_DATA_TYPE_VOLUME):
00182 lsm_volume_record_free((lsm_volume *) job->return_data);
00183 break;
00184 default:
00185 break;
00186 }
00187 job->return_data = NULL;
00188 }
00189 free(job);
00190 }
00191
00192 struct allocated_ag *alloc_allocated_ag(lsm_access_group * ag,
00193 lsm_access_group_init_type i) {
00194 struct allocated_ag *aag =
00195 (struct allocated_ag *) malloc(sizeof(struct allocated_ag));
00196 if (aag) {
00197 aag->ag = ag;
00198 aag->ag_type = i;
00199 }
00200 return aag;
00201 }
00202
00203 void free_allocated_ag(void *v)
00204 {
00205 if (v) {
00206 struct allocated_ag *aag = (struct allocated_ag *) v;
00207 lsm_access_group_record_free(aag->ag);
00208 free(aag);
00209 }
00210 }
00211
00212 void free_pool_record(void *p)
00213 {
00214 if (p) {
00215 lsm_pool_record_free((lsm_pool *) p);
00216 }
00217 }
00218
00219 void free_fs_record(struct allocated_fs *fs)
00220 {
00221 if (fs) {
00222 g_hash_table_destroy(fs->ss);
00223 g_hash_table_destroy(fs->exports);
00224 lsm_fs_record_free(fs->fs);
00225 fs->p = NULL;
00226 free(fs);
00227 }
00228 }
00229
00230 static void free_ss(void *s)
00231 {
00232 lsm_fs_ss_record_free((lsm_fs_ss *) s);
00233 }
00234
00235 static void free_export(void *exp)
00236 {
00237 lsm_nfs_export_record_free((lsm_nfs_export *) exp);
00238 }
00239
00240 static struct allocated_fs *alloc_fs_record()
00241 {
00242 struct allocated_fs *rc = (struct allocated_fs *)
00243 malloc(sizeof(struct allocated_fs));
00244 if (rc) {
00245 rc->fs = NULL;
00246 rc->p = NULL;
00247 rc->ss =
00248 g_hash_table_new_full(g_str_hash, g_str_equal, free, free_ss);
00249 rc->exports =
00250 g_hash_table_new_full(g_str_hash, g_str_equal, free,
00251 free_export);
00252
00253 if (!rc->ss || !rc->exports) {
00254 if (rc->ss) {
00255 g_hash_table_destroy(rc->ss);
00256 }
00257
00258 if (rc->exports) {
00259 g_hash_table_destroy(rc->exports);
00260 }
00261
00262 free(rc);
00263 rc = NULL;
00264 }
00265 }
00266 return rc;
00267 }
00268
00269 static int create_job(struct plugin_data *pd, char **job, lsm_data_type t,
00270 void *new_value, void **returned_value)
00271 {
00272 static int job_num = 0;
00273 int rc = LSM_ERR_JOB_STARTED;
00274 char job_id[64];
00275 char *key = NULL;
00276
00277
00278 if (0) {
00279 if (returned_value) {
00280 *returned_value = new_value;
00281 }
00282 *job = NULL;
00283 rc = LSM_ERR_OK;
00284 } else {
00285 snprintf(job_id, sizeof(job_id), "JOB_%d", job_num);
00286 job_num += 1;
00287
00288 if (returned_value) {
00289 *returned_value = NULL;
00290 }
00291
00292 *job = strdup(job_id);
00293 key = strdup(job_id);
00294
00295 struct allocated_job *value = alloc_allocated_job(t, new_value);
00296 if (*job && key && value) {
00297 g_hash_table_insert(pd->jobs, key, value);
00298 } else {
00299 free(*job);
00300 *job = NULL;
00301 free(key);
00302 key = NULL;
00303 free_allocated_job(value);
00304 value = NULL;
00305 rc = LSM_ERR_NO_MEMORY;
00306 }
00307 }
00308 return rc;
00309 }
00310
00311 static int tmo_set(lsm_plugin_ptr c, uint32_t timeout, lsm_flag flags)
00312 {
00313 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
00314
00315 if (pd) {
00316 pd->tmo = timeout;
00317 return LSM_ERR_OK;
00318 }
00319 return LSM_ERR_INVALID_ARGUMENT;
00320 }
00321
00322 static int tmo_get(lsm_plugin_ptr c, uint32_t * timeout, lsm_flag flags)
00323 {
00324 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
00325
00326 if (pd) {
00327 *timeout = pd->tmo;
00328 return LSM_ERR_OK;
00329 }
00330 return LSM_ERR_INVALID_ARGUMENT;
00331 }
00332
00333 static int vol_accessible_by_ag(lsm_plugin_ptr c,
00334 lsm_access_group * group,
00335 lsm_volume ** volumes[],
00336 uint32_t * count, lsm_flag flags);
00337
00338 static int ag_granted_to_volume(lsm_plugin_ptr c,
00339 lsm_volume * volume,
00340 lsm_access_group ** groups[],
00341 uint32_t * count, lsm_flag flags);
00342
00343 static int cap(lsm_plugin_ptr c, lsm_system * system,
00344 lsm_storage_capabilities ** cap, lsm_flag flags)
00345 {
00346 int rc = LSM_ERR_NO_MEMORY;
00347 *cap = lsm_capability_record_alloc(NULL);
00348
00349 if (*cap) {
00350 rc = lsm_capability_set_n(*cap, LSM_CAP_SUPPORTED,
00351 LSM_CAP_VOLUMES,
00352 LSM_CAP_VOLUME_CREATE,
00353 LSM_CAP_VOLUME_RESIZE,
00354 LSM_CAP_VOLUME_REPLICATE,
00355 LSM_CAP_VOLUME_REPLICATE_CLONE,
00356 LSM_CAP_VOLUME_REPLICATE_COPY,
00357 LSM_CAP_VOLUME_REPLICATE_MIRROR_ASYNC,
00358 LSM_CAP_VOLUME_REPLICATE_MIRROR_SYNC,
00359 LSM_CAP_VOLUME_COPY_RANGE_BLOCK_SIZE,
00360 LSM_CAP_VOLUME_COPY_RANGE,
00361 LSM_CAP_VOLUME_COPY_RANGE_CLONE,
00362 LSM_CAP_VOLUME_COPY_RANGE_COPY,
00363 LSM_CAP_VOLUME_DELETE,
00364 LSM_CAP_VOLUME_ENABLE,
00365 LSM_CAP_VOLUME_DISABLE,
00366 LSM_CAP_VOLUME_MASK,
00367 LSM_CAP_VOLUME_UNMASK,
00368 LSM_CAP_ACCESS_GROUPS,
00369 LSM_CAP_ACCESS_GROUP_CREATE_ISCSI_IQN,
00370 LSM_CAP_VOLUME_ISCSI_CHAP_AUTHENTICATION,
00371 LSM_CAP_ACCESS_GROUP_CREATE_WWPN,
00372 LSM_CAP_ACCESS_GROUP_INITIATOR_ADD_WWPN,
00373 LSM_CAP_ACCESS_GROUP_INITIATOR_DELETE,
00374 LSM_CAP_ACCESS_GROUP_DELETE,
00375 LSM_CAP_VOLUMES_ACCESSIBLE_BY_ACCESS_GROUP,
00376 LSM_CAP_ACCESS_GROUPS_GRANTED_TO_VOLUME,
00377 LSM_CAP_VOLUME_CHILD_DEPENDENCY,
00378 LSM_CAP_VOLUME_CHILD_DEPENDENCY_RM,
00379 LSM_CAP_FS,
00380 LSM_CAP_FS_DELETE,
00381 LSM_CAP_FS_RESIZE,
00382 LSM_CAP_FS_CREATE,
00383 LSM_CAP_FS_CLONE,
00384 LSM_CAP_FILE_CLONE,
00385 LSM_CAP_FS_SNAPSHOTS,
00386 LSM_CAP_FS_SNAPSHOT_CREATE,
00387 LSM_CAP_FS_SNAPSHOT_DELETE,
00388 LSM_CAP_FS_SNAPSHOT_RESTORE,
00389 LSM_CAP_FS_SNAPSHOT_RESTORE_SPECIFIC_FILES,
00390 LSM_CAP_FS_CHILD_DEPENDENCY,
00391 LSM_CAP_FS_CHILD_DEPENDENCY_RM,
00392 LSM_CAP_FS_CHILD_DEPENDENCY_RM_SPECIFIC_FILES,
00393 LSM_CAP_EXPORT_AUTH,
00394 LSM_CAP_EXPORTS,
00395 LSM_CAP_EXPORT_FS,
00396 LSM_CAP_EXPORT_REMOVE,
00397 LSM_CAP_VOLUME_RAID_INFO,
00398 LSM_CAP_POOL_MEMBER_INFO, -1);
00399
00400 if (LSM_ERR_OK != rc) {
00401 lsm_capability_record_free(*cap);
00402 *cap = NULL;
00403 }
00404 }
00405 return rc;
00406 }
00407
00408 static int job_status(lsm_plugin_ptr c, const char *job_id,
00409 lsm_job_status * status, uint8_t * percent_complete,
00410 lsm_data_type * t, void **value, lsm_flag flags)
00411 {
00412 int rc = LSM_ERR_OK;
00413 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
00414
00415 if (pd) {
00416 struct allocated_job *val = (struct allocated_job *)
00417 g_hash_table_lookup(pd->jobs, job_id);
00418 if (val) {
00419 *status = LSM_JOB_INPROGRESS;
00420
00421 val->polls += 34;
00422
00423 if ((val->polls) >= 100) {
00424 *t = val->type;
00425 *value = lsm_data_type_copy(val->type, val->return_data);
00426 *status = LSM_JOB_COMPLETE;
00427 *percent_complete = 100;
00428 } else {
00429 *percent_complete = val->polls;
00430 }
00431
00432 } else {
00433 rc = LSM_ERR_NOT_FOUND_JOB;
00434 }
00435 } else {
00436 rc = LSM_ERR_INVALID_ARGUMENT;
00437 }
00438
00439 return rc;
00440 }
00441
00442 static int list_pools(lsm_plugin_ptr c, const char *search_key,
00443 const char *search_value, lsm_pool ** pool_array[],
00444 uint32_t * count, lsm_flag flags)
00445 {
00446 int rc = LSM_ERR_OK;
00447 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
00448 *count = g_hash_table_size(pd->pools);
00449
00450 if (*count) {
00451 *pool_array = lsm_pool_record_array_alloc(*count);
00452 if (*pool_array) {
00453 uint32_t i = 0;
00454 char *k = NULL;
00455 lsm_pool *p = NULL;
00456 GHashTableIter iter;
00457 g_hash_table_iter_init(&iter, pd->pools);
00458 while (g_hash_table_iter_next
00459 (&iter, (gpointer) & k, (gpointer) & p)) {
00460 (*pool_array)[i] = lsm_pool_record_copy(p);
00461 if (!(*pool_array)[i]) {
00462 rc = LSM_ERR_NO_MEMORY;
00463 lsm_pool_record_array_free(*pool_array, i);
00464 *count = 0;
00465 *pool_array = NULL;
00466 break;
00467 }
00468 ++i;
00469 }
00470 } else {
00471 rc = lsm_log_error_basic(c, LSM_ERR_NO_MEMORY, "ENOMEM");
00472 }
00473 }
00474
00475 if (LSM_ERR_OK == rc) {
00476 lsm_plug_pool_search_filter(search_key, search_value, *pool_array,
00477 count);
00478 }
00479
00480 return rc;
00481 }
00482
00483 static int list_systems(lsm_plugin_ptr c, lsm_system ** systems[],
00484 uint32_t * system_count, lsm_flag flags)
00485 {
00486 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
00487
00488 if (pd) {
00489 *system_count = pd->num_systems;
00490 *systems = lsm_system_record_array_alloc(MAX_SYSTEMS);
00491
00492 if (*systems) {
00493 (*systems)[0] = lsm_system_record_copy(pd->system[0]);
00494
00495 if ((*systems)[0]) {
00496 return LSM_ERR_OK;
00497 } else {
00498 lsm_system_record_array_free(*systems, pd->num_systems);
00499 }
00500 }
00501 return LSM_ERR_NO_MEMORY;
00502 } else {
00503 return LSM_ERR_INVALID_ARGUMENT;
00504 }
00505 }
00506
00507 static int job_free(lsm_plugin_ptr c, char *job_id, lsm_flag flags)
00508 {
00509 int rc = LSM_ERR_OK;
00510 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
00511
00512 if (pd) {
00513 if (!g_hash_table_remove(pd->jobs, job_id)) {
00514 rc = LSM_ERR_NOT_FOUND_JOB;
00515 }
00516 } else {
00517 rc = LSM_ERR_INVALID_ARGUMENT;
00518 }
00519
00520 return rc;
00521 }
00522
00523 static struct lsm_mgmt_ops_v1 mgm_ops = {
00524 tmo_set,
00525 tmo_get,
00526 cap,
00527 job_status,
00528 job_free,
00529 list_pools,
00530 list_systems,
00531 };
00532
00533 static int list_volumes(lsm_plugin_ptr c, const char *search_key,
00534 const char *search_value,
00535 lsm_volume ** vols[], uint32_t * count,
00536 lsm_flag flags)
00537 {
00538 int rc = LSM_ERR_OK;
00539 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
00540 *count = g_hash_table_size(pd->volumes);
00541
00542 if (*count) {
00543 *vols = lsm_volume_record_array_alloc(*count);
00544 if (*vols) {
00545 uint32_t i = 0;
00546 char *k = NULL;
00547 struct allocated_volume *vol;
00548 GHashTableIter iter;
00549 g_hash_table_iter_init(&iter, pd->volumes);
00550 while (g_hash_table_iter_next
00551 (&iter, (gpointer) & k, (gpointer) & vol)) {
00552 (*vols)[i] = lsm_volume_record_copy(vol->v);
00553 if (!(*vols)[i]) {
00554 rc = LSM_ERR_NO_MEMORY;
00555 lsm_volume_record_array_free(*vols, i);
00556 *count = 0;
00557 *vols = NULL;
00558 break;
00559 }
00560 ++i;
00561 }
00562 } else {
00563 rc = lsm_log_error_basic(c, LSM_ERR_NO_MEMORY, "ENOMEM");
00564 }
00565 }
00566
00567 if (LSM_ERR_OK == rc) {
00568 lsm_plug_volume_search_filter(search_key, search_value, *vols,
00569 count);
00570 }
00571
00572 return rc;
00573 }
00574
00575 static int list_disks(lsm_plugin_ptr c, const char *search_key,
00576 const char *search_value, lsm_disk ** disks[],
00577 uint32_t * count, lsm_flag flags)
00578 {
00579 int rc = LSM_ERR_OK;
00580 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
00581 *count = g_hash_table_size(pd->disks);
00582
00583
00584 if (*count) {
00585 *disks = lsm_disk_record_array_alloc(*count);
00586 if (*disks) {
00587 uint32_t i = 0;
00588 char *k = NULL;
00589 lsm_disk *disk;
00590 GHashTableIter iter;
00591 g_hash_table_iter_init(&iter, pd->disks);
00592 while (g_hash_table_iter_next
00593 (&iter, (gpointer) & k, (gpointer) & disk)) {
00594 (*disks)[i] = lsm_disk_record_copy(disk);
00595 if (!(*disks)[i]) {
00596 rc = LSM_ERR_NO_MEMORY;
00597 lsm_disk_record_array_free(*disks, i);
00598 *count = 0;
00599 *disks = NULL;
00600 break;
00601 }
00602 ++i;
00603 }
00604 } else {
00605 rc = lsm_log_error_basic(c, LSM_ERR_NO_MEMORY, "ENOMEM");
00606 }
00607 }
00608
00609 if (LSM_ERR_OK == rc) {
00610 lsm_plug_disk_search_filter(search_key, search_value, *disks,
00611 count);
00612 }
00613
00614 return rc;
00615 }
00616
00617 static int list_targets(lsm_plugin_ptr c, const char *search_key,
00618 const char *search_value, lsm_target_port ** tp[],
00619 uint32_t * count, lsm_flag flags)
00620 {
00621 uint32_t i = 0;
00622 const char p0[] = "50:0a:09:86:99:4b:8d:c5";
00623 const char p1[] = "50:0a:09:86:99:4b:8d:c6";
00624 int rc = LSM_ERR_OK;
00625
00626 *count = 5;
00627 *tp = lsm_target_port_record_array_alloc(*count);
00628
00629 if (*tp) {
00630 (*tp)[0] = lsm_target_port_record_alloc("TGT_PORT_ID_01",
00631 LSM_TARGET_PORT_TYPE_FC, p0,
00632 p0, p0, "FC_a_0b", sys_id,
00633 NULL);
00634
00635 (*tp)[1] = lsm_target_port_record_alloc("TGT_PORT_ID_02",
00636 LSM_TARGET_PORT_TYPE_FCOE,
00637 p1, p1, p1, "FC_a_0c",
00638 sys_id, NULL);
00639
00640 (*tp)[2] = lsm_target_port_record_alloc("TGT_PORT_ID_03",
00641 LSM_TARGET_PORT_TYPE_ISCSI,
00642 "iqn.1986-05.com.example:sim-tgt-03",
00643 "sim-iscsi-tgt-3.example.com:3260",
00644 "a4:4e:31:47:f4:e0",
00645 "iSCSI_c_0d", sys_id, NULL);
00646
00647 (*tp)[3] = lsm_target_port_record_alloc("TGT_PORT_ID_04",
00648 LSM_TARGET_PORT_TYPE_ISCSI,
00649 "iqn.1986-05.com.example:sim-tgt-03",
00650 "10.0.0.1:3260",
00651 "a4:4e:31:47:f4:e1",
00652 "iSCSI_c_0e", sys_id, NULL);
00653
00654 (*tp)[4] = lsm_target_port_record_alloc("TGT_PORT_ID_05",
00655 LSM_TARGET_PORT_TYPE_ISCSI,
00656 "iqn.1986-05.com.example:sim-tgt-03",
00657 "[2001:470:1f09:efe:a64e:31ff::1]:3260",
00658 "a4:4e:31:47:f4:e1",
00659 "iSCSI_c_0e", sys_id, NULL);
00660
00661 for (i = 0; i < *count; ++i) {
00662 if (!(*tp)[i]) {
00663 rc = lsm_log_error_basic(c, LSM_ERR_NO_MEMORY, "ENOMEM");
00664 lsm_target_port_record_array_free(*tp, *count);
00665 *count = 0;
00666 break;
00667 }
00668 }
00669 } else {
00670 rc = lsm_log_error_basic(c, LSM_ERR_NO_MEMORY, "ENOMEM");
00671 *count = 0;
00672 }
00673
00674 if (LSM_ERR_OK == rc) {
00675 lsm_plug_target_port_search_filter(search_key, search_value, *tp,
00676 count);
00677 }
00678
00679 return rc;
00680 }
00681
00682 static uint64_t pool_allocate(lsm_pool * p, uint64_t size)
00683 {
00684 uint64_t rounded_size = 0;
00685 uint64_t free_space = lsm_pool_free_space_get(p);
00686
00687 rounded_size = (size / BS) * BS;
00688
00689 if (free_space >= rounded_size) {
00690 free_space -= rounded_size;
00691 lsm_pool_free_space_set(p, free_space);
00692 } else {
00693 rounded_size = 0;
00694 }
00695 return rounded_size;
00696 }
00697
00698 void pool_deallocate(lsm_pool * p, uint64_t size)
00699 {
00700 uint64_t free_space = lsm_pool_free_space_get(p);
00701
00702 free_space += size;
00703 lsm_pool_free_space_set(p, free_space);
00704 }
00705
00706 static lsm_pool *find_pool(struct plugin_data *pd, const char *pool_id)
00707 {
00708 return (lsm_pool *) g_hash_table_lookup(pd->pools, pool_id);
00709 }
00710
00711 static struct allocated_volume *find_volume(struct plugin_data *pd,
00712 const char *vol_id)
00713 {
00714 struct allocated_volume *rc = g_hash_table_lookup(pd->volumes, vol_id);
00715 return rc;
00716 }
00717
00718 static struct allocated_volume *find_volume_name(struct plugin_data *pd,
00719 const char *name)
00720 {
00721 struct allocated_volume *found = NULL;
00722 char *k = NULL;
00723 struct allocated_volume *vol;
00724 GHashTableIter iter;
00725 g_hash_table_iter_init(&iter, pd->volumes);
00726 while (g_hash_table_iter_next(&iter, (gpointer) & k, (gpointer) & vol)) {
00727 if (strcmp(lsm_volume_name_get(vol->v), name) == 0) {
00728 found = vol;
00729 break;
00730 }
00731 }
00732 return found;
00733 }
00734
00735 static int volume_create(lsm_plugin_ptr c, lsm_pool * pool,
00736 const char *volume_name, uint64_t size,
00737 lsm_volume_provision_type provisioning,
00738 lsm_volume ** new_volume, char **job,
00739 lsm_flag flags)
00740 {
00741 int rc = LSM_ERR_OK;
00742
00743 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
00744 lsm_pool *p = find_pool(pd, lsm_pool_id_get(pool));
00745
00746 if (p) {
00747 if (!find_volume_name(pd, volume_name)) {
00748 uint64_t allocated_size = pool_allocate(p, size);
00749 if (allocated_size) {
00750 char *id = md5(volume_name);
00751
00752
00753
00754 lsm_volume *v = lsm_volume_record_alloc(id, volume_name,
00755 "60a980003246694a412b45673342616e",
00756 BS, allocated_size/BS, 0, sys_id,
00757 lsm_pool_id_get(pool), NULL);
00758
00759 lsm_volume *to_store = lsm_volume_record_copy(v);
00760 struct allocated_volume *av =
00761 malloc(sizeof(struct allocated_volume));
00762
00763 if (v && av && to_store) {
00764 av->v = to_store;
00765 av->p = p;
00766
00767
00768
00769
00770
00771 g_hash_table_insert(pd->volumes, (gpointer)
00772 strdup(lsm_volume_id_get(to_store)),
00773 (gpointer) av);
00774
00775 rc = create_job(pd, job, LSM_DATA_TYPE_VOLUME, v,
00776 (void **) new_volume);
00777
00778 } else {
00779 free(av);
00780 lsm_volume_record_free(v);
00781 lsm_volume_record_free(to_store);
00782 rc = lsm_log_error_basic(c, LSM_ERR_NO_MEMORY,
00783 "Check for leaks");
00784 }
00785
00786 } else {
00787 rc = lsm_log_error_basic(c, LSM_ERR_NOT_ENOUGH_SPACE,
00788 "Insufficient space in pool");
00789 }
00790
00791 } else {
00792 rc = lsm_log_error_basic(c, LSM_ERR_NAME_CONFLICT,
00793 "Existing volume " "with name");
00794 }
00795 } else {
00796 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_POOL,
00797 "Pool not found!");
00798 }
00799 return rc;
00800 }
00801
00802 static int volume_replicate(lsm_plugin_ptr c, lsm_pool * pool,
00803 lsm_replication_type rep_type,
00804 lsm_volume * volume_src, const char *name,
00805 lsm_volume ** new_replicant, char **job,
00806 lsm_flag flags)
00807 {
00808 int rc = LSM_ERR_OK;
00809 lsm_pool *pool_to_use = NULL;
00810
00811 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
00812
00813 if (pool) {
00814 pool_to_use = find_pool(pd, lsm_pool_id_get(pool));
00815 } else {
00816 pool_to_use = find_pool(pd, lsm_volume_pool_id_get(volume_src));
00817 }
00818
00819 if (!pool_to_use) {
00820 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_POOL,
00821 "Pool not found!");
00822 } else {
00823 if (find_volume(pd, lsm_volume_id_get(volume_src))) {
00824 rc = volume_create(c, pool_to_use, name,
00825 lsm_volume_number_of_blocks_get(volume_src) *
00826 BS, LSM_VOLUME_PROVISION_DEFAULT,
00827 new_replicant, job, flags);
00828 } else {
00829 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_VOLUME,
00830 "Volume not found!");
00831 }
00832 }
00833 return rc;
00834 }
00835
00836 static int volume_replicate_range_bs(lsm_plugin_ptr c, lsm_system * system,
00837 uint32_t * bs, lsm_flag flags)
00838 {
00839 *bs = BS;
00840 return LSM_ERR_OK;
00841 }
00842
00843 static int volume_replicate_range(lsm_plugin_ptr c,
00844 lsm_replication_type rep_type,
00845 lsm_volume * source,
00846 lsm_volume * dest,
00847 lsm_block_range ** ranges,
00848 uint32_t num_ranges, char **job,
00849 lsm_flag flags)
00850 {
00851 int rc = LSM_ERR_OK;
00852 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
00853
00854 struct allocated_volume *src_v =
00855 find_volume(pd, lsm_volume_id_get(source));
00856 struct allocated_volume *dest_v =
00857 find_volume(pd, lsm_volume_id_get(dest));
00858
00859 if (!src_v || !dest_v) {
00860 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_VOLUME,
00861 "Src or dest volumes not found!");
00862 } else {
00863 rc = create_job(pd, job, LSM_DATA_TYPE_NONE, NULL, NULL);
00864 }
00865
00866 return rc;
00867 }
00868
00869 static int volume_resize(lsm_plugin_ptr c, lsm_volume * volume,
00870 uint64_t new_size, lsm_volume ** resized_volume,
00871 char **job, lsm_flag flags)
00872 {
00873 int rc = LSM_ERR_OK;
00874 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
00875 struct allocated_volume *av =
00876 find_volume(pd, lsm_volume_id_get(volume));
00877
00878 if (av) {
00879 lsm_volume *v = av->v;
00880 lsm_pool *p = av->p;
00881 uint64_t curr_size = lsm_volume_number_of_blocks_get(v) * BS;
00882
00883 pool_deallocate(p, curr_size);
00884 uint64_t resized_size = pool_allocate(p, new_size);
00885 if (resized_size) {
00886 lsm_volume *vp = lsm_volume_record_alloc(lsm_volume_id_get(v),
00887 lsm_volume_name_get(v),
00888 lsm_volume_vpd83_get(v),
00889 lsm_volume_block_size_get(v),
00890 resized_size/BS, 0, sys_id,
00891 lsm_volume_pool_id_get(volume),
00892 NULL);
00893
00894 if( vp ) {
00895 av->v = vp;
00896 lsm_volume_record_free(v);
00897 rc = create_job(pd, job, LSM_DATA_TYPE_VOLUME,
00898 lsm_volume_record_copy(vp),
00899 (void **) resized_volume);
00900 } else {
00901 pool_deallocate(p, resized_size);
00902 pool_allocate(p, curr_size);
00903 rc = lsm_log_error_basic(c, LSM_ERR_NO_MEMORY, "ENOMEM");
00904 }
00905
00906 } else {
00907
00908 pool_allocate(p, curr_size);
00909 rc = lsm_log_error_basic(c, LSM_ERR_NOT_ENOUGH_SPACE,
00910 "Insufficient space in pool");
00911 }
00912
00913 } else {
00914 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_VOLUME,
00915 "volume not found!");
00916 }
00917 return rc;
00918 }
00919
00920 static int _volume_delete(lsm_plugin_ptr c, const char *volume_id)
00921 {
00922 int rc = LSM_ERR_OK;
00923 GHashTableIter iter;
00924 char *k = NULL;
00925 GHashTable *v = NULL;
00926 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
00927 struct allocated_volume *av = find_volume(pd, volume_id);
00928
00929 if (av) {
00930 lsm_volume *vp = av->v;
00931 pool_deallocate(av->p, lsm_volume_number_of_blocks_get(vp) * BS);
00932
00933 g_hash_table_remove(pd->volumes, volume_id);
00934
00935 g_hash_table_iter_init(&iter, pd->group_grant);
00936 while (g_hash_table_iter_next
00937 (&iter, (gpointer) & k, (gpointer) & v)) {
00938 if (g_hash_table_lookup(v, volume_id)) {
00939 g_hash_table_remove(v, volume_id);
00940 }
00941 }
00942
00943 } else {
00944 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_VOLUME,
00945 "volume not found!");
00946 }
00947 return rc;
00948 }
00949
00950 static int volume_delete(lsm_plugin_ptr c, lsm_volume * volume,
00951 char **job, lsm_flag flags)
00952 {
00953 lsm_access_group **groups = NULL;
00954 uint32_t count = 0;
00955
00956 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
00957
00958
00959
00960 int rc = ag_granted_to_volume(c, volume, &groups, &count,
00961 LSM_CLIENT_FLAG_RSVD);
00962
00963 if (LSM_ERR_OK == rc) {
00964 lsm_access_group_record_array_free(groups, count);
00965 groups = NULL;
00966
00967 if (!count) {
00968
00969 rc = _volume_delete(c, lsm_volume_id_get(volume));
00970
00971 if (LSM_ERR_OK == rc) {
00972 rc = create_job(pd, job, LSM_DATA_TYPE_NONE, NULL, NULL);
00973 }
00974 } else {
00975 rc = lsm_log_error_basic(c, LSM_ERR_IS_MASKED,
00976 "Volume is masked!");
00977 }
00978 }
00979 return rc;
00980 }
00981
00982 static int volume_raid_info(lsm_plugin_ptr c, lsm_volume * volume,
00983 lsm_volume_raid_type * raid_type,
00984 uint32_t * strip_size, uint32_t * disk_count,
00985 uint32_t * min_io_size, uint32_t * opt_io_size,
00986 lsm_flag flags)
00987 {
00988 int rc = LSM_ERR_OK;
00989 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
00990 struct allocated_volume *av =
00991 find_volume(pd, lsm_volume_id_get(volume));
00992
00993 if (!av) {
00994 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_VOLUME,
00995 "volume not found!");
00996 }
00997
00998 *raid_type = LSM_VOLUME_RAID_TYPE_UNKNOWN;
00999 *strip_size = LSM_VOLUME_STRIP_SIZE_UNKNOWN;
01000 *disk_count = LSM_VOLUME_DISK_COUNT_UNKNOWN;
01001 *min_io_size = LSM_VOLUME_MIN_IO_SIZE_UNKNOWN;
01002 *opt_io_size = LSM_VOLUME_OPT_IO_SIZE_UNKNOWN;
01003 return rc;
01004 }
01005
01006 static int pool_member_info(lsm_plugin_ptr c, lsm_pool * pool,
01007 lsm_volume_raid_type * raid_type,
01008 lsm_pool_member_type * member_type,
01009 lsm_string_list ** member_ids, lsm_flag flags)
01010 {
01011 int rc = LSM_ERR_OK;
01012 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01013 lsm_pool *p = find_pool(pd, lsm_pool_id_get(pool));
01014
01015 if (!p) {
01016 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_POOL,
01017 "Pool not found!");
01018 }
01019
01020 *raid_type = LSM_VOLUME_RAID_TYPE_UNKNOWN;
01021 *member_type = LSM_POOL_MEMBER_TYPE_UNKNOWN;
01022 *member_ids = NULL;
01023 return rc;
01024 }
01025
01026 static int volume_raid_create_cap_get(lsm_plugin_ptr c, lsm_system * system,
01027 uint32_t ** supported_raid_types,
01028 uint32_t * supported_raid_type_count,
01029 uint32_t ** supported_strip_sizes,
01030 uint32_t * supported_strip_size_count,
01031 lsm_flag flags)
01032 {
01033 return LSM_ERR_NO_SUPPORT;
01034 }
01035
01036 static int volume_raid_create(lsm_plugin_ptr c, const char *name,
01037 lsm_volume_raid_type raid_type,
01038 lsm_disk * disks[], uint32_t disk_count,
01039 uint32_t strip_size, lsm_volume ** new_volume,
01040 lsm_flag flags)
01041 {
01042 return LSM_ERR_NO_SUPPORT;
01043 }
01044
01045 static struct lsm_ops_v1_2 ops_v1_2 = {
01046 volume_raid_info,
01047 pool_member_info,
01048 volume_raid_create_cap_get,
01049 volume_raid_create,
01050 };
01051
01052 static int volume_enable_disable(lsm_plugin_ptr c, lsm_volume * v,
01053 lsm_flag flags)
01054 {
01055 int rc = LSM_ERR_OK;
01056 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01057 struct allocated_volume *av = find_volume(pd, lsm_volume_id_get(v));
01058
01059 if (!av) {
01060 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_VOLUME,
01061 "volume not found!");
01062 }
01063 return rc;
01064 }
01065
01066 static int access_group_list(lsm_plugin_ptr c,
01067 const char *search_key,
01068 const char *search_value,
01069 lsm_access_group ** groups[],
01070 uint32_t * group_count, lsm_flag flags)
01071 {
01072 int rc = LSM_ERR_OK;
01073 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01074
01075 *group_count = g_hash_table_size(pd->access_groups);
01076
01077 if (*group_count) {
01078 *groups = lsm_access_group_record_array_alloc(*group_count);
01079 if (*groups) {
01080 int i = 0;
01081 char *key = NULL;
01082 struct allocated_ag *val = NULL;
01083 GHashTableIter iter;
01084
01085 g_hash_table_iter_init(&iter, pd->access_groups);
01086
01087 while (g_hash_table_iter_next(&iter, (gpointer) & key,
01088 (gpointer) & val)) {
01089 (*groups)[i] = lsm_access_group_record_copy(val->ag);
01090 if (!(*groups)[i]) {
01091 rc = LSM_ERR_NO_MEMORY;
01092 lsm_access_group_record_array_free(*groups, i);
01093 *group_count = 0;
01094 groups = NULL;
01095 break;
01096 }
01097 ++i;
01098 }
01099 } else {
01100 rc = LSM_ERR_NO_MEMORY;
01101 }
01102 }
01103
01104 if (LSM_ERR_OK == rc) {
01105 lsm_plug_access_group_search_filter(search_key, search_value,
01106 *groups, group_count);
01107 }
01108
01109 return rc;
01110 }
01111
01112 static int _find_dup_init(struct plugin_data *pd, const char *initiator_id)
01113 {
01114 GList *all_aags = g_hash_table_get_values(pd->access_groups);
01115 guint y;
01116 int rc = 1;
01117 for (y = 0; y < g_list_length(all_aags); ++y) {
01118 struct allocated_ag *cur_aag =
01119 (struct allocated_ag *) g_list_nth_data(all_aags, y);
01120 if (cur_aag) {
01121 lsm_string_list *inits =
01122 lsm_access_group_initiator_id_get(cur_aag->ag);
01123 int i;
01124 for (i = 0; i < lsm_string_list_size(inits); ++i) {
01125 const char *cur_init_id =
01126 lsm_string_list_elem_get(inits, i);
01127 if (strcmp(initiator_id, cur_init_id) == 0) {
01128 rc = 0;
01129 break;
01130 }
01131 }
01132 if (rc == 0) {
01133 break;
01134 } else {
01135 cur_aag = (struct allocated_ag *) g_list_next(all_aags);
01136 }
01137 }
01138 }
01139 g_list_free(all_aags);
01140 return rc;
01141 }
01142
01143 static int access_group_create(lsm_plugin_ptr c,
01144 const char *name,
01145 const char *initiator_id,
01146 lsm_access_group_init_type id_type,
01147 lsm_system * system,
01148 lsm_access_group ** access_group,
01149 lsm_flag flags)
01150 {
01151 int rc = LSM_ERR_OK;
01152 lsm_access_group *ag = NULL;
01153 struct allocated_ag *aag = NULL;
01154 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01155 char *id = strdup(md5(name));
01156
01157 struct allocated_ag *find = (struct allocated_ag *)
01158 g_hash_table_lookup(pd->access_groups, id);
01159
01160 if (!find) {
01161
01162 if (_find_dup_init(pd, initiator_id) == 0) {
01163 rc = lsm_log_error_basic(c, LSM_ERR_EXISTS_INITIATOR,
01164 "Requested initiator is used by other access group");
01165 } else {
01166 lsm_string_list *initiators = lsm_string_list_alloc(1);
01167 if (initiators && id &&
01168 (LSM_ERR_OK ==
01169 lsm_string_list_elem_set(initiators, 0, initiator_id))) {
01170 ag = lsm_access_group_record_alloc(id, name, initiators,
01171 id_type,
01172 lsm_system_id_get
01173 (system), NULL);
01174 aag = alloc_allocated_ag(ag, id_type);
01175 if (ag && aag) {
01176 g_hash_table_insert(pd->access_groups, (gpointer) id,
01177 (gpointer) aag);
01178 *access_group = lsm_access_group_record_copy(ag);
01179 } else {
01180 free_allocated_ag(aag);
01181 lsm_access_group_record_free(ag);
01182 rc = lsm_log_error_basic(c, LSM_ERR_NO_MEMORY,
01183 "ENOMEM");
01184 }
01185 } else {
01186 rc = lsm_log_error_basic(c, LSM_ERR_NO_MEMORY, "ENOMEM");
01187 }
01188
01189 lsm_string_list_free(initiators);
01190 }
01191 } else {
01192 rc = lsm_log_error_basic(c, LSM_ERR_NAME_CONFLICT,
01193 "access group with same id found");
01194 }
01195
01196
01197
01198
01199
01200 if (LSM_ERR_OK != rc) {
01201 free(id);
01202 }
01203
01204 return rc;
01205 }
01206
01207 static int access_group_delete(lsm_plugin_ptr c,
01208 lsm_access_group * group, lsm_flag flags)
01209 {
01210 int rc = LSM_ERR_OK;
01211 lsm_volume **volumes = NULL;
01212 uint32_t count = 0;
01213
01214 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01215 const char *id = lsm_access_group_id_get(group);
01216
01217 rc = vol_accessible_by_ag(c, group, &volumes, &count,
01218 LSM_CLIENT_FLAG_RSVD);
01219 lsm_volume_record_array_free(volumes, count);
01220 volumes = NULL;
01221
01222 if (rc == LSM_ERR_OK) {
01223 if (count) {
01224 rc = lsm_log_error_basic(c, LSM_ERR_IS_MASKED,
01225 "access group has masked volumes!");
01226 } else {
01227 gboolean r =
01228 g_hash_table_remove(pd->access_groups, (gpointer) id);
01229
01230 if (!r) {
01231 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_ACCESS_GROUP,
01232 "access group not found");
01233 } else {
01234 g_hash_table_remove(pd->group_grant, id);
01235 }
01236
01237 if (!g_hash_table_size(pd->access_groups)) {
01238 assert(g_hash_table_size(pd->group_grant) == 0);
01239 }
01240 }
01241 }
01242
01243 return rc;
01244 }
01245
01246 static int access_group_initiator_add(lsm_plugin_ptr c,
01247 lsm_access_group * group,
01248 const char *initiator_id,
01249 lsm_access_group_init_type id_type,
01250 lsm_access_group **
01251 updated_access_group,
01252 lsm_flag flags)
01253 {
01254 int rc = LSM_ERR_OK;
01255 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01256
01257 struct allocated_ag *find = (struct allocated_ag *)
01258 g_hash_table_lookup(pd->access_groups,
01259 lsm_access_group_id_get(group));
01260
01261 if (find) {
01262 lsm_string_list *inits =
01263 lsm_access_group_initiator_id_get(find->ag);
01264 rc = lsm_string_list_append(inits, initiator_id);
01265
01266 if (LSM_ERR_OK == rc) {
01267 *updated_access_group = lsm_access_group_record_copy(find->ag);
01268 if (!*updated_access_group) {
01269 rc = LSM_ERR_NO_MEMORY;
01270 }
01271 }
01272 } else {
01273 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_ACCESS_GROUP,
01274 "access group not found");
01275 }
01276 return rc;
01277 }
01278
01279 static int access_group_initiator_delete(lsm_plugin_ptr c,
01280 lsm_access_group * group,
01281 const char *initiator_id,
01282 lsm_access_group_init_type id_type,
01283 lsm_access_group **
01284 updated_access_group,
01285 lsm_flag flags)
01286 {
01287 int rc = LSM_ERR_INVALID_ARGUMENT;
01288 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01289
01290 struct allocated_ag *find = (struct allocated_ag *)
01291 g_hash_table_lookup(pd->access_groups,
01292 lsm_access_group_id_get(group));
01293
01294 if (find) {
01295 uint32_t i;
01296 lsm_string_list *inits =
01297 lsm_access_group_initiator_id_get(find->ag);
01298
01299 for (i = 0; i < lsm_string_list_size(inits); ++i) {
01300 if (strcmp(initiator_id, lsm_string_list_elem_get(inits, i)) ==
01301 0) {
01302 lsm_string_list_delete(inits, i);
01303 rc = LSM_ERR_OK;
01304 break;
01305 }
01306 }
01307
01308 if (LSM_ERR_OK == rc) {
01309 *updated_access_group = lsm_access_group_record_copy(find->ag);
01310 if (!*updated_access_group) {
01311 rc = LSM_ERR_NO_MEMORY;
01312 }
01313 }
01314
01315 } else {
01316 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_ACCESS_GROUP,
01317 "access group not found");
01318 }
01319 return rc;
01320 }
01321
01322 static int volume_mask(lsm_plugin_ptr c,
01323 lsm_access_group * group,
01324 lsm_volume * volume, lsm_flag flags)
01325 {
01326 int rc = LSM_ERR_OK;
01327 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01328
01329 struct allocated_ag *find = (struct allocated_ag *)
01330 g_hash_table_lookup(pd->access_groups,
01331 lsm_access_group_id_get(group));
01332
01333 struct allocated_volume *av =
01334 find_volume(pd, lsm_volume_id_get(volume));
01335
01336 if (find && av) {
01337 GHashTable *grants = g_hash_table_lookup(pd->group_grant,
01338 lsm_access_group_id_get
01339 (find->ag));
01340 if (!grants) {
01341
01342 GHashTable *grant =
01343 g_hash_table_new_full(g_str_hash, g_str_equal,
01344 free, free);
01345 char *key = strdup(lsm_access_group_id_get(find->ag));
01346 char *vol_id = strdup(lsm_volume_id_get(volume));
01347 int *val = (int *) malloc(sizeof(int));
01348
01349 if (grant && key && val && vol_id) {
01350 *val = 1;
01351
01352
01353 g_hash_table_insert(grant, vol_id, val);
01354
01355
01356 g_hash_table_insert(pd->group_grant, key, grant);
01357
01358 } else {
01359 rc = LSM_ERR_NO_MEMORY;
01360 free(key);
01361 free(val);
01362 free(vol_id);
01363 if (grant) {
01364 g_hash_table_destroy(grant);
01365 grant = NULL;
01366 }
01367 }
01368
01369 } else {
01370
01371 char *vol_id =
01372 g_hash_table_lookup(grants, lsm_volume_id_get(volume));
01373 if (!vol_id) {
01374 vol_id = strdup(lsm_volume_id_get(volume));
01375 int *val = (int *) malloc(sizeof(int));
01376 if (vol_id && val) {
01377 *val = 1;
01378 g_hash_table_insert(grants, vol_id, val);
01379 } else {
01380 rc = LSM_ERR_NO_MEMORY;
01381 free(vol_id);
01382 free(val);
01383 }
01384
01385 } else {
01386 rc = LSM_ERR_NO_STATE_CHANGE;
01387 }
01388 }
01389 } else {
01390 if (!av) {
01391 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_VOLUME,
01392 "volume not found");
01393 } else {
01394 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_ACCESS_GROUP,
01395 "access group not found");
01396 }
01397 }
01398 return rc;
01399 }
01400
01401 static int volume_unmask(lsm_plugin_ptr c,
01402 lsm_access_group * group,
01403 lsm_volume * volume, lsm_flag flags)
01404 {
01405 int rc = LSM_ERR_NO_STATE_CHANGE;
01406 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01407
01408 struct allocated_ag *find = (struct allocated_ag *)
01409 g_hash_table_lookup(pd->access_groups,
01410 lsm_access_group_id_get(group));
01411
01412 struct allocated_volume *av =
01413 find_volume(pd, lsm_volume_id_get(volume));
01414
01415 if (find && av) {
01416 GHashTable *grants = g_hash_table_lookup(pd->group_grant,
01417 lsm_access_group_id_get
01418 (find->ag));
01419
01420 if (grants) {
01421 char *vol_id =
01422 g_hash_table_lookup(grants, lsm_volume_id_get(volume));
01423 if (vol_id) {
01424 g_hash_table_remove(grants, lsm_volume_id_get(volume));
01425 rc = LSM_ERR_OK;
01426 } else {
01427 rc = LSM_ERR_NO_STATE_CHANGE;
01428 }
01429 }
01430
01431 } else {
01432 if (!av) {
01433 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_VOLUME,
01434 "volume not found");
01435 } else {
01436 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_ACCESS_GROUP,
01437 "access group not found");
01438 }
01439 }
01440 return rc;
01441 }
01442
01443 static lsm_volume *get_volume_by_id(struct plugin_data *pd, const char *id)
01444 {
01445 struct allocated_volume *av = find_volume(pd, id);
01446 if (av) {
01447 return av->v;
01448 }
01449 return NULL;
01450 }
01451
01452 static int vol_accessible_by_ag(lsm_plugin_ptr c,
01453 lsm_access_group * group,
01454 lsm_volume ** volumes[],
01455 uint32_t * count, lsm_flag flags)
01456 {
01457 int rc = LSM_ERR_OK;
01458 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01459
01460 struct allocated_ag *find = (struct allocated_ag *)
01461 g_hash_table_lookup(pd->access_groups,
01462 lsm_access_group_id_get(group));
01463 if (find) {
01464 GHashTable *grants = g_hash_table_lookup(pd->group_grant,
01465 lsm_access_group_id_get
01466 (find->ag));
01467 *count = 0;
01468
01469 if (grants && g_hash_table_size(grants)) {
01470 *count = g_hash_table_size(grants);
01471 GList *keys = g_hash_table_get_keys(grants);
01472 *volumes = lsm_volume_record_array_alloc(*count);
01473
01474 if (keys && *volumes) {
01475 GList *curr = NULL;
01476 int i = 0;
01477
01478 for (curr = g_list_first(keys);
01479 curr != NULL; curr = g_list_next(curr), ++i) {
01480
01481 (*volumes)[i] =
01482 lsm_volume_record_copy(get_volume_by_id
01483 (pd, (char *) curr->data));
01484 if (!(*volumes)[i]) {
01485 rc = LSM_ERR_NO_MEMORY;
01486 lsm_volume_record_array_free(*volumes, i);
01487 *volumes = NULL;
01488 *count = 0;
01489 break;
01490 }
01491 }
01492
01493
01494 g_list_free(keys);
01495 } else {
01496 rc = LSM_ERR_NO_MEMORY;
01497 }
01498 }
01499
01500 } else {
01501 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_ACCESS_GROUP,
01502 "access group not found");
01503 }
01504 return rc;
01505 }
01506
01507 static lsm_access_group *access_group_by_id(struct plugin_data *pd,
01508 const char *key)
01509 {
01510 struct allocated_ag *find = g_hash_table_lookup(pd->access_groups, key);
01511 if (find) {
01512 return find->ag;
01513 }
01514 return NULL;
01515 }
01516
01517 static int ag_granted_to_volume(lsm_plugin_ptr c,
01518 lsm_volume * volume,
01519 lsm_access_group ** groups[],
01520 uint32_t * count, lsm_flag flags)
01521 {
01522 int rc = LSM_ERR_OK;
01523 GHashTableIter iter;
01524 char *k = NULL;
01525 GHashTable *v = NULL;
01526 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01527 const char *volume_id = lsm_volume_id_get(volume);
01528 g_hash_table_iter_init(&iter, pd->group_grant);
01529 GSList *result = NULL;
01530
01531 *count = 0;
01532
01533 while (g_hash_table_iter_next(&iter, (gpointer) & k, (gpointer) & v)) {
01534 if (g_hash_table_lookup(v, volume_id)) {
01535 *count += 1;
01536 result = g_slist_prepend(result, access_group_by_id(pd, k));
01537 }
01538 }
01539
01540 if (*count) {
01541 int i = 0;
01542 *groups = lsm_access_group_record_array_alloc(*count);
01543 GSList *siter = NULL;
01544
01545 if (*groups) {
01546 for (siter = result; siter; siter = g_slist_next(siter), i++) {
01547 (*groups)[i] =
01548 lsm_access_group_record_copy((lsm_access_group *)
01549 siter->data);
01550
01551 if (!(*groups)[i]) {
01552 rc = LSM_ERR_NO_MEMORY;
01553 lsm_access_group_record_array_free(*groups, i);
01554 *groups = NULL;
01555 *count = 0;
01556 break;
01557 }
01558 }
01559 } else {
01560 rc = LSM_ERR_NO_MEMORY;
01561 }
01562 }
01563
01564 if (result) {
01565 g_slist_free(result);
01566 }
01567 return rc;
01568 }
01569
01570 int static volume_dependency(lsm_plugin_ptr c,
01571 lsm_volume * volume,
01572 uint8_t * yes, lsm_flag flags)
01573 {
01574 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01575 struct allocated_volume *av =
01576 find_volume(pd, lsm_volume_id_get(volume));
01577
01578 if (av) {
01579 *yes = 0;
01580 return LSM_ERR_OK;
01581 } else {
01582 return LSM_ERR_NOT_FOUND_VOLUME;
01583 }
01584 }
01585
01586 int static volume_dependency_rm(lsm_plugin_ptr c,
01587 lsm_volume * volume,
01588 char **job, lsm_flag flags)
01589 {
01590 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01591 struct allocated_volume *av =
01592 find_volume(pd, lsm_volume_id_get(volume));
01593
01594 if (av) {
01595 return create_job(pd, job, LSM_DATA_TYPE_NONE, NULL, NULL);
01596 } else {
01597 return LSM_ERR_NOT_FOUND_VOLUME;
01598 }
01599 }
01600
01601 static int iscsi_chap_auth(lsm_plugin_ptr c, const char *init_id,
01602 const char *in_user, const char *in_password,
01603 const char *out_user, const char *out_password,
01604 lsm_flag flags)
01605 {
01606 if (init_id) {
01607 return 0;
01608 }
01609 return LSM_ERR_INVALID_ARGUMENT;
01610 }
01611
01612 static struct lsm_san_ops_v1 san_ops = {
01613 list_volumes,
01614 list_disks,
01615 volume_create,
01616 volume_replicate,
01617 volume_replicate_range_bs,
01618 volume_replicate_range,
01619 volume_resize,
01620 volume_delete,
01621 volume_enable_disable,
01622 volume_enable_disable,
01623 iscsi_chap_auth,
01624 access_group_list,
01625 access_group_create,
01626 access_group_delete,
01627 access_group_initiator_add,
01628 access_group_initiator_delete,
01629 volume_mask,
01630 volume_unmask,
01631 vol_accessible_by_ag,
01632 ag_granted_to_volume,
01633 volume_dependency,
01634 volume_dependency_rm,
01635 list_targets
01636 };
01637
01638 static int fs_list(lsm_plugin_ptr c, const char *search_key,
01639 const char *search_value, lsm_fs ** fs[],
01640 uint32_t * count, lsm_flag flags)
01641 {
01642 int rc = LSM_ERR_OK;
01643 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01644 *count = g_hash_table_size(pd->fs);
01645
01646 if (*count) {
01647 *fs = lsm_fs_record_array_alloc(*count);
01648 if (*fs) {
01649 uint32_t i = 0;
01650 char *k = NULL;
01651 struct allocated_fs *afs = NULL;
01652 GHashTableIter iter;
01653 g_hash_table_iter_init(&iter, pd->fs);
01654 while (g_hash_table_iter_next
01655 (&iter, (gpointer) & k, (gpointer) & afs)) {
01656 (*fs)[i] = lsm_fs_record_copy(afs->fs);
01657 if (!(*fs)[i]) {
01658 rc = LSM_ERR_NO_MEMORY;
01659 lsm_fs_record_array_free(*fs, i);
01660 *count = 0;
01661 *fs = NULL;
01662 break;
01663 }
01664 ++i;
01665 }
01666 } else {
01667 rc = lsm_log_error_basic(c, LSM_ERR_NO_MEMORY, "ENOMEM");
01668 }
01669 }
01670
01671 if (LSM_ERR_OK == rc) {
01672 lsm_plug_fs_search_filter(search_key, search_value, *fs, count);
01673 }
01674
01675 return rc;
01676 }
01677
01678 static int fs_create(lsm_plugin_ptr c, lsm_pool * pool, const char *name,
01679 uint64_t size_bytes, lsm_fs ** fs, char **job,
01680 lsm_flag flags)
01681 {
01682 int rc = LSM_ERR_OK;
01683 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01684
01685 lsm_pool *p = find_pool(pd, lsm_pool_id_get(pool));
01686
01687
01688 if (p && !g_hash_table_lookup(pd->fs, md5(name))) {
01689 uint64_t allocated_size = pool_allocate(p, size_bytes);
01690 if (allocated_size) {
01691 char *id = md5(name);
01692 char *key = strdup(id);
01693 lsm_fs *new_fs = NULL;
01694
01695
01696 lsm_fs *tfs = lsm_fs_record_alloc(id, name, allocated_size,
01697 allocated_size,
01698 lsm_pool_id_get(pool), sys_id,
01699 NULL);
01700 new_fs = lsm_fs_record_copy(tfs);
01701
01702
01703 struct allocated_fs *afs = alloc_fs_record();
01704
01705 if (key && tfs && afs) {
01706 afs->fs = tfs;
01707 afs->p = p;
01708 g_hash_table_insert(pd->fs, key, afs);
01709
01710 rc = create_job(pd, job, LSM_DATA_TYPE_FS, new_fs,
01711 (void **) fs);
01712 } else {
01713 free(key);
01714 lsm_fs_record_free(new_fs);
01715 lsm_fs_record_free(tfs);
01716 free_fs_record(afs);
01717
01718 *fs = NULL;
01719 rc = lsm_log_error_basic(c, LSM_ERR_NO_MEMORY, "ENOMEM");
01720 }
01721 } else {
01722 rc = lsm_log_error_basic(c, LSM_ERR_NOT_ENOUGH_SPACE,
01723 "Insufficient space in pool");
01724 }
01725 } else {
01726 if (p == NULL) {
01727 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_POOL,
01728 "Pool not found!");
01729 } else {
01730 rc = lsm_log_error_basic(c, LSM_ERR_NAME_CONFLICT,
01731 "File system with name exists");
01732 }
01733 }
01734 return rc;
01735 }
01736
01737 static int fs_delete(lsm_plugin_ptr c, lsm_fs * fs, char **job,
01738 lsm_flag flags)
01739 {
01740 int rc = LSM_ERR_OK;
01741 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01742
01743 if (!g_hash_table_remove(pd->fs, lsm_fs_id_get(fs))) {
01744 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_FS, "FS not found!");
01745 } else {
01746 rc = create_job(pd, job, LSM_DATA_TYPE_NONE, NULL, NULL);
01747 }
01748 return rc;
01749 }
01750
01751 static int fs_resize(lsm_plugin_ptr c, lsm_fs * fs,
01752 uint64_t new_size_bytes, lsm_fs * *rfs,
01753 char **job, lsm_flag flags)
01754 {
01755 int rc = LSM_ERR_OK;
01756 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01757 struct allocated_fs *afs =
01758 g_hash_table_lookup(pd->fs, lsm_fs_id_get(fs));
01759
01760 *rfs = NULL;
01761 *job = NULL;
01762
01763 if (afs) {
01764 lsm_pool *p = afs->p;
01765 lsm_fs *tfs = afs->fs;
01766
01767 pool_deallocate(p, lsm_fs_total_space_get(tfs));
01768 uint64_t resized_size = pool_allocate(p, new_size_bytes);
01769
01770 if (resized_size) {
01771
01772 lsm_fs *resized = lsm_fs_record_alloc(lsm_fs_id_get(tfs),
01773 lsm_fs_name_get(tfs),
01774 new_size_bytes,
01775 new_size_bytes,
01776 lsm_fs_pool_id_get(tfs),
01777 lsm_fs_system_id_get(tfs),
01778 NULL);
01779 lsm_fs *returned_copy = lsm_fs_record_copy(resized);
01780
01781 if (resized && returned_copy) {
01782 lsm_fs_record_free(tfs);
01783 afs->fs = resized;
01784
01785 rc = create_job(pd, job, LSM_DATA_TYPE_FS, returned_copy,
01786 (void **) rfs);
01787
01788 } else {
01789 lsm_fs_record_free(resized);
01790 lsm_fs_record_free(returned_copy);
01791 *rfs = NULL;
01792
01793 pool_deallocate(p, new_size_bytes);
01794 pool_allocate(p, lsm_fs_total_space_get(tfs));
01795 rc = lsm_log_error_basic(c, LSM_ERR_NO_MEMORY, "ENOMEM");
01796 }
01797 } else {
01798
01799 pool_allocate(p, lsm_fs_total_space_get(tfs));
01800 rc = lsm_log_error_basic(c, LSM_ERR_NOT_ENOUGH_SPACE,
01801 "Insufficient space in pool");
01802 }
01803
01804 } else {
01805 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_FS,
01806 "file system not found!");
01807 }
01808 return rc;
01809 }
01810
01811 static int fs_clone(lsm_plugin_ptr c, lsm_fs * src_fs,
01812 const char *dest_fs_name, lsm_fs ** cloned_fs,
01813 lsm_fs_ss * optional_snapshot, char **job,
01814 lsm_flag flags)
01815 {
01816 int rc = LSM_ERR_OK;
01817 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01818
01819 struct allocated_fs *find =
01820 g_hash_table_lookup(pd->fs, lsm_fs_id_get(src_fs));
01821
01822 if (find) {
01823 rc = fs_create(c, find->p, dest_fs_name,
01824 lsm_fs_total_space_get(find->fs), cloned_fs, job,
01825 flags);
01826 } else {
01827 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_FS,
01828 "Source fs not found");
01829 }
01830
01831 return rc;
01832 }
01833
01834 static int fs_file_clone(lsm_plugin_ptr c, lsm_fs * fs,
01835 const char *src_file_name,
01836 const char *dest_file_name,
01837 lsm_fs_ss * snapshot, char **job, lsm_flag flags)
01838 {
01839 int rc = LSM_ERR_OK;
01840 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01841
01842 struct allocated_fs *find =
01843 (struct allocated_fs *) g_hash_table_lookup(pd->fs,
01844 lsm_fs_id_get(fs));
01845 if (!find) {
01846 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_FS, "fs not found");
01847 } else {
01848 rc = create_job(pd, job, LSM_DATA_TYPE_NONE, NULL, NULL);
01849 }
01850 return rc;
01851 }
01852
01853 static int fs_child_dependency(lsm_plugin_ptr c, lsm_fs * fs,
01854 lsm_string_list * files, uint8_t * yes)
01855 {
01856 int rc = LSM_ERR_OK;
01857 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01858 if (g_hash_table_lookup(pd->fs, lsm_fs_id_get(fs))) {
01859 *yes = 0;
01860 } else {
01861 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_FS, "fs not found");
01862 }
01863 return rc;
01864 }
01865
01866 static int fs_child_dependency_rm(lsm_plugin_ptr c, lsm_fs * fs,
01867 lsm_string_list * files,
01868 char **job, lsm_flag flags)
01869 {
01870 int rc = LSM_ERR_OK;
01871 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01872 if (!g_hash_table_lookup(pd->fs, lsm_fs_id_get(fs))) {
01873 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_FS, "fs not found");
01874 } else {
01875 rc = create_job(pd, job, LSM_DATA_TYPE_NONE, NULL, NULL);
01876 }
01877 return rc;
01878 }
01879
01880 static int ss_list(lsm_plugin_ptr c, lsm_fs * fs, lsm_fs_ss ** ss[],
01881 uint32_t * count, lsm_flag flags)
01882 {
01883 int rc = LSM_ERR_OK;
01884 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01885
01886 struct allocated_fs *find =
01887 (struct allocated_fs *) g_hash_table_lookup(pd->fs,
01888 lsm_fs_id_get(fs));
01889
01890 if (find) {
01891 char *k = NULL;
01892 lsm_fs_ss *v = NULL;
01893 GHashTableIter iter;
01894
01895 *ss = NULL;
01896 *count = g_hash_table_size(find->ss);
01897
01898 if (*count) {
01899 *ss = lsm_fs_ss_record_array_alloc(*count);
01900 if (*ss) {
01901 int i = 0;
01902 g_hash_table_iter_init(&iter, find->ss);
01903
01904 while (g_hash_table_iter_next(&iter,
01905 (gpointer) & k,
01906 (gpointer) & v)) {
01907 (*ss)[i] = lsm_fs_ss_record_copy(v);
01908 if (!(*ss)[i]) {
01909 rc = lsm_log_error_basic(c, LSM_ERR_NO_MEMORY,
01910 "ENOMEM");
01911 lsm_fs_ss_record_array_free(*ss, i);
01912 *ss = NULL;
01913 *count = 0;
01914 break;
01915 }
01916 ++i;
01917 }
01918
01919 } else {
01920 rc = lsm_log_error_basic(c, LSM_ERR_NO_MEMORY, "ENOMEM");
01921 *count = 0;
01922 }
01923 }
01924 } else {
01925 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_FS, "fs not found");
01926 }
01927 return rc;
01928 }
01929
01930 static int ss_create(lsm_plugin_ptr c, lsm_fs * fs,
01931 const char *name,
01932 lsm_fs_ss ** snapshot, char **job, lsm_flag flags)
01933 {
01934 int rc = LSM_ERR_NO_MEMORY;
01935 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01936
01937 struct allocated_fs *find =
01938 (struct allocated_fs *) g_hash_table_lookup(pd->fs,
01939 lsm_fs_id_get(fs));
01940
01941 if (find) {
01942 if (!g_hash_table_lookup(find->ss, md5(name))) {
01943 char *id = strdup(md5(name));
01944 if (id) {
01945 lsm_fs_ss *ss =
01946 lsm_fs_ss_record_alloc(id, name, time(NULL), NULL);
01947 lsm_fs_ss *new_shot = lsm_fs_ss_record_copy(ss);
01948 if (ss && new_shot) {
01949 g_hash_table_insert(find->ss, (gpointer) id,
01950 (gpointer) ss);
01951 rc = create_job(pd, job, LSM_DATA_TYPE_SS, new_shot,
01952 (void **) snapshot);
01953 } else {
01954 lsm_fs_ss_record_free(ss);
01955 ss = NULL;
01956 lsm_fs_ss_record_free(new_shot);
01957 *snapshot = NULL;
01958 free(id);
01959 id = NULL;
01960 }
01961 }
01962 } else {
01963 rc = lsm_log_error_basic(c, LSM_ERR_NAME_CONFLICT,
01964 "snapshot name exists");
01965 }
01966 } else {
01967 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_FS, "fs not found");
01968 }
01969 return rc;
01970 }
01971
01972 static int ss_delete(lsm_plugin_ptr c, lsm_fs * fs, lsm_fs_ss * ss,
01973 char **job, lsm_flag flags)
01974 {
01975 int rc = LSM_ERR_OK;
01976 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
01977
01978 struct allocated_fs *find =
01979 (struct allocated_fs *) g_hash_table_lookup(pd->fs,
01980 lsm_fs_id_get(fs));
01981
01982 if (find) {
01983 if (!g_hash_table_remove(find->ss, lsm_fs_ss_id_get(ss))) {
01984 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_FS_SS,
01985 "snapshot not found");
01986 } else {
01987 rc = create_job(pd, job, LSM_DATA_TYPE_NONE, NULL, NULL);
01988 }
01989 } else {
01990 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_FS, "fs not found");
01991 }
01992 return rc;
01993 }
01994
01995 static int ss_restore(lsm_plugin_ptr c, lsm_fs * fs, lsm_fs_ss * ss,
01996 lsm_string_list * files,
01997 lsm_string_list * restore_files,
01998 int all_files, char **job, lsm_flag flags)
01999 {
02000 int rc = LSM_ERR_OK;
02001 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
02002
02003 struct allocated_fs *find =
02004 (struct allocated_fs *) g_hash_table_lookup(pd->fs,
02005 lsm_fs_id_get(fs));
02006
02007 if (find) {
02008 if (!g_hash_table_lookup(find->ss, lsm_fs_ss_id_get(ss))) {
02009 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_FS_SS,
02010 "snapshot not found");
02011 } else {
02012 rc = create_job(pd, job, LSM_DATA_TYPE_NONE, NULL, NULL);
02013 }
02014 } else {
02015 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_FS, "fs not found");
02016 }
02017 return rc;
02018 }
02019
02020 static struct lsm_fs_ops_v1 fs_ops = {
02021 fs_list,
02022 fs_create,
02023 fs_delete,
02024 fs_resize,
02025 fs_clone,
02026 fs_file_clone,
02027 fs_child_dependency,
02028 fs_child_dependency_rm,
02029 ss_list,
02030 ss_create,
02031 ss_delete,
02032 ss_restore
02033 };
02034
02035 static int nfs_auth_types(lsm_plugin_ptr c, lsm_string_list ** types,
02036 lsm_flag flags)
02037 {
02038 int rc = LSM_ERR_OK;
02039 *types = lsm_string_list_alloc(1);
02040 if (*types) {
02041 rc = lsm_string_list_elem_set(*types, 0, "standard");
02042 } else {
02043 rc = LSM_ERR_NO_MEMORY;
02044 }
02045 return rc;
02046 }
02047
02048 static int nfs_export_list(lsm_plugin_ptr c, const char *search_key,
02049 const char *search_value,
02050 lsm_nfs_export ** exports[], uint32_t * count,
02051 lsm_flag flags)
02052 {
02053 int rc = LSM_ERR_OK;
02054 GHashTableIter fs_iter;
02055 GHashTableIter exports_iter;
02056 char *k = NULL;
02057 struct allocated_fs *v = NULL;
02058 GSList *result = NULL;
02059 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
02060
02061 g_hash_table_iter_init(&fs_iter, pd->fs);
02062
02063 *count = 0;
02064
02065
02066 while (g_hash_table_iter_next(&fs_iter, (gpointer) & k, (gpointer) & v)) {
02067 char *exp_key = NULL;
02068 lsm_nfs_export **exp_val = NULL;
02069
02070 g_hash_table_iter_init(&exports_iter, v->exports);
02071 while (g_hash_table_iter_next(&exports_iter, (gpointer) & exp_key,
02072 (gpointer) & exp_val)) {
02073 result = g_slist_prepend(result, exp_val);
02074 *count += 1;
02075 }
02076 }
02077
02078 if (*count) {
02079 int i = 0;
02080 GSList *s_iter = NULL;
02081 *exports = lsm_nfs_export_record_array_alloc(*count);
02082 if (*exports) {
02083 for (s_iter = result; s_iter;
02084 s_iter = g_slist_next(s_iter), i++) {
02085 (*exports)[i] =
02086 lsm_nfs_export_record_copy((lsm_nfs_export *)
02087 s_iter->data);
02088
02089 if (!(*exports)[i]) {
02090 rc = LSM_ERR_NO_MEMORY;
02091 lsm_nfs_export_record_array_free(*exports, i);
02092 *exports = NULL;
02093 *count = 0;
02094 break;
02095 }
02096 }
02097 } else {
02098 rc = LSM_ERR_NO_MEMORY;
02099 }
02100 }
02101
02102 if (result) {
02103 g_slist_free(result);
02104 result = NULL;
02105 }
02106
02107 if (LSM_ERR_OK == rc) {
02108 lsm_plug_nfs_export_search_filter(search_key, search_value,
02109 *exports, count);
02110 }
02111
02112 return rc;
02113 }
02114
02115 static int nfs_export_create(lsm_plugin_ptr c,
02116 const char *fs_id,
02117 const char *export_path,
02118 lsm_string_list *root_list,
02119 lsm_string_list *rw_list,
02120 lsm_string_list *ro_list,
02121 uint64_t anon_uid,
02122 uint64_t anon_gid,
02123 const char *auth_type,
02124 const char *options,
02125 lsm_nfs_export **exported,
02126 lsm_flag flags)
02127 {
02128 int rc = LSM_ERR_OK;
02129 char auto_export[2048];
02130 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
02131
02132 struct allocated_fs *fs = g_hash_table_lookup(pd->fs, fs_id);
02133 if (fs) {
02134 if (!export_path) {
02135 snprintf(auto_export, sizeof(auto_export), "/mnt/lsm/nfs/%s",
02136 lsm_fs_name_get(fs->fs));
02137 export_path = auto_export;
02138 }
02139
02140 char *key = strdup(md5(export_path));
02141 *exported = lsm_nfs_export_record_alloc(md5(export_path),
02142 fs_id,
02143 export_path,
02144 auth_type,
02145 root_list,
02146 rw_list,
02147 ro_list,
02148 anon_uid,
02149 anon_gid, options, NULL);
02150
02151 lsm_nfs_export *value = lsm_nfs_export_record_copy(*exported);
02152
02153 if (key && *exported && value) {
02154 g_hash_table_insert(fs->exports, key, value);
02155 } else {
02156 rc = LSM_ERR_NO_MEMORY;
02157 free(key);
02158 lsm_nfs_export_record_free(*exported);
02159 lsm_nfs_export_record_free(value);
02160 }
02161
02162 } else {
02163 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_FS, "fs not found");
02164 }
02165 return rc;
02166 }
02167
02168 static int nfs_export_remove(lsm_plugin_ptr c, lsm_nfs_export * e,
02169 lsm_flag flags)
02170 {
02171 int rc = LSM_ERR_OK;
02172 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
02173
02174 struct allocated_fs *fs = g_hash_table_lookup(pd->fs,
02175 lsm_nfs_export_fs_id_get
02176 (e));
02177 if (fs) {
02178 if (!g_hash_table_remove(fs->exports, lsm_nfs_export_id_get(e))) {
02179 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_NFS_EXPORT,
02180 "export not found");
02181 }
02182 } else {
02183 rc = lsm_log_error_basic(c, LSM_ERR_NOT_FOUND_FS, "fs not found");
02184 }
02185 return rc;
02186 }
02187
02188 static struct lsm_nas_ops_v1 nfs_ops = {
02189 nfs_auth_types,
02190 nfs_export_list,
02191 nfs_export_create,
02192 nfs_export_remove
02193 };
02194
02195
02196 void free_group_grant_hash(void *v)
02197 {
02198 g_hash_table_destroy((GHashTable *) v);
02199 }
02200
02201 void free_allocated_fs(void *v)
02202 {
02203 free_fs_record((struct allocated_fs *) v);
02204 }
02205
02206 void free_disk(void *d)
02207 {
02208 lsm_disk_record_free((lsm_disk *) d);
02209 }
02210
02211 void free_allocated_volume(void *v)
02212 {
02213 if (v) {
02214 struct allocated_volume *av = (struct allocated_volume *) v;
02215 lsm_volume_record_free(av->v);
02216 av->v = NULL;
02217 av->p = NULL;
02218 free(av);
02219 }
02220 }
02221
02222 static void _unload(struct plugin_data *pd)
02223 {
02224 int i;
02225
02226 if (pd) {
02227
02228 if (pd->disks) {
02229 g_hash_table_destroy(pd->disks);
02230 pd->disks = NULL;
02231 }
02232
02233 if (pd->jobs) {
02234 g_hash_table_destroy(pd->jobs);
02235 pd->jobs = NULL;
02236 }
02237
02238 if (pd->fs) {
02239 g_hash_table_destroy(pd->fs);
02240 pd->fs = NULL;
02241 }
02242
02243 if (pd->group_grant) {
02244 g_hash_table_destroy(pd->group_grant);
02245 pd->group_grant = NULL;
02246 }
02247
02248 if (pd->access_groups) {
02249 g_hash_table_destroy(pd->access_groups);
02250 pd->access_groups = NULL;
02251 }
02252
02253 if (pd->volumes) {
02254 g_hash_table_destroy(pd->volumes);
02255 pd->volumes = NULL;
02256 }
02257
02258 if (pd->pools) {
02259 g_hash_table_destroy(pd->pools);
02260 pd->pools = NULL;
02261 }
02262
02263 for (i = 0; i < pd->num_systems; ++i) {
02264 lsm_system_record_free(pd->system[i]);
02265 pd->system[i] = NULL;
02266 }
02267 pd->num_systems = 0;
02268
02269 free(pd);
02270 pd = NULL;
02271 }
02272 }
02273
02274 int load(lsm_plugin_ptr c, const char *uri, const char *password,
02275 uint32_t timeout, lsm_flag flags)
02276 {
02277 struct plugin_data *pd = (struct plugin_data *)
02278 calloc(1, sizeof(struct plugin_data));
02279 int rc = LSM_ERR_NO_MEMORY;
02280 int i;
02281 lsm_pool *p = NULL;
02282 if (pd) {
02283 pd->num_systems = 1;
02284 pd->system[0] = lsm_system_record_alloc(sys_id,
02285 "LSM simulated storage plug-in",
02286 LSM_SYSTEM_STATUS_OK, "",
02287 NULL);
02288
02289 p = lsm_pool_record_alloc("POOL_3", "lsm_test_aggr",
02290 LSM_POOL_ELEMENT_TYPE_FS |
02291 LSM_POOL_ELEMENT_TYPE_VOLUME, 0,
02292 UINT64_MAX, UINT64_MAX,
02293 LSM_POOL_STATUS_OK, "", sys_id, 0);
02294 if (p) {
02295 pd->pools = g_hash_table_new_full(g_str_hash, g_str_equal, free,
02296 free_pool_record);
02297
02298 g_hash_table_insert(pd->pools, strdup(lsm_pool_id_get(p)), p);
02299
02300 for (i = 0; i < 3; ++i) {
02301 char name[32];
02302 snprintf(name, sizeof(name), "POOL_%d", i);
02303
02304 p = lsm_pool_record_alloc(name, name,
02305 LSM_POOL_ELEMENT_TYPE_FS |
02306 LSM_POOL_ELEMENT_TYPE_VOLUME, 0,
02307 UINT64_MAX, UINT64_MAX,
02308 LSM_POOL_STATUS_OK, "", sys_id,
02309 NULL);
02310
02311 if (p) {
02312 g_hash_table_insert(pd->pools,
02313 strdup(lsm_pool_id_get(p)), p);
02314 } else {
02315 g_hash_table_destroy(pd->pools);
02316 pd->pools = NULL;
02317 break;
02318 }
02319 }
02320 }
02321
02322 pd->volumes = g_hash_table_new_full(g_str_hash, g_str_equal, free,
02323 free_allocated_volume);
02324
02325 pd->access_groups = g_hash_table_new_full(g_str_hash, g_str_equal,
02326 free, free_allocated_ag);
02327
02328
02329
02330 pd->group_grant = g_hash_table_new_full(g_str_hash, g_str_equal,
02331 free,
02332 free_group_grant_hash);
02333
02334 pd->fs = g_hash_table_new_full(g_str_hash, g_str_equal, free,
02335 free_allocated_fs);
02336
02337 pd->jobs = g_hash_table_new_full(g_str_hash, g_str_equal, free,
02338 free_allocated_job);
02339
02340 pd->disks = g_hash_table_new_full(g_str_hash, g_str_equal, free,
02341 free_disk);
02342
02343
02344 for (i = 0; i < 10; ++i) {
02345 lsm_disk *d = NULL;
02346 char name[17];
02347 char *key = NULL;
02348 snprintf(name, sizeof(name), "Sim C disk %d", i);
02349
02350 d = lsm_disk_record_alloc(md5(name), name, LSM_DISK_TYPE_SOP,
02351 512, 0x8000000000000,
02352 LSM_DISK_STATUS_OK, sys_id);
02353
02354 key = strdup(lsm_disk_id_get(d));
02355
02356 if (!key || !d) {
02357 g_hash_table_destroy(pd->disks);
02358 pd->disks = NULL;
02359
02360 lsm_disk_record_free(d);
02361 d = NULL;
02362
02363 free(key);
02364 key = NULL;
02365
02366 break;
02367 }
02368
02369 g_hash_table_insert(pd->disks, key, d);
02370 d = NULL;
02371 }
02372
02373 if (!pd->system[0] || !pd->volumes || !pd->pools
02374 || !pd->access_groups || !pd->group_grant || !pd->fs
02375 || !pd->jobs || !pd->disks) {
02376 rc = LSM_ERR_NO_MEMORY;
02377 _unload(pd);
02378 pd = NULL;
02379 } else {
02380 rc = lsm_register_plugin_v1_2(c, pd, &mgm_ops, &san_ops,
02381 &fs_ops, &nfs_ops, &ops_v1_2);
02382 }
02383 }
02384 return rc;
02385 }
02386
02387 int unload(lsm_plugin_ptr c, lsm_flag flags)
02388 {
02389 struct plugin_data *pd = (struct plugin_data *) lsm_private_data_get(c);
02390 if (pd) {
02391 _unload(pd);
02392 return LSM_ERR_OK;
02393 } else {
02394 return LSM_ERR_INVALID_ARGUMENT;
02395 }
02396 }
02397
02398 int main(int argc, char *argv[])
02399 {
02400 return lsm_plugin_init_v1(argc, argv, load, unload, name, version);
02401 }
02402
02403
02404 #ifdef __cplusplus
02405 }
02406 #endif