Index: /branches/rel_avx_2_7_3/src/avxd/avx_rpc.h
===================================================================
--- /branches/rel_avx_2_7_3/src/avxd/avx_rpc.h	(revision 8949)
+++ /branches/rel_avx_2_7_3/src/avxd/avx_rpc.h	(working copy)
@@ -109,6 +109,7 @@
     SWITCH_DEL_BOND,
     SWITCH_UPDATE_BOND_PORT,
     VA_INSTANCE_CHANGE_VDISK,
+    VA_INSTANCE_CHANGE_VDISK_CACHE,
     MAX_RPC_FUNC_ID
 };
 
Index: /branches/rel_avx_2_7_3/src/avxd/avx_rpcserver.c
===================================================================
--- /branches/rel_avx_2_7_3/src/avxd/avx_rpcserver.c	(revision 8949)
+++ /branches/rel_avx_2_7_3/src/avxd/avx_rpcserver.c	(working copy)
@@ -157,6 +157,8 @@
 RPC_FUNC_SANITY_WRAP(switch_del_bond);
 RPC_FUNC_SANITY_WRAP(switch_update_bond_port);
 RPC_FUNC_SANITY_WRAP(va_instance_change_vdisk);
+RPC_FUNC_SANITY_WRAP(va_instance_change_vdisk_cache);
+
 
 struct {
     int (*func)(RPC_FUNC_ARGS_TMPL); // rpc function pointer
@@ -216,6 +218,7 @@
     { _switch_del_bond, "switch_del_bond"},
     { _switch_update_bond_port, "switch_update_bond_port"},
     { _va_instance_change_vdisk, "va_instance_change_vdisk"},
+    { _va_instance_change_vdisk_cache, "va_instance_change_vdisk_cache"},
 };
 
 #ifndef __DEBUG__
@@ -888,6 +891,21 @@
 	}
         return -1;
 }
+
+static int
+    _va_instance_change_vdisk_cache(RPC_FUNC_ARGS_TMPL)
+{
+	const char* vm_name = args->list[0];
+	const char* vdisk_type = args->list[1];
+	const char* cache = args->list[2];
+
+	if(vm_name != NULL && strlen(vm_name) != 0 
+		&& vdisk_type != NULL && strlen(vdisk_type) != 0
+		&& cache != NULL && strlen(cache) != 0 ) {
+		return va_instance_change_vdisk_cache(vm_name, vdisk_type, cache);
+	}
+        return -1;
+}
 
 static int
     _va_instance_clear(RPC_FUNC_ARGS_TMPL)
Index: /branches/rel_avx_2_7_3/src/generator/commands.pm
===================================================================
--- /branches/rel_avx_2_7_3/src/generator/commands.pm	(revision 8949)
+++ /branches/rel_avx_2_7_3/src/generator/commands.pm	(working copy)
@@ -6231,6 +6231,30 @@
                         },],
     },
     {
+		obj_type => "ITEM",
+		name => "diskcache",
+		help_string => "Change VA disk cache type (none, writethrough, writeback, directsync)",
+		menu => "root_va",
+		cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+		user_level => "CLI_LEVEL_CONFIG",
+		function_name => "va_instance_change_vdisk_cache_rpc",
+		function_args => [ {
+									type => "STRING",
+									help_string => "VA instance name",
+									optional => "NO",
+								},
+                                {
+									type => "STRING",
+									help_string => "Disk type: system or exdisk",
+									optional => "NO",
+								},
+								{
+									type => "STRING",
+									help_string => "Cache type: none, writethrough, writeback, directsync",
+									optional => "NO",
+								},],
+	},
+    {
         obj_type => "MENU",
         name => "monitor",
         parent_menu => ".",
Index: /branches/rel_avx_2_7_3/src/library/avxvainst/va_config.h
===================================================================
--- /branches/rel_avx_2_7_3/src/library/avxvainst/va_config.h	(revision 8949)
+++ /branches/rel_avx_2_7_3/src/library/avxvainst/va_config.h	(working copy)
@@ -107,5 +107,7 @@
 
 int va_config_update_disk_type(const char* vm_name, const char* disk_name, const char* disk_type);
 
+int va_config_update_disk_cache(const char* vm_name, const char* disk_name, const char* cache_type);
+
 int update_xml_cpu_cell_guest_cpu_model(const char* vm_name, char* cpu_model);
 #endif
Index: /branches/rel_avx_2_7_3/src/library/avxvainst/va_config.c
===================================================================
--- /branches/rel_avx_2_7_3/src/library/avxvainst/va_config.c	(revision 8949)
+++ /branches/rel_avx_2_7_3/src/library/avxvainst/va_config.c	(working copy)
@@ -2019,6 +2019,95 @@
     return -1;
 }
 
