예제 #1
0
template<class ST> void CDenseFeatures<ST>::initialize_cache()
{
	if (m_subset_stack->has_subsets())
		SG_ERROR("A subset is set, cannot call initialize_cache\n");

	if (num_features && num_vectors)
	{
		SG_UNREF(feature_cache);
		feature_cache = new CCache<ST>(get_cache_size(), num_features,
				num_vectors);
		SG_REF(feature_cache);
	}
}
//// DO NOT CHANGE ANYTHING BELOW THIS POINT
int main(void) {
  int size;
  int assoc;
  int block_size;

  int i;

  /* The cache needs to be initialized, but the parameters will be
     ignored by the mystery caches, as they are hard coded.  You can
     test your geometry paramter discovery routines by calling
     cache_init() w/ your own size and block size values. */
  cache_init(64*1024,16);
  flush_cache();
  
  /*
  for (i = 0; i < 17; i++)
  {
      if (!access_cache(addr + i))
	  printf("%lld miss\n", addr + i);
      else
	  printf("%lld hit\n", addr + i);
  }

  for (i = 0; i < 17; i++)
  {
      if (!access_cache(addr + i))
	  printf("%lld miss\n", addr + i);
      else
	  printf("%lld hit\n", addr + i);
  }

  for (i = 17; i < 34; i++)
  {
      if (!access_cache(addr + i))
	  printf("%lld miss\n", addr + i);
      else
	  printf("%lld hit\n", addr + i);
  }
  */

  block_size=get_block_size();
  size=get_cache_size(block_size);
  assoc=get_cache_assoc(size);

  printf("Cache block size: %d bytes\n", block_size);
  printf("Cache size: %d bytes\n", size);
  printf("Cache associativity: %d\n", assoc);

  return EXIT_SUCCESS;
}
예제 #3
0
int main(void) {
  int size;
  int assoc;
  int block_size;

  cache_init(0,0);

  block_size=get_block_size();
  size=get_cache_size(block_size);
  assoc=get_cache_assoc(size);

  printf("Cache block size: %d bytes\n", block_size);
  printf("Cache size: %d bytes\n", size);
  printf("Cache associativity: %d\n", assoc);

  return EXIT_SUCCESS;
}
/*
   Returns the associativity of the cache.
*/
int get_cache_assoc() {
  flush_cache();
  //int block_size = get_block_size();
  int cache_size = get_cache_size(0);
  int block_size = get_block_size();
  int addr = 0, replace_addr = 0;

  for (; addr < cache_size; addr += block_size){
      access_cache(addr);
  }

  int special_addr = cache_size * 2 - block_size; // 11111...
  access_cache(special_addr);
  for(; replace_addr < cache_size && access_cache(replace_addr); replace_addr += block_size);

  return cache_size / (replace_addr + block_size);
}
//// DO NOT CHANGE ANYTHING BELOW THIS POINT
int main(void) {
  int size;
  int assoc;
  int block_size;

  /* The cache needs to be initialized, but the parameters will be
     ignored by the mystery caches, as they are hard coded.  You can
     test your geometry paramter discovery routines by calling
     cache_init() w/ your own size and block size values. */
  cache_init(1,1);

  block_size=get_block_size();
  size=get_cache_size(block_size);
  assoc=get_cache_assoc(size);

  printf("Cache block size: %d bytes\n", block_size);
  printf("Cache size: %d bytes\n", size);
  printf("Cache associativity: %d\n", assoc);

  return EXIT_SUCCESS;
}
예제 #6
0
int
main(int argc, char *argv[])
{
	int sflag = 0, s1flag = 0, s2flag = 0, nflag = 0, dflag = 0, eflag = 0;
	char *options, *value;
	extern char *optarg;
	extern int optind;
	int c, d;
	struct rlimit rl;
	int mode = RPC_SVC_MT_AUTO;
	int maxrecsz = RPC_MAXDATASIZE;

	void detachfromtty(void);
	int setmodulus();
	int pk_nodefaultkeys();
	int svc_create_local_service();

	char domainname[MAXNETNAMELEN + 1];

	/*
	 * Set our allowed number of file descriptors to the max
	 * of what the system will allow, limited by FD_SETSIZE.
	 */
	if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
		rlim_t limit;

		if ((limit = rl.rlim_max) > FD_SETSIZE)
			limit = FD_SETSIZE;
		rl.rlim_cur = limit;
		(void) setrlimit(RLIMIT_NOFILE, &rl);
		(void) enable_extended_FILE_stdio(-1, -1);
	}

	__key_encryptsession_pk_LOCAL = &__key_encrypt_pk_2_svc;
	__key_decryptsession_pk_LOCAL = &__key_decrypt_pk_2_svc;
	__key_gendes_LOCAL = &__key_gen_1_svc;

	/*
	 * Pre-option initialisation
	 */
	(void) umask(066);	/* paranoia */
	if (geteuid() != 0) {
		(void) fprintf(stderr, "%s must be run as root\n", argv[0]);
		exit(1);
	}
	setmodulus(HEXMODULUS);
	openlog("keyserv", LOG_PID, LOG_DAEMON);

	/*
	 * keyserv will not work with a null domainname.
	 */
	if (getdomainname(domainname, MAXNETNAMELEN+1) ||
	    (domainname[0] == '\0')) {
		syslog(LOG_ERR, "could not get a valid domainname.\n");
		exit(SMF_EXIT_ERR_CONFIG);
	}

	/*
	 * Initialise security mechanisms
	 */
	cache_size = NULL;
	cache_options = NULL;
	if (init_mechs() == -1) {
		disk_caching = 0;
	}

	defaults();

	while ((c = getopt(argc, argv, "ndDet:cs:")) != -1)
		switch (c) {
		case 'n':
			nflag++;
			break;
		case 'd':
			dflag++;
			use_nobody_keys = FALSE;
			break;
		case 'e':
			eflag++;
			use_nobody_keys = TRUE;
			break;
		case 'D':
			debugging = 1;
			break;
		case 't':
			nthreads = atoi(optarg);
			break;
		case 'c':
			disk_caching = 0;
			break;
		case 's':
			if (!disk_caching) {
				fprintf(stderr, "missing configuration file");
				fprintf(stderr, " or -c option specified\n");
				usage();
			}
			sflag++;
			/*
			 * Which version of [-s] do we have...?
			 */
			if (strchr((const char *) optarg, '=') == NULL) {
				/*
				 * -s <size>
				 */
				if (s1flag) {
					fprintf(stderr, "duplicate"
					    " [-s <size>]\n");
					usage();
				}
				s1flag++;
				default_cache = get_cache_size(optarg);
				break;
			}
			/*
			 * -s <mechtype>=<size>[,...]
			 */
			s2flag++;
			options = optarg;
			while (*options != '\0') {
				d = getsubopt(&options, cache_options, &value);
				if (d == -1) {
					/* Ignore unknown mechtype */
					continue;
				}
				if (value == NULL) {
					fprintf(stderr,
					    "missing cache size for "
					    "mechtype %s\n", cache_options[d]);
					usage();
				}
				cache_size[d] = get_cache_size(value);
			}
			break;
		default:
			usage();
			break;
		}


	if (dflag && eflag) {
		(void) fprintf(stderr, "specify only one of -d and -e\n");
		usage();
	}

	if (use_nobody_keys == FALSE) {
		pk_nodefaultkeys();
	}

	if (optind != argc) {
		usage();
	}

	if (!disk_caching && sflag) {
		fprintf(stderr, "missing configuration file");
		fprintf(stderr, " or -c option specified\n");
		usage();
	}

	if (debugging) {
		if (disk_caching) {
			char **cpp = cache_options;
			int *ip = cache_size;
			(void) fprintf(stderr, "default disk cache size: ");
			if (default_cache < 0) {
				(void) fprintf(stderr, "%d entries\n",
				    abs(default_cache));
			} else {
				(void) fprintf(stderr, "%dMB\n", default_cache);
			}

			(void) fprintf(stderr, "supported mechanisms:\n");
			(void) fprintf(stderr, "\talias\t\tdisk cache size\n");
			(void) fprintf(stderr, "\t=====\t\t===============\n");
			while (*cpp != NULL) {
				(void) fprintf(stderr, "\t%s\t\t", *cpp++);
				if (*ip < 0) {
					(void) fprintf(stderr, "%d entries\n",
					    abs(*ip));
				} else {
					(void) fprintf(stderr, "%dMB\n", *ip);
				}
				ip++;
			}
		} else {
			(void) fprintf(stderr,
			    "common key disk caching disabled\n");
		}
	}
	/*
	 * Post-option initialisation
	 */
	if (disk_caching) {
		int i;
		for (i = 0; mechs[i]; i++) {
			if ((AUTH_DES_COMPAT_CHK(mechs[i])) ||
			    (mechs[i]->keylen < 0) || (mechs[i]->algtype < 0))
				continue;
			create_cache_file(mechs[i]->keylen, mechs[i]->algtype,
			    cache_size[i] ? cache_size[i] : default_cache);
		}
	}
	getrootkey(&masterkey, nflag);

	/*
	 * Set MT mode
	 */
	if (nthreads > 0) {
		(void) rpc_control(RPC_SVC_MTMODE_SET, &mode);
		(void) rpc_control(RPC_SVC_THRMAX_SET, &nthreads);
	}

	/*
	 * Enable non-blocking mode and maximum record size checks for
	 * connection oriented transports.
	 */
	if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrecsz)) {
		syslog(LOG_INFO, "unable to set max RPC record size");
	}

	if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS,
	    "netpath", "keyserv") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service for version %d\n",
		    argv[0], KEY_VERS);
		exit(1);
	}

	if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS2,
	    "netpath", "keyserv") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service for version %d\n",
		    argv[0], KEY_VERS2);
		exit(1);
	}

	if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS3,
	    "netpath", "keyserv") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service for version %d\n",
		    argv[0], KEY_VERS3);
		exit(1);
	}

	if (!debugging) {
		detachfromtty();
	}

	if (svc_create(keyprogram, KEY_PROG, KEY_VERS, "door") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service over doors for version %d\n",
		    argv[0], KEY_VERS);
		exit(1);
	}

	if (svc_create(keyprogram, KEY_PROG, KEY_VERS2, "door") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service over doors for version %d\n",
		    argv[0], KEY_VERS2);
		exit(1);
	}

	if (svc_create(keyprogram, KEY_PROG, KEY_VERS3, "door") == 0) {
		syslog(LOG_ERR,
		    "%s: unable to create service over doors for version %d\n",
		    argv[0], KEY_VERS3);
		exit(1);
	}

	svc_run();
	abort();
	/* NOTREACHED */
	return (0);
}
예제 #7
0
main(int argc, char **argv)
{
	int disk_fd, c;
	char *disk_devname, *ssd_devname, *cachedev;
	sector_t block_size = 0, cache_size = 0;
	sector_t disk_devsize;
	int write_around = 0;
	
	pname = argv[0];
	while ((c = getopt(argc, argv, "fs:b:vr")) != -1) {
		switch (c) {
		case 's':
			cache_size = get_cache_size(optarg);
			break;
		case 'b':
			block_size = get_block_size(optarg);
			/* Block size should be a power of 2 */
                        break;
		case 'v':
			verbose = 1;
                        break;			
		case 'f':
			force = 1;
                        break;
		case 'r':
			write_around = 1;
                        break;
		case '?':
			usage(pname);
		}
	}
	if (optind == argc)
		usage(pname);
	if (block_size == 0)
		block_size = 8;		/* 4KB default blocksize */
	cachedev = argv[optind++];
	if (optind == argc)
		usage(pname);
	ssd_devname = argv[optind++];
	if (optind == argc)
		usage(pname);
	disk_devname = argv[optind];
	disk_fd = open(disk_devname, O_RDONLY);
	if (disk_fd < 0) {
		fprintf(stderr, "%s: Failed to open %s\n", 
			pname, disk_devname);
		exit(1);
	}
	if (ioctl(disk_fd, BLKGETSIZE, &disk_devsize) < 0) {
		fprintf(stderr, "%s: Cannot get disk size %s\n", 
			pname, disk_devname);
		exit(1);				
	}
	printf("cachedev %s, ssd_devname %s, disk_devname %s\n", 
	       cachedev, ssd_devname, disk_devname);
	printf("cache mode %s, block_size %lu, cache_size %lu\n", 
	       ((write_around) ? "WRITE_AROUND" : "WRITE_THRU"), block_size, cache_size);
	sprintf(dmsetup_cmd, "echo 0 %lu flashcache-wt %s %s %d %lu ",
		disk_devsize, disk_devname, ssd_devname, write_around, block_size);
	if (cache_size > 0) {
		char cache_size_str[4096];
		
		sprintf(cache_size_str, "%lu ", cache_size);
		strcat(dmsetup_cmd, cache_size_str);
	}
	/* Go ahead and create the cache.
	 * XXX - Should use the device mapper library for this.
	 */
	strcat(dmsetup_cmd, "| dmsetup create ");
	strcat(dmsetup_cmd, cachedev);
	strcat(dmsetup_cmd, "\n");
	load_module();
	if (verbose)
		fprintf(stderr, "Creating FlashCache_wt Volume : %s", dmsetup_cmd);
	system(dmsetup_cmd);
}
예제 #8
0
파일: info.c 프로젝트: rkd77/elinks-tv
static unsigned char *
get_resource_info(struct terminal *term, void *data)
{
	struct string info;
	long val;
	unsigned longlong bigval;

	if (!init_string(&info))
		return NULL;

#define val_add(text) \
	add_format_to_string(&info, (const char *)text, val);

	add_to_string(&info, _("Resources", term));
	add_to_string(&info, (const unsigned char *)": ");

	val = get_file_handles_count();
	val_add(n_((unsigned char *)"%ld handle", (unsigned char *)"%ld handles", val, term));
	add_to_string(&info, (const unsigned char *)", ");

	val = get_timers_count();
	val_add(n_((unsigned char *)"%ld timer", (unsigned char *)"%ld timers", val, term));
	add_to_string(&info, (const unsigned char *)".\n");

	add_to_string(&info, _("Connections", term));
	add_to_string(&info, (const unsigned char *)": ");

	val = get_connections_count();
	val_add(n_((unsigned char *)"%ld connection", (unsigned char *)"%ld connections", val, term));
	add_to_string(&info, (const unsigned char *)", ");

	val = get_connections_connecting_count();
	val_add(n_((unsigned char *)"%ld connecting", (unsigned char *)"%ld connecting", val, term));
	add_to_string(&info, (const unsigned char *)", ");

	val = get_connections_transfering_count();
	val_add(n_((unsigned char *)"%ld transferring", (unsigned char *)"%ld transferring", val, term));
	add_to_string(&info, (const unsigned char *)", ");

	val = get_keepalive_connections_count();
	val_add(n_((unsigned char *)"%ld keepalive", (unsigned char *)"%ld keepalive", val, term));
	add_to_string(&info, (const unsigned char *)".\n");

	add_to_string(&info, _("Memory cache", term));
	add_to_string(&info, (const unsigned char *)": ");

	/* What about just using Kibi/Mebi representation here? --jonas */
	bigval = get_cache_size();
	add_format_to_string(&info, (const char *)n_((unsigned char *)"%ld byte", (unsigned char *)"%ld bytes", bigval, term), bigval);
	add_to_string(&info, (const unsigned char *)", ");

	val = get_cache_entry_count();
	val_add(n_((unsigned char *)"%ld file", (unsigned char *)"%ld files", val, term));
	add_to_string(&info, (const unsigned char *)", ");

	val = get_cache_entry_used_count();
	val_add(n_((unsigned char *)"%ld in use", (unsigned char *)"%ld in use", val, term));
	add_to_string(&info, (const unsigned char *)", ");

	val = get_cache_entry_loading_count();
	val_add(n_((unsigned char *)"%ld loading", (unsigned char *)"%ld loading", val, term));
	add_to_string(&info, (const unsigned char *)".\n");

	add_to_string(&info, _("Document cache", term));
	add_to_string(&info, (const unsigned char *)": ");

	val = get_format_cache_size();
	val_add(n_((unsigned char *)"%ld formatted", (unsigned char *)"%ld formatted", val, term));
	add_to_string(&info, (const unsigned char *)", ");

	val = get_format_cache_used_count();
	val_add(n_((unsigned char *)"%ld in use", (unsigned char *)"%ld in use", val, term));
	add_to_string(&info, (const unsigned char *)", ");

	val = get_format_cache_refresh_count();
	val_add(n_((unsigned char *)"%ld refreshing", (unsigned char *)"%ld refreshing", val, term));
	add_to_string(&info, (const unsigned char *)".\n");

#ifdef CONFIG_ECMASCRIPT
	add_to_string(&info, _("ECMAScript", term));
	add_to_string(&info, (const unsigned char *)": ");

	val = ecmascript_get_interpreter_count();
	val_add(n_((unsigned char *)"%ld interpreter", (unsigned char *)"%ld interpreters", val, term));
	add_to_string(&info, (const unsigned char *)".\n");
#endif

	add_to_string(&info, _("Interlinking", term));
	add_to_string(&info, (const unsigned char *)": ");
	if (term->master)
		add_to_string(&info, _("master terminal", term));
	else
		add_to_string(&info, _("slave terminal", term));
	add_to_string(&info, (const unsigned char *)", ");

	val = list_size(&terminals);
	val_add(n_((unsigned char *)"%ld terminal", (unsigned char *)"%ld terminals", val, term));
	add_to_string(&info, (const unsigned char *)", ");

	val = list_size(&sessions);
	val_add(n_((unsigned char *)"%ld session", (unsigned char *)"%ld sessions", val, term));
	add_char_to_string(&info, '.');

#ifdef DEBUG_MEMLEAK
	add_char_to_string(&info, '\n');
	add_to_string(&info, _("Memory allocated", term));
	add_to_string(&info, (const unsigned char *)": ");

	val = mem_stats.amount;
	val_add(n_((unsigned char *)"%ld byte", (unsigned char *)"%ld bytes", val, term));
	add_to_string(&info, ", ");

	val = mem_stats.true_amount - mem_stats.amount;
	val_add(n_((unsigned char *)"%ld byte overhead", (unsigned char *)"%ld bytes overhead", val, term));

	add_format_to_string(&info, " (%0.2f%%).",
		(double) (mem_stats.true_amount - mem_stats.amount) / (double) mem_stats.amount * 100);
#endif /* DEBUG_MEMLEAK */

#undef val_add

	return info.source;
}
예제 #9
0
int
main(int argc, char **argv)
{
	int nvram_fd, cache_fd, disk_fd, c;//新增 nvram_fd
	char *disk_devname, *flash_devname, *nvram_devname, *cachedev;//新增 nvram_devname表示nvram缓存路径名字
	struct flash_superblock *sb = (struct flash_superblock *)buf;//flash超级块的对象sb指向buf空间
	struct flash_superblock *nsb = (struct flash_superblock *)nvram_buf;//新增 nb结构体
	sector_t nvram_devsize, cache_devsize, disk_devsize;//新增 nvram_cache_devsize
	sector_t block_size = 0, md_block_size = 0, cache_size = 0, nvram_size = 0;//新增 nvram_size
	sector_t ram_needed;//typedef unsigned long sector_t;
	struct sysinfo i;
	int cache_sectorsize, nvram_sectorsize;//新增 nvram的扇区大小
	int associativity = 512;
	int disk_associativity = 512;
	int ret;
	int cache_mode = -1;
	char *cache_mode_str;
	
	pname = argv[0];
	//flashcache_create -p back flashcache /dev/pma /dev/pmb /dev/loop0
	//flashcache_create [-v] -p back|around|thru [-s cache size] [-b block size] cachedevname flash_devname disk_devname
	while ((c = getopt(argc, argv, "fs:b:d:m:va:p:")) != -1) {
		switch (c) {
		case 's':
			//这个位置以后还可以初始化nvram_size属性
			cache_size = get_cache_size(optarg);//s选项后面跟着的是缓存大小 默认大小,不然就要分别指定两个缓存的大小
			break;
		case 'a':
			associativity = atoi(optarg);//缓存分组大小
			break;
		case 'b':
			block_size = get_block_size(optarg);//缓存块大小  2的n次幂
			/* Block size should be a power of 2 */
                        break;
		case 'd':
			disk_associativity = get_block_size(optarg);//磁盘分组大小
			break;
		case 'm':
			md_block_size = get_block_size(optarg);//元数据块大小
			/* MD block size should be a power of 2 */
                        break;
		case 'v':
			verbose = 1;
                        break;			
		case 'f':
			force = 1;
                        break;
		case 'p':
			if (strcmp(optarg, "back") == 0) {        //默认设置成WB模式
				cache_mode = FLASHCACHE_WRITE_BACK;
				cache_mode_str = "WRITE_BACK";
			} else if ((strcmp(optarg, "thru") == 0) ||
				   (strcmp(optarg, "through") == 0)) {
				cache_mode = FLASHCACHE_WRITE_THROUGH;
				cache_mode_str = "WRITE_THROUGH";
			} else if (strcmp(optarg, "around") == 0) {
				cache_mode = FLASHCACHE_WRITE_AROUND;
				cache_mode_str = "WRITE_AROUND";
			} else
				usage(pname);
                        break;			
		case '?':
			usage(pname);
		}
	}
	if (cache_mode == -1)
		usage(pname);
	if (optind == argc)
		usage(pname);
	if (block_size == 0)
		block_size = 8;		/* 4KB default blocksize */  //缓存块大小默认为8个扇区,4KB
	if (md_block_size == 0)
		md_block_size = 8;	/* 4KB default blocksize */  //元数据块大小也是一样
	//进一步分别获取虚拟设备、flash设备和磁盘设备的名字   如果说参数个数提前用完了optind==argc,则调用usage返回错误信息
	cachedev = argv[optind++];
	if (optind == argc)
		usage(pname);
	//新增 获取nvram的设备路径名
	nvram_devname = argv[optind++];
	if (optind == argc)
		usage(pname);
	flash_devname = argv[optind++];
	if (optind == argc)
		usage(pname);
	disk_devname = argv[optind];
	//新增 对nvram路径名/磁盘分组大小的输出 
	//printf("cachedev %s, nvram_devname %s, flash_devname %s, disk_devname %s cache_mode %s disk_associativity %lu\n", 
	//       cachedev, nvram_devname, flash_devname, disk_devname, cache_mode_str, disk_associativity);
	if (cache_mode == FLASHCACHE_WRITE_BACK)
		printf("FLASHCACHE_WRITE_BACK:block_size %lu, md_block_size %lu, cache_size %lu\n", 
		       block_size, md_block_size, cache_size);
	else
		printf("block_size %lu, cache_size %lu\n", 
		       block_size, cache_size);

	//新增 读取nvram缓存空间的超级块中的数据,并判断nvram中是否已经有数据
	nvram_fd = open(nvram_devname, O_RDONLY);
	if (nvram_fd < 0) {
		fprintf(stderr, "Failed to open %s\n", nvram_devname);
		exit(1);
	}
    lseek(nvram_fd, 0, SEEK_SET);
	if (read(nvram_fd, nvram_buf, 512) < 0) {
		fprintf(stderr, "Cannot read NVRAM superblock %s\n", 
			nvram_devname);
		exit(1);		
	}
	if (nsb->cache_sb_state == CACHE_MD_STATE_DIRTY ||
	    nsb->cache_sb_state == CACHE_MD_STATE_CLEAN ||
	    nsb->cache_sb_state == CACHE_MD_STATE_FASTCLEAN ||
	    nsb->cache_sb_state == CACHE_MD_STATE_UNSTABLE) {
		fprintf(stderr, "%s: Valid Flashcache already exists on %s\n", 
			pname, nvram_devname);
		fprintf(stderr, "%s: Use flashcache_destroy first and then create again %s\n", 
			pname, nvram_devname);
		exit(1);
	}

	//读取flash缓存空间的超级块中的数据
	//指向文件的头部,并从头部开始读取512个字节的数据到buf中  那就应该是超级块只占用一个扇区大小?
	cache_fd = open(flash_devname, O_RDONLY);
	if (cache_fd < 0) {
		fprintf(stderr, "Failed to open %s\n", flash_devname);
		exit(1);
	}
    lseek(cache_fd, 0, SEEK_SET);
	if (read(cache_fd, buf, 512) < 0) {
		fprintf(stderr, "Cannot read Flash superblock %s\n", 
			flash_devname);
		exit(1);		
	}
	//通过flash缓存超级块的clean或者shutdown状态来判断是否已经有缓存数据在flash中
	if (sb->cache_sb_state == CACHE_MD_STATE_DIRTY ||
	    sb->cache_sb_state == CACHE_MD_STATE_CLEAN ||
	    sb->cache_sb_state == CACHE_MD_STATE_FASTCLEAN ||
	    sb->cache_sb_state == CACHE_MD_STATE_UNSTABLE) {
		fprintf(stderr, "%s: Valid Flashcache already exists on %s\n", 
			pname, flash_devname);
		fprintf(stderr, "%s: Use flashcache_destroy first and then create again %s\n", 
			pname, flash_devname);
		exit(1);
	}
	//
	disk_fd = open(disk_devname, O_RDONLY);
	if (disk_fd < 0) {
		fprintf(stderr, "%s: Failed to open %s\n", 
			pname, disk_devname);
		exit(1);
	}

	//新增 获取nvram设备空间大小BLKGETSIZE和物理扇区大小BLKSSZGET
	//并判断nvram缓存数据块大小是否大于nvram物理扇区大小和nvram缓存空间大小是否小于nvram设备大小
	//不过默认cache_size应该为0,所以nvram_size也默认为0
	if (ioctl(nvram_fd, BLKGETSIZE, &nvram_devsize) < 0) {
		fprintf(stderr, "%s: Cannot get nvram size %s\n", 
		pname, nvram_devname);
		exit(1);		
	}
	if (ioctl(nvram_fd, BLKSSZGET, &nvram_sectorsize) < 0) {
		fprintf(stderr, "%s: Cannot get nvram size %s\n", 
			pname, nvram_devname);
		exit(1);		
	}
	if (md_block_size > 0 &&
	    md_block_size * 512 < nvram_sectorsize) {
		fprintf(stderr, "%s: NVRAM device (%s) sector size (%d) cannot be larger than metadata block size (%d) !\n",
		        pname, nvram_devname, nvram_sectorsize, md_block_size * 512);
		exit(1);				
	}
	if (nvram_size && nvram_size > nvram_devsize) {
		fprintf(stderr, "%s: Cache size is larger than nvram size %lu/%lu\n", 
			pname, nvram_size, nvram_devsize);
		exit(1);		
	}

	//获取flash设备的空间大小并写入到cache_devsize中
	if (ioctl(cache_fd, BLKGETSIZE, &cache_devsize) < 0) {
		fprintf(stderr, "%s: Cannot get cache size %s\n", 
			pname, flash_devname);
		exit(1);		
	}
	if (ioctl(disk_fd, BLKGETSIZE, &disk_devsize) < 0) {
		fprintf(stderr, "%s: Cannot get disk size %s\n", 
			pname, disk_devname);
		exit(1);				
	}

	//获取flash设备的物理扇区大小
	if (ioctl(cache_fd, BLKSSZGET, &cache_sectorsize) < 0) {
		fprintf(stderr, "%s: Cannot get cache size %s\n", 
			pname, flash_devname);
		exit(1);		
	}
	//flash设备的物理扇区大小不能大于元数据块的大小   不然元数据块就成了管理flash的最小数据单元了
	if (md_block_size > 0 &&
	    md_block_size * 512 < cache_sectorsize) {
		fprintf(stderr, "%s: SSD device (%s) sector size (%d) cannot be larger than metadata block size (%d) !\n",
		        pname, flash_devname, cache_sectorsize, md_block_size * 512);
		exit(1);				
	}
	//缓存空间大小不能大于flash设备空间大小
	if (cache_size && cache_size > cache_devsize) {
		fprintf(stderr, "%s: Cache size is larger than ssd size %lu/%lu\n", 
			pname, cache_size, cache_devsize);
		exit(1);		
	}

	//新增 输出已获取到的设备信息
	printf("flash:%s缓存大小为%d,设备大小为%d nvram:%s缓存大小为%d,设备大小为%d disk:%s设备大小为%d\n", flash_devname, cache_size, cache_devsize, nvram_devname, nvram_size, nvram_devsize, disk_devname, disk_devsize);

	/* Remind users how much core memory it will take - not always insignificant.
 	 * If it's > 25% of RAM, warn.
         */
 	//如果缓存空间大小没有在参数中赋值,为0,则为设备大小/块大小 *缓存块大小,即整个设备 
 	//新增 nvram_size为0,ram_needed加上nvram设备大小
	if (cache_size == 0 || nvram_size == 0)
		ram_needed = (cache_devsize / block_size) * sizeof(struct cacheblock) + (nvram_devsize / block_size) * sizeof(struct cacheblock);	/* Whole device */
	else
		ram_needed = (cache_size / block_size) * sizeof(struct cacheblock) + (nvram_size / block_size) * sizeof(struct cacheblock);

	sysinfo(&i);
	printf("Flashcache metadata will use %luMB of your %luMB main memory\n",
		ram_needed >> 20, i.totalram >> 20);
	//若是所使用的Flashcache元数据空间占内存空间比例超过1/4则提示     ram_needed不是整个缓存空间的大小吗?为什么说元数据?
	if (!force && ram_needed > (i.totalram * 25 / 100)) {
		fprintf(stderr, "Proportion of main memory needed for flashcache metadata is high.\n");
		fprintf(stderr, "You can reduce this with a smaller cache or a larger blocksize.\n");
		check_sure();
	}
	//printf("输出一次disk_associativity=%lu associativity=%lu\n", disk_associativity, associativity);
	//磁盘分组大小不能大于缓存分组大小
	if (disk_associativity == 0 ||
	    disk_associativity > associativity) {
		fprintf(stderr, "%s: Invalid Disk Associativity %ld\n",
			pname, disk_associativity);
		exit(1);
	}
	//printf("再输出一次disk_associativity=%lu associativity=%lu\n", disk_associativity, associativity);
	//缓存大小也不能大于磁盘大小   
	//新增 加入nvram_size > disk_devsize
	if (!force && (cache_size > disk_devsize || nvram_size > disk_devsize)) {
		fprintf(stderr, "Size of cache volume (%s) || (%s) is larger than disk volume (%s)\n",
			nvram_devname, flash_devname, disk_devname);
		check_sure();
	}
	//新增  先提前输出一遍命令内容  共享cache_mode、block_size、assoc、md_block_size   persistence默认为2,即create
	printf("echo 0 %lu flashcache disk=%s ssd=%s nvram=%s cachedev=%s cachemode=%d 2 blocksize=%lu cachesize=%lu nvramsize=%lu assoc=%d diskassoc=%d md_block_size=%lu"
		" | dmsetup create %s.\n",
		disk_devsize, disk_devname, flash_devname, nvram_devname, cachedev, cache_mode, block_size, 
		cache_size, nvram_size, associativity, disk_associativity, md_block_size,
		cachedev);

	/*
[root@localhost flashcache-3.1.3]# flashcache_create -p back cache1g8g /dev/pma /dev/pmb /dev/loop0
cachedev cache1g8g, nvram_devname /dev/pma, flash_devname /dev/pmb, disk_devname /dev/loop0 cache mode WRITE_BACK
block_size 8, md_block_size 8, cache_size 0
Flashcache metadata will use 58MB of your 64426MB main memory
echo 0 20971520 flashcache /dev/loop0 /dev/pmb /dev/pma cache1g8g 1 2 8 0 0 512 266287972864 8 | dmsetup create cache1g8g
echo 0 20971520 flashcache /dev/loop0 /dev/pmb cachehaha 1 2 8 0 512 140733193388544 8 | dmsetup create cachehaha
	*/
	/*
umount /dev/mapper/cachecache
dmsetup remove cachecache
rmmod flashcache
flashcache_destroy /dev/pmb


make && make install
modprobe pmbd mode="pmbd1,8;hmo50;hms9;pmapY;rdsx1,2;wrsx1,12;"
fdisk -l
losetup /dev/loop0 /home/disk.img 

dd if=/dev/zero of=/root/workspace/disk.img bs=1024k count=131072



make KERNEL_TREE=/usr/src/kernels/2.6.32-504.12.2.el6.x86_64/ && make install
modprobe flashcache
lsmod | grep flashcache
flashcache_create -p back cachecache /dev/pma /dev/pmb /dev/loop0

flashcache_create -p back cachecache /dev/pma /dev/loop0

mkfs.ext3 /dev/mapper/cachecache
mount /dev/mapper/cachecache /home/mount
fio -filename=/home/mount/file.1G -direct=1 -iodepth 1 -thread -rw=randread -ioengine=psync -bs=16k -size=1G -numjobs=10 -runtime=1000 -group_reporting -name=mytest 


echo 0 20971520 flashcache disk=/dev/loop0 ssd=/dev/pmb nvram=/dev/pma cachedev=cachecache cachemode=1 2 blocksize=8 cachesize=0 nvramsize=0 assoc=512 diskassoc=512 md_block_size=8 | dmsetup create cachecache
echo 0 20971520 flashcache /dev/loop0 /dev/pmb /dev/pma cachecache 1 2 8 0 0 512 512 8 | dmsetup create cachecache

	*/

	//设计创建设备的命令  先不加入nvram,不然后面需要加上解析参数的部分才能正常运行
	sprintf(dmsetup_cmd, "echo 0 %lu flashcache %s %s %s %s %d 2 %lu %lu %lu %d %lu %lu"
		" | dmsetup create %s",
		disk_devsize, disk_devname, flash_devname, nvram_devname, cachedev, cache_mode, block_size, 
		cache_size, nvram_size, associativity, disk_associativity, md_block_size,
		cachedev);
	printf("dmsetup_cmd:%s\n", dmsetup_cmd);
	/* Go ahead and create the cache.
	 * XXX - Should use the device mapper library for this.
	 */
	
	load_module();//加载flashcache模块
	if (verbose)
		fprintf(stderr, "Creating FlashCache Volume : \"%s\"\n", dmsetup_cmd);
	ret = system(dmsetup_cmd);//执行命令  创建设备
	if (ret) {
		fprintf(stderr, "%s failed\n", dmsetup_cmd);
		exit(1);
	}
	return 0;
}