Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 288896
b: refs/heads/master
c: db42533
h: refs/heads/master
v: v3
  • Loading branch information
K. Y. Srinivasan authored and Greg Kroah-Hartman committed Mar 16, 2012
1 parent a919aa2 commit 6d33dd0
Show file tree
Hide file tree
Showing 2 changed files with 281 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: fa3d5b85c681518b6e4ec515814dcb2d5b702b89
refs/heads/master: db425334e5bb7fa65bbbd7bea9d79842f65bcf45
281 changes: 280 additions & 1 deletion trunk/tools/hv/hv_kvp_daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
#include <ifaddrs.h>
#include <netdb.h>
#include <syslog.h>

#include <sys/stat.h>
#include <fcntl.h>

/*
* KVP protocol: The user mode component first registers with the
Expand Down Expand Up @@ -79,6 +80,250 @@ static char *os_build;
static char *lic_version;
static struct utsname uts_buf;


#define MAX_FILE_NAME 100
#define ENTRIES_PER_BLOCK 50

struct kvp_record {
__u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
__u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
};

struct kvp_file_state {
int fd;
int num_blocks;
struct kvp_record *records;
int num_records;
__u8 fname[MAX_FILE_NAME];
};

static struct kvp_file_state kvp_file_info[KVP_POOL_COUNT];

static void kvp_acquire_lock(int pool)
{
struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0};
fl.l_pid = getpid();

if (fcntl(kvp_file_info[pool].fd, F_SETLKW, &fl) == -1) {
syslog(LOG_ERR, "Failed to acquire the lock pool: %d", pool);
exit(-1);
}
}

static void kvp_release_lock(int pool)
{
struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0};
fl.l_pid = getpid();

if (fcntl(kvp_file_info[pool].fd, F_SETLK, &fl) == -1) {
perror("fcntl");
syslog(LOG_ERR, "Failed to release the lock pool: %d", pool);
exit(-1);
}
}

static void kvp_update_file(int pool)
{
FILE *filep;
size_t bytes_written;

/*
* We are going to write our in-memory registry out to
* disk; acquire the lock first.
*/
kvp_acquire_lock(pool);

filep = fopen(kvp_file_info[pool].fname, "w");
if (!filep) {
kvp_release_lock(pool);
syslog(LOG_ERR, "Failed to open file, pool: %d", pool);
exit(-1);
}

bytes_written = fwrite(kvp_file_info[pool].records,
sizeof(struct kvp_record),
kvp_file_info[pool].num_records, filep);

fflush(filep);
kvp_release_lock(pool);
}

static int kvp_file_init(void)
{
int ret, fd;
FILE *filep;
size_t records_read;
__u8 *fname;
struct kvp_record *record;
struct kvp_record *readp;
int num_blocks;
int i;
int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK;

if (access("/var/opt/hyperv", F_OK)) {
if (mkdir("/var/opt/hyperv", S_IRUSR | S_IWUSR | S_IROTH)) {
syslog(LOG_ERR, " Failed to create /var/opt/hyperv");
exit(-1);
}
}

for (i = 0; i < KVP_POOL_COUNT; i++) {
fname = kvp_file_info[i].fname;
records_read = 0;
num_blocks = 1;
sprintf(fname, "/var/opt/hyperv/.kvp_pool_%d", i);
fd = open(fname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH);

if (fd == -1)
return 1;


filep = fopen(fname, "r");
if (!filep)
return 1;

record = malloc(alloc_unit * num_blocks);
if (record == NULL) {
fclose(filep);
return 1;
}
while (!feof(filep)) {
readp = &record[records_read];
records_read += fread(readp, sizeof(struct kvp_record),
ENTRIES_PER_BLOCK,
filep);

if (!feof(filep)) {
/*
* We have more data to read.
*/
num_blocks++;
record = realloc(record, alloc_unit *
num_blocks);
if (record == NULL) {
fclose(filep);
return 1;
}
continue;
}
break;
}
kvp_file_info[i].fd = fd;
kvp_file_info[i].num_blocks = num_blocks;
kvp_file_info[i].records = record;
kvp_file_info[i].num_records = records_read;
fclose(filep);

}

return 0;
}