+/*
+change the disk cache mode of the specified disk of the specified VA instance
+Parameters:
+    vm_name: the name of the VA instance
+    disk_name: the name of the disk
+    cache_type: the caching mode to be set
+Return:
+    0: success
+    -1: xml parser failed.
+    -2: empty documents.
+    -3: failed to get the dev attribute of the target node.
+*/ 
+int va_config_update_disk_cache(const char* vm_name, const char* disk_name, const char* cache_type) {
+    char filename[AVX_MAX_PATH_LEN + 1];
+    sprintf(filename, "%s/%s.xml", AVX_VA_CONFIG_DIR, vm_name);
+
+    int ret = 0;
+    xmlDocPtr doc = NULL;
+    xmlNodePtr node = NULL;
+    xmlNodePtr driver_node = NULL;
+    xmlChar* dev_prop = NULL;
+    xmlChar* cache_prop = NULL;
+
+    doc = xmlParseFile(filename);
+    if (doc == NULL) {
+        va_log_error("Unable to parse file \"%s\"", filename);
+        ret = -1;
+        goto cleanup;
+    }
+    node = xmlDocGetRootElement(doc);
+    if (node == NULL) {
+        va_log_debug("empty documents...");
+        ret = -2;
+        goto cleanup;
+    }
+
+    xmlNodePtr current_node = node->children;
+    while (current_node) {
+        if (!xmlStrcmp(current_node->name, BAD_CAST "devices")) {
+            xmlNodePtr device_node = current_node->children;
+            while (device_node) {
+                if (!xmlStrcmp(device_node->name, BAD_CAST "disk")) {
+                    xmlNodePtr disk_node = device_node->children;
+                    while (disk_node) {
+                        // 1. record driver node, cache attribute need to be add here.
+                        if (!xmlStrcmp(disk_node->name, BAD_CAST "driver")) {
+                            driver_node = disk_node;
+                        }
+                        // 2. find target node, we verify dev name here, if matched disk_name, we update cache attribute.
+                        if (!xmlStrcmp(disk_node->name, BAD_CAST "target")) {
+                            dev_prop = xmlGetProp(disk_node, BAD_CAST "dev");
+                            if (!dev_prop) {
+                                ret = -3;
+                                goto cleanup;
+                            }
+                            if (!xmlStrcmp(BAD_CAST disk_name, dev_prop)) {
+                                // 3. dev name matched, update cache attribute.
+                                // support we already found driver node, ohterwise there is a bug here (and all previous logic).
+                                cache_prop = xmlGetProp(driver_node, BAD_CAST "cache");
+                                if (cache_prop) {
+                                    xmlSetProp(driver_node, BAD_CAST "cache", BAD_CAST cache_type);
+                                } else {
+                                    xmlNewProp(driver_node, BAD_CAST "cache", BAD_CAST cache_type);
+                                }
+                                xmlSaveFile(filename, doc);
+                                goto cleanup;
+                            }
+                        }
+                        disk_node = disk_node->next;
+                    }
+                }
+                device_node = device_node->next;
+            }
+        }
+        current_node = current_node->next;
+    }
+cleanup:
+    if(doc) {
+        xmlFreeDoc(doc);
+    }
+    if(dev_prop) {
+        xmlFree(dev_prop);
+    }
+    if(cache_prop) {
+        xmlFree(cache_prop);
+    }
+    return ret;
+}
+
 
 int
 update_xml_cpu_cell_guest_cpu_model(const char* vm_name, char* cpu_model) {
Index: /branches/rel_avx_2_7_3/src/library/avxvainst/va_constants.h
===================================================================
--- /branches/rel_avx_2_7_3/src/library/avxvainst/va_constants.h	(revision 8949)
+++ /branches/rel_avx_2_7_3/src/library/avxvainst/va_constants.h	(working copy)
@@ -34,6 +34,7 @@
 #define MAX_CREATE_INSTANCE_CMD_LEN 64
 #define MAX_PORT_NAME_LEN 12
 #define MAX_VDISK_NAME_LEN 16
+#define MAX_VDISK_CACHE_TYPE_LEN 16
 
 #define AVX_MAX_XML_FILE (2*1024*1024)
 #define AVX_MAX_PATH_LINE 128
@@ -203,6 +204,7 @@
 #define VA_DISK_NAME_PRE 6
 #define VA_DISK_NAME_LEN 10
 #define VA_DISK_SYS_NAME_LEN 4
+#define VA_DISK_CACHE_MODE_LEN 20
 #define VA_DISK_RESERVED_NAME "reserved"
 
 #define AVX_MD5_LENGTH 32
Index: /branches/rel_avx_2_7_3/src/library/avxvainst/va_info.h
===================================================================
--- /branches/rel_avx_2_7_3/src/library/avxvainst/va_info.h	(revision 8949)
+++ /branches/rel_avx_2_7_3/src/library/avxvainst/va_info.h	(working copy)
@@ -56,6 +56,7 @@
     char file[VA_MAX_DISK][AVX_MAX_PATH_LEN + 1];
     char base_md5[VA_MAX_DISK][AVX_MD5_LENGTH + 1];
     int size[VA_MAX_DISK];
+    char cache_mode[VA_MAX_DISK][VA_DISK_CACHE_MODE_LEN + 1];
 } va_disk_info_t;
 
 
