8205 Optimize boot archive inode ratio to save memory
authorAlexander Eremin <eremin@milax.org>
Wed, 09 Dec 2009 10:07:02 +0100
changeset 659 230370af933c
parent 658 831357e2155d
child 660 d87123ecef4a
8205 Optimize boot archive inode ratio to save memory
usr/src/cmd/distro_const/DC-manifest.defval.xml
usr/src/cmd/distro_const/DC-manifest.rng
usr/src/cmd/distro_const/dc_defs.py
usr/src/cmd/distro_const/utils/boot_archive_archive.py
usr/src/lib/libti/test_ti.c
usr/src/lib/libti/ti_api.h
usr/src/lib/libti/ti_dcm.c
usr/src/lib/libti_pymod/libti.c
usr/src/lib/libti_pymod/ti_defs.py
--- a/usr/src/cmd/distro_const/DC-manifest.defval.xml	Tue Dec 08 14:07:15 2009 -0700
+++ b/usr/src/cmd/distro_const/DC-manifest.defval.xml	Wed Dec 09 10:07:02 2009 +0100
@@ -264,7 +264,13 @@
 	    from="value" type="element" missing_parent="create">
 		0
 	</default>
-
+	
+	<default nodepath=                                                
+            "img_params/output_image/boot_archive/nbpi"
+	    from="value" type="element" missing_parent="create">
+		0
+	</default>
+	
 	<default nodepath= "img_params/hostname"
 	    from="value" type="element">
 		opensolaris
--- a/usr/src/cmd/distro_const/DC-manifest.rng	Tue Dec 08 14:07:15 2009 -0700
+++ b/usr/src/cmd/distro_const/DC-manifest.rng	Wed Dec 09 10:07:02 2009 +0100
@@ -500,7 +500,14 @@
 						<data type= "unsignedInt"/>
 					</element>
 				</optional>
-
+				
+				<!-- Boot archive number of bytes per inode-->
+				<optional>
+					<element name="nbpi">
+						<data type= "unsignedInt"/>
+					</element>
+				</optional>
+				
 				<!-- If/how to compress boot archive-->
 				<optional>
 					<element name="compression">
--- a/usr/src/cmd/distro_const/dc_defs.py	Tue Dec 08 14:07:15 2009 -0700
+++ b/usr/src/cmd/distro_const/dc_defs.py	Wed Dec 09 10:07:02 2009 +0100
@@ -89,6 +89,7 @@
 BOOT_ARCHIVE_COMPRESSION_LEVEL = \
     OUTPUT_IMAGE_BOOT_ARCHIVE + "/compression/level"
 BOOT_ARCHIVE_SIZE_PAD = OUTPUT_IMAGE_BOOT_ARCHIVE + "/size_pad_mb"
+BOOT_ARCHIVE_BYTES_PER_INODE = OUTPUT_IMAGE_BOOT_ARCHIVE + "/nbpi"
 COMPRESSION_TYPE = IMG_PARAMS + "/live_img_compression/type"
 COMPRESSION_LEVEL = IMG_PARAMS + "/live_img_compression/level"
 BUILD_AREA = IMG_PARAMS + "/build_area"
--- a/usr/src/cmd/distro_const/utils/boot_archive_archive.py	Tue Dec 08 14:07:15 2009 -0700
+++ b/usr/src/cmd/distro_const/utils/boot_archive_archive.py	Wed Dec 09 10:07:02 2009 +0100
@@ -31,6 +31,7 @@
 import stat
 import signal
 from subprocess import Popen, PIPE
+from math import floor,log
 from osol_install.ManifestRead import ManifestRead
 from osol_install.install_utils import find
 from osol_install.install_utils import dir_size
@@ -41,6 +42,7 @@
 from osol_install.distro_const.dc_defs import BOOT_ARCHIVE_COMPRESSION_LEVEL
 from osol_install.distro_const.dc_defs import BOOT_ARCHIVE_COMPRESSION_TYPE
 from osol_install.distro_const.dc_defs import BOOT_ARCHIVE_SIZE_PAD
+from osol_install.distro_const.dc_defs import BOOT_ARCHIVE_BYTES_PER_INODE
 from osol_install.distro_const.dc_defs import BA_FILENAME_SUN4U
 from osol_install.distro_const.dc_defs import BA_FILENAME_X86
 from osol_install.distro_const.dc_defs import BA_FILENAME_AMD64