static int kvp_key_delete(int pool, __u8 *key, int key_size)
{
int i;
int j, k;
int num_records = kvp_file_info[pool].num_records;
struct kvp_record *record = kvp_file_info[pool].records;

for (i = 0; i < num_records; i++) {
if (memcmp(key, record[i].key, key_size))
continue;
/*
* Found a match; just move the remaining
* entries up.
*/
if (i == num_records) {
kvp_file_info[pool].num_records--;
kvp_update_file(pool);
return 0;
}

j = i;
k = j + 1;
for (; k < num_records; k++) {
strcpy(record[j].key, record[k].key);
strcpy(record[j].value, record[k].value);
j++;
}

kvp_file_info[pool].num_records--;
kvp_update_file(pool);
return 0;
}
return 1;
}

static int kvp_key_add_or_modify(int pool, __u8 *key, int key_size, __u8 *value,
int value_size)
{
int i;
int j, k;
int num_records = kvp_file_info[pool].num_records;
struct kvp_record *record = kvp_file_info[pool].records;
int num_blocks = kvp_file_info[pool].num_blocks;

if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
(value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
return 1;

for (i = 0; i < num_records; i++) {
if (memcmp(key, record[i].key, key_size))
continue;
/*
* Found a match; just update the value -
* this is the modify case.
*/
memcpy(record[i].value, value, value_size);
kvp_update_file(pool);
return 0;
}

/*
* Need to add a new entry;
*/
if (num_records == (ENTRIES_PER_BLOCK * num_blocks)) {
/* Need to allocate a larger array for reg entries. */
record = realloc(record, sizeof(struct kvp_record) *
ENTRIES_PER_BLOCK * (num_blocks + 1));

if (record == NULL)
return 1;
kvp_file_info[pool].num_blocks++;

}
memcpy(record[i].value, value, value_size);
memcpy(record[i].key, key, key_size);
kvp_file_info[pool].records = record;
kvp_file_info[pool].num_records++;
kvp_update_file(pool);
return 0;
}

static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
int value_size)
{
int i;
int num_records = kvp_file_info[pool].num_records;
struct kvp_record *record = kvp_file_info[pool].records;

if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
(value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
return 1;

for (i = 0; i < num_records; i++) {
if (memcmp(key, record[i].key, key_size))
continue;
/*
* Found a match; just copy the value out.
*/
memcpy(value, record[i].value, value_size);
return 0;
}

return 1;
}

void kvp_get_os_info(void)
{
FILE *file;
Expand Down Expand Up @@ -315,6 +560,11 @@ int main(void)
*/
kvp_get_os_info();

if (kvp_file_init()) {
syslog(LOG_ERR, "Failed to initialize the pools");
exit(-1);
}

fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
if (fd < 0) {
syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd);
Expand Down Expand Up @@ -389,9 +639,38 @@ int main(void)
}
continue;

/*
* The current protocol with the kernel component uses a
* NULL key name to pass an error condition.
* For the SET, GET and DELETE operations,
* use the existing protocol to pass back error.
*/

case KVP_OP_SET:
if (kvp_key_add_or_modify(hv_msg->kvp_hdr.pool,
hv_msg->body.kvp_set.data.key,
hv_msg->body.kvp_set.data.key_size,
hv_msg->body.kvp_set.data.value,
hv_msg->body.kvp_set.data.value_size))
strcpy(hv_msg->body.kvp_set.data.key, "");
break;

case KVP_OP_GET:
if (kvp_get_value(hv_msg->kvp_hdr.pool,
hv_msg->body.kvp_set.data.key,
hv_msg->body.kvp_set.data.key_size,
hv_msg->body.kvp_set.data.value,
hv_msg->body.kvp_set.data.value_size))
strcpy(hv_msg->body.kvp_set.data.key, "");
break;

case KVP_OP_DELETE:
if (kvp_key_delete(hv_msg->kvp_hdr.pool,
hv_msg->body.kvp_delete.key,
hv_msg->body.kvp_delete.key_size))
strcpy(hv_msg->body.kvp_delete.key, "");
break;

default:
break;
}
Expand Down

0 comments on commit 6d33dd0

Please sign in to comment.