Index: /branches/rel_avx_2_7_3/src/library/avxvainst/va_info.c
===================================================================
--- /branches/rel_avx_2_7_3/src/library/avxvainst/va_info.c	(revision 8949)
+++ /branches/rel_avx_2_7_3/src/library/avxvainst/va_info.c	(working copy)
@@ -444,6 +444,9 @@
 
         if (strlen(info->va_inst_disks.base_md5[i]))
             xmlSetProp(p, BAD_CAST "basemd5", BAD_CAST info->va_inst_disks.base_md5[i]);
+        
+        if (strlen(info->va_inst_disks.cache_mode[i]))
+            xmlSetProp(p, BAD_CAST "cache", BAD_CAST info->va_inst_disks.cache_mode[i]);
     }
 
     // add usbs node
Index: /branches/rel_avx_2_7_3/src/library/avxvainst/va_instance.h
===================================================================
--- /branches/rel_avx_2_7_3/src/library/avxvainst/va_instance.h	(revision 8949)
+++ /branches/rel_avx_2_7_3/src/library/avxvainst/va_instance.h	(working copy)
@@ -31,6 +31,8 @@
 
 int va_instance_change_vdisk(const char* vm_name, const char* vdisk_type, const char* bus_type);
 
+int va_instance_change_vdisk_cache(const char* vm_name, const char* vdisk_type, const char* cache_type);
+
 int va_instance_undefine_vm(const char *name);
 
 int va_instance_clean_vms();
Index: /branches/rel_avx_2_7_3/src/library/avxvainst/va_instance.c
===================================================================
--- /branches/rel_avx_2_7_3/src/library/avxvainst/va_instance.c	(revision 8949)
+++ /branches/rel_avx_2_7_3/src/library/avxvainst/va_instance.c	(working copy)
@@ -7259,3 +7259,94 @@
 
     return ret;
 }