@@ -50,7 +52,8 @@
 from osol_install.ti_defs import TI_ATTR_TARGET_TYPE, \
     TI_TARGET_TYPE_DC_RAMDISK, TI_ATTR_DC_RAMDISK_DEST, \
     TI_ATTR_DC_RAMDISK_FS_TYPE, TI_DC_RAMDISK_FS_TYPE_UFS, \
-    TI_ATTR_DC_RAMDISK_SIZE, TI_ATTR_DC_RAMDISK_BOOTARCH_NAME
+    TI_ATTR_DC_RAMDISK_SIZE, TI_ATTR_DC_RAMDISK_BOOTARCH_NAME, \
+    TI_ATTR_DC_RAMDISK_BYTES_PER_INODE
 
 # A few commands
 AWK = "/usr/bin/awk"
@@ -179,6 +182,45 @@
 
 
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+def get_boot_archive_nbpi(size, rootpath):
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    """ Get the number of bytes per inode for boot archive. 
+
+	Args:
+	  size : boot archive size in bytes.   
+	  rootpath : boot archive directory.
+
+	Returns: number of bytes per inode
+
+	Raises: None
+
+    """
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    nbpi = 0
+    fcount = 0
+    
+    # Get total number of inodes needed for boot archive
+    for root, subdirs, files in os.walk(rootpath):
+	for f in (files + subdirs):
+	    fcount += 1
+
+    # Find optimal nbpi
+    nbpi = int(round(size / fcount))
+
+    # round the nbpi value to the largest power of 2
+    # which is less than or equal to calculated value
+    if nbpi is not 0:
+	nbpi = pow(2,floor(log(nbpi,2)))
+
+    if (nbpi != 0):
+	print "Calculated number of bytes per inode: %d." % (nbpi)
+    else:
+	print "Calculation of nbpi failed, default will be used."
+
+    return nbpi
+
+
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 def release_archive():
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     """ Release archive.
@@ -307,6 +349,17 @@
                       ": Boot archive padding size is missing from manifest "
                       "or invalid.")
 
+BA_BYTES_PER_INODE_STR = get_manifest_value(MANIFEST_READER_OBJ,
+    BOOT_ARCHIVE_BYTES_PER_INODE)
+if BA_BYTES_PER_INODE_STR is not None:
+    try:
+	BA_BYTES_PER_INODE = int(BA_BYTES_PER_INODE_STR)
+    except ValueError:
+	pass
+    if (BA_BYTES_PER_INODE == 0):
+	print "Boot archive nbpi has not been specified in manifest, " \
+	    "it will be calculated"
+
 # Remove any old stale archive.
 GZ_ARCH_FILE = BA_ARCHFILE + ".gz"
 if (os.path.exists(GZ_ARCH_FILE)):
@@ -342,6 +395,10 @@
 BOOT_ARCHIVE_SIZE = \
     int(round((BOOT_ARCHIVE_SIZE * OVERHEAD) + (PADDING * 1024)))
 
+if (BA_BYTES_PER_INODE == 0):
+    BA_BYTES_PER_INODE = get_boot_archive_nbpi(
+	BOOT_ARCHIVE_SIZE * 1024, BA_BUILD) 
+
 print "Creating boot archive with padded size of %d MB..." % (
     (BOOT_ARCHIVE_SIZE / 1024))
 
@@ -352,6 +409,7 @@
     TI_ATTR_DC_RAMDISK_DEST: BA_LOFI_MNT_PT,
     TI_ATTR_DC_RAMDISK_FS_TYPE: TI_DC_RAMDISK_FS_TYPE_UFS,
     TI_ATTR_DC_RAMDISK_SIZE: BOOT_ARCHIVE_SIZE,
+    TI_ATTR_DC_RAMDISK_BYTES_PER_INODE: BA_BYTES_PER_INODE,
     TI_ATTR_DC_RAMDISK_BOOTARCH_NAME: BA_ARCHFILE })
 signal.signal (signal.SIGINT, signal.SIG_DFL)
 if (STATUS != 0):
@@ -360,15 +418,6 @@
         ": Unable to create boot archive: ti_create_target returned: " +
         os.strerror(STATUS))
 
-# Allow all space to be used.
-# Saving 10% space as typical on UFS buys nothing for a ramdisk.
-CMD = TUNEFS + " -m 0 " + BA_LOFI_MNT_PT + " >/dev/null"
-COPY_STATUS = os.system(CMD)
-if (COPY_STATUS != 0):  # Print a warning and forge ahead anyway...
-    print >> sys.stderr, (
-        "Warning: Could not tunefs the boot archive to use all space:" +
-        os.strerror(COPY_STATUS >> 8))
-
 if IS_SPARC:
     ETC_SYSTEM = open(BA_BUILD + "/etc/system", "a+")
     ETC_SYSTEM.write("set root_is_ramdisk=1\n")
--- a/usr/src/lib/libti/test_ti.c	Tue Dec 08 14:07:15 2009 -0700
+++ b/usr/src/lib/libti/test_ti.c	Wed Dec 09 10:07:02 2009 +0100
@@ -118,6 +118,7 @@
 	    " ramdisk options (select ramdisk type: option \"-t r\")\n"
 	    "  -r ramdisk_size   size of ramdisk in Kbytes\n"
 	    "  -m ramdisk_mp     mount point of ramdisk\n"
+	    "  -i nbpi           number of bytes per inode\n"
 	    "  -b boot_archive   file name of boot archive\n"
 	    "  -R                release indicated target (see -m, -b)\n"
 	    " create directory for DC (select type \"-t d\")\n"
@@ -971,6 +972,7 @@
 	uint32_t	zfs_vol_size = 2048;
 	uint16_t	zfs_vol_type = 0;
 	uint32_t	dc_ramdisk_size = 0;
+	uint32_t	dc_ramdisk_nbpi = 0;
 	char		*dc_bootarch_name = NULL;
 	char		*dc_dest_path = NULL;
 	boolean_t	dc_ramdisk_release = B_FALSE;
@@ -1008,10 +1010,11 @@
 	 * u - zvol type
 	 * m - ramdisk mountpoint
 	 * b - boot archive file name
+	 * i - number of bytes per inode
 	 * n - BE name
 	 */
 
-	while ((opt = getopt(argc, argv, "x:b:d:f:m:n:p:Rr:t:z:u:hcws")) !=
+	while ((opt = getopt(argc, argv, "x:b:d:f:i:m:n:p:Rr:t:z:u:hcws")) !=
 	    EOF) {
 		switch (opt) {
 
@@ -1051,6 +1054,10 @@
 				config_file = optarg;
 			break;
 
+			case 'i':
+				dc_ramdisk_nbpi = atoi(optarg);
+			break;
+
 			case 'm':
 				dc_dest_path = optarg;
 			break;
@@ -1293,6 +1300,18 @@
 				nvlist_free(target_attrs);
 				exit(1);
 			}
+			if (!dc_ramdisk_release &&
+			    (dc_ramdisk_nbpi != 0) &&
+			    nvlist_add_uint32(target_attrs,
+			    TI_ATTR_DC_RAMDISK_BYTES_PER_INODE,
+			    dc_ramdisk_nbpi) != 0) {
+				(void) fprintf(stderr, "ERR: Couldn't add "
+				    "TI_ATTR_DC_RAMDISK_BYTES_PER_INODE "
+				    "to nvlist\n");
+
+				nvlist_free(target_attrs);
+				exit(1);
+			}
 			/* create target */
 
 			if (dc_ramdisk_release) {
--- a/usr/src/lib/libti/ti_api.h	Tue Dec 08 14:07:15 2009 -0700
+++ b/usr/src/lib/libti/ti_api.h	Wed Dec 09 10:07:02 2009 +0100
@@ -290,6 +290,9 @@
 /* string - ramdisk mountpoint */
 #define	TI_ATTR_DC_RAMDISK_BOOTARCH_NAME	"ti_dc_ramdisk_bootarch_name"
 
+/* uint_32_t - # of bytes per inode */
+#define	TI_ATTR_DC_RAMDISK_BYTES_PER_INODE	"ti_dc_ramdisk_bytes_per_inode"
+
 /* string - ramdisk fs type */
 #define	TI_ATTR_DC_RAMDISK_DEST		"ti_dc_ramdisk_dest"
 
--- a/usr/src/lib/libti/ti_dcm.c	Tue Dec 08 14:07:15 2009 -0700
+++ b/usr/src/lib/libti/ti_dcm.c	Wed Dec 09 10:07:02 2009 +0100
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -130,6 +130,7 @@
  * Attributes (all required):
  *	TI_TARGET_TYPE_DC_RAMDISK - indicates type of target to be created
  *	TI_ATTR_DC_RAMDISK_SIZE - ramdisk size in K
+ *	TI_ATTR_DC_RAMDISK_BYTES_PER_INODE - number of bytes per inode
  *	TI_ATTR_DC_RAMDISK_BOOTARCH_NAME - name of boot archive
  *	TI_ATTR_DC_RAMDISK_DEST - ramdisk path
  */
@@ -140,6 +141,7 @@
 	char		*bootarch_name;	/* attr: name of boot archive */
 	char		*ramdisk_path;	/* attr: path of boot archive */
 	uint16_t	ramdisk_fstype;	/* attr: path of boot archive */
+	uint32_t	ramdisk_nbpi;	/* attr: number of bytes per inode */
 	char		cmd[IDM_MAXCMDLEN];	/* to hold shell command */
 	char		pseudod[512];	/* newfs returns pseudodevice */
 	int		ret = 0;	/* function return code */
@@ -153,6 +155,13 @@
 		    "RAM disk size not provided\n");
 		return (TI_E_INVALID_RAMDISK_ATTR);
 	}
+	if (nvlist_lookup_uint32(attrs, TI_ATTR_DC_RAMDISK_BYTES_PER_INODE,
+	    &ramdisk_nbpi) != 0) {
+		ls_write_dbg_message(TIDC, LS_DBGLVL_INFO,
+		    "Number of bytes per inode not provided, newfs(1M)"
+		    " will use the default value");
+		ramdisk_nbpi = 0;
+	}
 	if (nvlist_lookup_string(attrs, TI_ATTR_DC_RAMDISK_BOOTARCH_NAME,
 	    &bootarch_name) != 0) {
 		ls_write_dbg_message(TIDC, LS_DBGLVL_ERR,
@@ -195,8 +204,12 @@
 	}
 	rollback_lofiadm = B_TRUE;	/* rollback if subsequent cmd fails */
 	/* make file system on ramdisk */
-	(void) snprintf(cmd, sizeof (cmd), "/usr/sbin/newfs %s 0</dev/null",
-	    pseudod);
+	if (ramdisk_nbpi != 0)
+		(void) snprintf(cmd, sizeof (cmd), "/usr/sbin/newfs -m 0 "
+		    "-o space -i %d %s 0</dev/null", ramdisk_nbpi, pseudod);
+	else
+		(void) snprintf(cmd, sizeof (cmd), "/usr/sbin/newfs -m 0 "
+		    "-o space %s 0</dev/null", pseudod);
 	if (dcm_system(cmd) == -1) {
 		ls_write_dbg_message(TIDC, LS_DBGLVL_ERR,
 		    "Couldn't create newfs cmd=<%s>\n", cmd);
--- a/usr/src/lib/libti_pymod/libti.c	Tue Dec 08 14:07:15 2009 -0700
+++ b/usr/src/lib/libti_pymod/libti.c	Wed Dec 09 10:07:02 2009 +0100
@@ -38,11 +38,11 @@
  * c function (ex. py_ti_create_target)
  */
 static	PyMethodDef libtiMethods[] = {
-    {"ti_create_target", py_ti_create_target, METH_VARARGS,
-    "Create a target"},
-    {"ti_release_target", py_ti_release_target, METH_VARARGS,
-    "Release a target"},
-    {NULL, NULL, 0, NULL} };
+	{"ti_create_target", py_ti_create_target, METH_VARARGS,
+	"Create a target"},
+	{"ti_release_target", py_ti_release_target, METH_VARARGS,
+	"Release a target"},
+	{NULL, NULL, 0, NULL} };
 
 struct attr_node {
 	char		*attribute;
@@ -62,7 +62,8 @@
 	{TI_ATTR_BE_SHARED_FS_NAMES, DATA_TYPE_STRING_ARRAY},
 	{TI_ATTR_BE_SHARED_FS_NUM, DATA_TYPE_UINT16},
 	{TI_ATTR_DC_RAMDISK_BOOTARCH_NAME, DATA_TYPE_STRING},
-	{TI_ATTR_DC_RAMDISK_DEST,DATA_TYPE_STRING},
+	{TI_ATTR_DC_RAMDISK_BYTES_PER_INODE, DATA_TYPE_UINT32},
+	{TI_ATTR_DC_RAMDISK_DEST, DATA_TYPE_STRING},
 	{TI_ATTR_DC_RAMDISK_FS_TYPE, DATA_TYPE_UINT16},
 	{TI_ATTR_DC_RAMDISK_SIZE, DATA_TYPE_UINT32},
 	{TI_ATTR_DC_UFS_DEST, DATA_TYPE_STRING},
@@ -145,15 +146,15 @@
 	 * Get each uint8_t in the list, convert from PyObject
 	 * to uint8_t and put into the array.
 	 */
-	for (index = 0; index < len; index++) { 
+	for (index = 0; index < len; index++) {
 		val_array[index] = (uint8_t)PyInt_AsLong(
 		    PyList_GetItem(pvalue, index));
-	}	
+	}
 
 	/*
 	 * and place the array into the nvlist
 	 */
-        if (nvlist_add_uint8_array(attrs, attribute, val_array, len) != 0) {
+	if (nvlist_add_uint8_array(attrs, attribute, val_array, len) != 0) {
 		free(val_array);
 		return (B_FALSE);
 	}
@@ -198,15 +199,15 @@
 	 * Get each uint16_t in the list, convert from PyObject
 	 * to uint16_t and put into the array.
 	 */
-	for (index = 0; index < len; index++) { 
+	for (index = 0; index < len; index++) {
 		val_array[index] = (uint16_t)PyInt_AsLong(
 		    PyList_GetItem(pvalue, index));
-	}	
+	}
 
 	/*
 	 * and place the array into the nvlist
 	 */
-        if (nvlist_add_uint16_array(attrs, attribute, val_array, len) != 0) {
+	if (nvlist_add_uint16_array(attrs, attribute, val_array, len) != 0) {
 		free(val_array);
 		return (B_FALSE);
 	}
@@ -250,15 +251,15 @@
 	 * Get each uint64_t in the list, convert from PyObject
 	 * to uint64_t and put into the array.
 	 */
-	for (index = 0; index < len ; index++) { 
+	for (index = 0; index < len; index++) {
 		val_array[index] = (uint64_t)PyLong_AsUnsignedLong(
 		    PyList_GetItem(pvalue, index));
-	}	
+	}
 
 	/*
 	 * and place the array into the nvlist
 	 */
-        if (nvlist_add_uint64_array(attrs, attribute,
+	if (nvlist_add_uint64_array(attrs, attribute,
 	    val_array, len) != 0) {
 		free(val_array);
 		return (B_FALSE);
@@ -272,7 +273,7 @@
  * Add a boolean_array into the nvlist
  * Arguments: attrs - nvlist_t to put the boolean array into
  *	      attribute - the name of the nvlist
- *            pvalue - list of booleans 
+ *	      pvalue - list of booleans
  * Returns: B_TRUE on success
  *          B_FALSE on failure
  */
@@ -283,7 +284,7 @@
 	Py_ssize_t	len, index;
 
 	/*
-	 * Find out how big the list of booleans is. 
+	 * Find out how big the list of booleans is.
 	 */
 	len = PyList_Size(pvalue);
 	if (len <= 0) {
@@ -294,7 +295,7 @@
 	/*
 	 * malloc the array accoringly
 	 */
-	val_array = malloc(len * sizeof(boolean_t));
+	val_array = malloc(len * sizeof (boolean_t));
 	if (val_array == NULL) {
 		return (B_FALSE);
 	}
@@ -304,17 +305,17 @@
 	 * Get each boolean in the list, convert from PyObject
 	 * to boolean and put into the array.
 	 */
-	for (index = 0; index < len ; index++) { 
+	for (index = 0; index < len; index++) {
 		if (PyList_GetItem(pvalue, index) == Py_True)
 			val_array[index] = B_TRUE;
 		else
 			val_array[index] = B_FALSE;
-	}	
+	}
 
 	/*
 	 * and place the array into the nvlist
 	 */
-        if (nvlist_add_boolean_array(attrs, attribute,
+	if (nvlist_add_boolean_array(attrs, attribute,
 	    val_array, len) != 0) {
 		free(val_array);
 		return (B_FALSE);
@@ -328,20 +329,20 @@
  * Add a string_array into the nvlist
  * Arguments: attrs - nvlist_t to put the string array into
  *	      attribute - the name of the nvlist
- *            pvalue - list of strings 
+ *            pvalue - list of strings
  * Returns: B_TRUE on success
  *          B_FALSE on failure
  */
 static boolean_t
 add_string_array(nvlist_t *attrs, char *attribute, PyObject *pvalue)
 {
-	char		**val_array;
-	char		*value;
+	char	**val_array;
+	char	*value;
 	Py_ssize_t	len, index;
 
 
 	/*
-	 * Find out how big the list of strings is. 
+	 * Find out how big the list of strings is.
 	 */
 	len = PyList_Size(pvalue);
 	if (len <= 0) {
@@ -361,10 +362,10 @@
 	 * Get each string in the list, convert from PyObject
 	 * to string and put into the array.
 	 */
-	for (index = 0; index < len ; index++) { 
+	for (index = 0; index < len; index++) {
 		value = PyString_AsString(
-		    PyList_GetItem(pvalue,index));
-   		val_array[index] = value;
+		    PyList_GetItem(pvalue, index));
+		val_array[index] = value;
 	}
 
 	/*
@@ -384,7 +385,7 @@
  * Add a nvlist_array into the nvlist
  * Arguments: attrs - nvlist_t to put the nvlist array into
  *	      attribute - the name of the nvlist
- *            pvalue - list of nvlist_ts 
+ *            pvalue - list of nvlist_ts
  * Returns: B_TRUE on success
  *          B_FALSE on failure
  */
@@ -398,7 +399,7 @@
 	int		ret = B_TRUE;
 
 	/*
-	 * Find out how big the list of nvlists is. 
+	 * Find out how big the list of nvlists is.
 	 */
 	len = PyTuple_Size(pvalue);
 	if (len <= 0) {
@@ -418,11 +419,11 @@
 	 * Get each nvlist in the list, convert from PyObject
 	 * to nvlist and put into the array.
 	 */
-	for (index = 0; index < len ; index++) { 
+	for (index = 0; index < len; index++) {
 		/*
 		 * Get the list
 		 */
-		list_obj = PyTuple_GetItem(pvalue,index);
+		list_obj = PyTuple_GetItem(pvalue, index);
 		if (list_obj == NULL) {
 			ret = B_FALSE;
 			goto done;
@@ -454,7 +455,7 @@
 	}
 
 done:
-	for (i = 0; i < index ; i++) { 
+	for (i = 0; i < index; i++) {
 		nvlist_free(val_array[i]);
 	}
 	free(val_array);
@@ -467,15 +468,15 @@
  * function used by the bsearch to compare the string
  * field in the nodes.
  */
-static
-int attr_compare(const void *attr1, const void *attr2)
+static int
+attr_compare(const void *attr1, const void *attr2)
 {
 	return (strcmp(((const struct attr_node *)attr1)->attribute,
 	    ((const struct attr_node *)attr2)->attribute));
 }
 
 /*
- * ti_setup_nvlist 
+ * ti_setup_nvlist
  * This will place the python args into the C nvlist
  */
 int
@@ -495,8 +496,8 @@
 		node.attribute = PyString_AsString(pkey);
 
 		node_ptr = bsearch(&node, attr_table,
-		    sizeof(attr_table)/sizeof(struct attr_node),
-		    sizeof(struct attr_node), attr_compare);
+		    sizeof (attr_table) / sizeof (struct attr_node),
+		    sizeof (struct attr_node), attr_compare);
 
 		if (node_ptr == NULL)
 			return (TI_E_PY_INVALID_ARG);
@@ -504,71 +505,78 @@
 		switch (node_ptr->type) {
 			case DATA_TYPE_UINT32:
 				/*
-		 	 	 * Place the uint32 properties into the nvlist
-		 	 	 */
+				 * Place the uint32 properties into the nvlist
+				 */
 				if (nvlist_add_uint32(attrs,
-				    node.attribute, (uint32_t)PyInt_AsLong(pvalue)) != 0) {
+				    node.attribute, (uint32_t)PyInt_AsLong(
+				    pvalue)) != 0) {
 					return (TI_E_PY_INVALID_ARG);
 				}
 				break;
 			case DATA_TYPE_STRING:
 				/*
-		 		 * Place the string properties into the nvlist
-		 		 */
+				 * Place the string properties into the nvlist
+				 */
 				if (nvlist_add_string(attrs, node.attribute,
-	    			    PyString_AsString(pvalue)) != 0) {
+				    PyString_AsString(pvalue)) != 0) {
 					return (TI_E_PY_INVALID_ARG);
 				}
 				break;
 			case DATA_TYPE_UINT16:
 				/*
-		 		 * Place the uint 16 properties into the nvlist
-		 		 */
-                		if (nvlist_add_uint16(attrs, node.attribute,
+				 * Place the uint 16 properties into the nvlist
+				 */
+				if (nvlist_add_uint16(attrs, node.attribute,
 				    (uint16_t)PyInt_AsLong(pvalue)) != 0) {
 					return (TI_E_PY_INVALID_ARG);
 				}
 				break;
 			case DATA_TYPE_BOOLEAN:
 				/*
-		 		 * Place the boolean properties into the nvlist
-		 		 */
+				 * Place the boolean properties into the nvlist
+				 */
 				if (pvalue == Py_True)
 					value = B_TRUE;
 				else
 					value = B_FALSE;
-                		if (nvlist_add_boolean_value(attrs, node.attribute,
-				    value) != 0) {
+				if (nvlist_add_boolean_value(attrs,
+				    node.attribute, value) != 0) {
 					return (TI_E_PY_INVALID_ARG);
 				}
 				break;
 			case DATA_TYPE_UINT8_ARRAY:
-				if (!add_uint8_array(attrs, node.attribute, pvalue)) {
+				if (!add_uint8_array(attrs, node.attribute,
+				    pvalue)) {
 					return (TI_E_PY_INVALID_ARG);
 				}
 				break;
 			case DATA_TYPE_UINT16_ARRAY:
-				if (!add_uint16_array(attrs, node.attribute, pvalue)) {
+				if (!add_uint16_array(attrs, node.attribute,
+				    pvalue)) {
 					return (TI_E_PY_INVALID_ARG);
 				}
 				break;
 			case DATA_TYPE_UINT64_ARRAY:
-				if (!add_uint64_array(attrs, node.attribute, pvalue)) {
+				if (!add_uint64_array(attrs, node.attribute,
+				    pvalue)) {
 					return (TI_E_PY_INVALID_ARG);
 				}
 				break;
 			case DATA_TYPE_BOOLEAN_ARRAY:
-				if (!add_boolean_array(attrs, node.attribute, pvalue)) {
+				if (!add_boolean_array(attrs, node.attribute,
+				    pvalue)) {
 					return (TI_E_PY_INVALID_ARG);
 				}
 				break;
 			case DATA_TYPE_STRING_ARRAY:
-				if (!add_string_array(attrs, node.attribute, pvalue)) {
+				if (!add_string_array(attrs, node.attribute,
+				    pvalue)) {
 					return (TI_E_PY_INVALID_ARG);
 				}
 				break;
 			case DATA_TYPE_NVLIST_ARRAY:
-				if (!add_nvlist_array(attrs, node.attribute, pvalue)) {
+				if (!add_nvlist_array(attrs, node.attribute,
+				    pvalue)) {
 					return (TI_E_PY_INVALID_ARG);
 				}
 				break;
@@ -594,38 +602,38 @@
 	PyObject	*ti_properties;
 
 	if (!Py_IsInitialized()) {
-        	Py_Initialize();
+		Py_Initialize();
 	}
 
 	/*
 	 * Parse the List input
 	 */
 	if (!PyArg_ParseTuple(args, "O", &ti_properties)) {
-		return Py_BuildValue("i", TI_E_PY_INVALID_ARG);
+		return (Py_BuildValue("i", TI_E_PY_INVALID_ARG));
 	}
 
 	if (ti_properties == NULL) {
-		return Py_BuildValue("i", TI_E_PY_INVALID_ARG);
+		return (Py_BuildValue("i", TI_E_PY_INVALID_ARG));
 	}
 
 	if (nvlist_alloc(&attrs, NV_UNIQUE_NAME, 0) != 0) {
-		return Py_BuildValue("i", TI_E_PY_INVALID_ARG);
+		return (Py_BuildValue("i", TI_E_PY_INVALID_ARG));
 	}
 
 	if ((ret = ti_setup_nvlist(attrs, ti_properties)) != TI_E_SUCCESS) {
-                nvlist_free(attrs);
-		return Py_BuildValue("i", ret);
+		nvlist_free(attrs);
+		return (Py_BuildValue("i", ret));
 	}
 
-	
+
 	ret = ti_create_target(attrs, NULL);
 	if (ret != TI_E_SUCCESS) {
-                nvlist_free(attrs);
-		return Py_BuildValue("i", ret);
+		nvlist_free(attrs);
+		return (Py_BuildValue("i", ret));
 	}
 
-        nvlist_free(attrs);
-	return Py_BuildValue("i", TI_E_SUCCESS);
+	nvlist_free(attrs);
+	return (Py_BuildValue("i", TI_E_SUCCESS));
 }
 
 /*
@@ -642,35 +650,35 @@
 	PyObject	*ti_properties;
 
 	if (!Py_IsInitialized()) {
-        	Py_Initialize();
+		Py_Initialize();
 	}
 
 	/*
 	 * Parse the List input
 	 */
 	if (!PyArg_ParseTuple(args, "O", &ti_properties)) {
-		return Py_BuildValue("i", TI_E_PY_INVALID_ARG);
+		return (Py_BuildValue("i", TI_E_PY_INVALID_ARG));
 	}
 
 	if (ti_properties == NULL) {
-		return Py_BuildValue("i", TI_E_PY_INVALID_ARG);
+		return (Py_BuildValue("i", TI_E_PY_INVALID_ARG));
 	}
 
 	if (nvlist_alloc(&attrs, NV_UNIQUE_NAME, 0) != 0) {
-		return Py_BuildValue("i", TI_E_PY_INVALID_ARG);
+		return (Py_BuildValue("i", TI_E_PY_INVALID_ARG));
 	}
 
 	if ((ret = ti_setup_nvlist(attrs, ti_properties)) != TI_E_SUCCESS) {
-                nvlist_free(attrs);
-		return Py_BuildValue("i", ret);
+		nvlist_free(attrs);
+		return (Py_BuildValue("i", ret));
 	}
 
 	ret = ti_release_target(attrs);
 	if (ret != TI_E_SUCCESS) {
-                nvlist_free(attrs);
-		return Py_BuildValue("i", ret);
+		nvlist_free(attrs);
+		return (Py_BuildValue("i", ret));
 	}
 
-        nvlist_free(attrs);
-	return Py_BuildValue("i", TI_E_SUCCESS);
+	nvlist_free(attrs);
+	return (Py_BuildValue("i", TI_E_SUCCESS));
 }
--- a/usr/src/lib/libti_pymod/ti_defs.py	Tue Dec 08 14:07:15 2009 -0700
+++ b/usr/src/lib/libti_pymod/ti_defs.py	Wed Dec 09 10:07:02 2009 +0100
@@ -99,6 +99,7 @@
     TI_DEFINES['TI_ATTR_DC_RAMDISK_BOOTARCH_NAME'].strip('"')
 TI_ATTR_DC_RAMDISK_DEST = TI_DEFINES['TI_ATTR_DC_RAMDISK_DEST'].strip('"')
 TI_ATTR_DC_UFS_DEST = TI_DEFINES['TI_ATTR_DC_UFS_DEST'].strip('"')
+TI_ATTR_DC_RAMDISK_BYTES_PER_INODE = TI_DEFINES['TI_ATTR_DC_RAMDISK_BYTES_PER_INODE'].strip('"')  
 
 TMP = TI_DEFINES['TI_DC_RAMDISK_FS_TYPE_UFS']
 TI_DC_RAMDISK_FS_TYPE_UFS = \