+
+/*
+change the disk cache mode of the specified disk of the specified VA instance
+Parameters:
+    vm_name: the name of the VA instance
+    vdisk_type: the type of the disk, system or exdisk
+    cache_mode: none, writeback, writethrough, directsync
+Return:
+    2: VA is not shutoff
+    1: VA domain not found
+    0: success
+    -1: failed
+*/ 
+
+int va_instance_change_vdisk_cache(const char* vm_name, const char* vdisk_type, const char* cache_mode)
+{
+    int ret = 0;
+    struct va_instance_info info;
+    int i = 0;
+    int update_flag = 0;
+    int hyper_type;
+
+    if(!vm_name || !strlen(vm_name)) {
+        va_log_error("virtual machine name is invalid\n");
+        return -1;
+    }
+
+    if(!vdisk_type || !strlen(vdisk_type)) {
+        va_log_error("Virtual disk type is missing.\n");
+        return -1;
+    }
+
+    if(!cache_mode || !strlen(cache_mode)) {
+        va_log_error("Cache mode is missing.\n");
+        return -1;
+    }
+
+    hyper_type = find_hyper_type_by_vaname(vm_name);
+    if(hyper_type == -1) {
+        ret = VA_DOMAIN_NOT_FOUND;
+        return ret;
+    }
+
+    // check whether the va shutdowns, if not, directly return
+    ret = check_va_status(vm_name, hyper_type);
+    if(ret != 0) {
+        va_log_error("VA(%s) is NOT shutoff", vm_name);
+        return ret;
+    }
+
+    va_instance_info_init_struct(&info);
+    ret = va_instance_info_get(vm_name, &info);
+    if (ret != 0) {
+        va_log_error("va_instance_change_vdisk_cache: Failed to get vm(%s) info", vm_name);
+        return -1;
+    }
+
+    for (i = 0; i < info.va_inst_disks.cnt; ++i) {
+        if ( (strcmp(info.va_inst_disks.name[i], "reserved") == 0) && (strcmp(vdisk_type, "system") == 0) ) {
+            if (strcmp(info.va_inst_disks.cache_mode[i], cache_mode) != 0) {
+                strcpy(info.va_inst_disks.cache_mode[i], cache_mode);
+                if (va_config_update_disk_cache(vm_name, info.va_inst_disks.disk[i], cache_mode) != 0) {
+                    va_log_error("va_instance_change_vdisk_cache: va_config_update_disk_cache vm(%s) disk(%s) failed", vm_name, info.va_inst_disks.name[i]);
+                    return -1;
+                }
+                update_flag = 1;
+            }
+        } else if ( (strncmp(info.va_inst_disks.name[i], "exdisk", strlen("exdisk")) == 0) && (strcmp(vdisk_type, "exdisk") == 0) ) {
+            if (strcmp(info.va_inst_disks.cache_mode[i], cache_mode) != 0) {
+                strcpy(info.va_inst_disks.cache_mode[i], cache_mode);
+                if (va_config_update_disk_cache(vm_name, info.va_inst_disks.disk[i], cache_mode) != 0) {
+                    va_log_error("va_instance_change_vdisk_cache: va_config_update_disk_cache vm(%s) disk(%s) failed", vm_name, info.va_inst_disks.name[i]);
+                    return -1;
+                }
+                update_flag = 1;
+            }
+        }
+    }
+
+    if (update_flag == 0) {
+        va_log_error("Current %s disk cache mode is %s.\n", vdisk_type, cache_mode);
+        return 0;
+    }
+
+    va_instance_info_create(&info);
+    ret = redefine_va(vm_name);
+    if (ret != 0) {
+        va_log_error("va_instance_change_vdisk_cache: redefine_va vm(%s) failed", vm_name);
+    }
+    return ret;
+}
\ No newline at end of file
Index: /branches/rel_avx_2_7_3/src/library/avxvainst/va_xmlrpc.h
===================================================================
--- /branches/rel_avx_2_7_3/src/library/avxvainst/va_xmlrpc.h	(revision 8949)
+++ /branches/rel_avx_2_7_3/src/library/avxvainst/va_xmlrpc.h	(working copy)
@@ -103,4 +103,5 @@
 int switch_add_bond_port_rpc(const char* bond, const char* ports);
 int switch_del_bond_port_rpc(const char* bond, const char* ports);
 int va_instance_change_vdisk_rpc(const char* name, const char* disk_type, const char *bus_type);
+int va_instance_change_vdisk_cache_rpc(const char* name, const char* disk_type, const char *cache_type);
 #endif
Index: /branches/rel_avx_2_7_3/src/library/avxvainst/va_xmlrpc.c
===================================================================
--- /branches/rel_avx_2_7_3/src/library/avxvainst/va_xmlrpc.c	(revision 8949)
+++ /branches/rel_avx_2_7_3/src/library/avxvainst/va_xmlrpc.c	(working copy)
@@ -61,6 +61,7 @@
     char wrap_sync_md5[AVX_MD5_LENGTH + 1];
     char wrap_sync_name[(MAX_IMAGE_NAME_LEN > MAX_VA_NAME_LEN ? MAX_IMAGE_NAME_LEN : MAX_VA_NAME_LEN) + 1];
     char wrap_vdisk_type[MAX_VDISK_NAME_LEN];
+    char wrap_vdisk_cache_type[MAX_VDISK_CACHE_TYPE_LEN];
     int wrap_vf_idx;
     int wrap_vf_shared;
 	int wrap_vlan_tag;
@@ -344,6 +345,11 @@
         strcpy(rpc_args[1], argu->wrap_vdisk_type);
         strcpy(rpc_args[2], argu->wrap_br_name);
         break;
+    case VA_INSTANCE_CHANGE_VDISK_CACHE:
+        strcpy(rpc_args[0], argu->wrap_vm_name);
+        strcpy(rpc_args[1], argu->wrap_vdisk_type);
+        strcpy(rpc_args[2], argu->wrap_vdisk_cache_type);
+        break;
 
     default:
         printf("Failed to parse argument %d\n", argu->wrap_func);
@@ -2901,3 +2907,70 @@
     
     return ret;
 }
+
+int va_instance_change_vdisk_cache_rpc(const char* name, const char* disk_type, const char *cache_type) 
+{
+    int ret;
+    char cache_type_[20];
+    char disk_type_[20];
+    int  i = 0;
+    struct wrap_rpc_argu *argu;
+
+    if(strlen(name) > MAX_VA_NAME_LEN) {
+        printf("The length of the VA name must not be larger than %d characters.\n",
+                MAX_VA_NAME_LEN);
+        return -1;
+    }
+
+    bzero(cache_type_, sizeof(cache_type_));
+    strcpy(cache_type_, cache_type);
+    for(i = 0; i < strlen(cache_type_); i++) {
+        cache_type_[i] = tolower(cache_type_[i]);
+    }
+
+    if ((strcmp(cache_type_, "none") != 0) && (strcmp(cache_type_, "writeback") != 0) &&
+        (strcmp(cache_type_, "writethrough") != 0) && (strcmp(cache_type_, "directsync") != 0))
+    {
+        printf("cache type should be none, writeback, writethrough or directsync.\n");
+        return -1;
+    }
+
+    bzero(disk_type_, sizeof(disk_type_));
+    strcpy(disk_type_, disk_type);
+    for(i = 0; i < strlen(disk_type_); i++) {
+        disk_type_[i] = tolower(disk_type_[i]);
+    }
+    if ( (strcmp(disk_type_, "system") != 0) && (strcmp(disk_type_, "exdisk") != 0) ) {
+        printf("disk type should be system or exdisk.\n");
+        return -1;
+    }
+
+    if(va_instance_isexisted(name, 0) != 0) {
+        printf("The entered VA instance name does not exist.\n");
+        return -1;
+    }
+
+    argu = (struct wrap_rpc_argu *)malloc(sizeof(struct wrap_rpc_argu));
+    if (!argu) {
+       printf("Memory allocation failed.\n");
+       return -1;
+    }
+
+    argu->wrap_func = VA_INSTANCE_CHANGE_VDISK_CACHE;
+    strcpy(argu->wrap_vm_name, name);
+    strcpy(argu->wrap_vdisk_type, disk_type_);
+    strcpy(argu->wrap_vdisk_cache_type, cache_type_);
+
+    ret = wrap_rpc_func(argu, NULL, NULL);
+    free(argu);
+    
+    if (ret == 0) {
+        printf("The VA(%s) %s disk cache type has been changed to %s\n", name, disk_type_, cache_type_);
+    } else if(ret > 0) {
+        printf("%s\n", va_get_error_info(ret));
+    } else {
+        printf("Command execution failed due to internal communication error\n");
+    }
+    
+    return ret;
+}
\ No newline at end of file
