6984618 Not preserving hard links in boot archive during fiocompression affects Sparc text media
--- a/usr/src/cmd/distro_const/DC-manifest.rng Mon Sep 20 09:00:45 2010 -0700
+++ b/usr/src/cmd/distro_const/DC-manifest.rng Tue Sep 21 10:21:04 2010 +0200
@@ -18,8 +18,7 @@
CDDL HEADER END
-Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-Use is subject to license terms.
+Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
-->
<!--
@@ -482,10 +481,15 @@
=======================================================================
-->
<define name="nm_boot_archive_compression">
- <!-- enum of gzip, none -->
+ <!-- enum of gzip, dcfs, none
+
+ 'gzip' and 'none' are applicable to x86 platform while
+ 'dcfs' and 'none' are applicable to Sparc.
+ -->
<attribute name="type">
<choice>
<value>gzip</value>
+ <value>dcfs</value>
<value>none</value>
</choice>
</attribute>
--- a/usr/src/cmd/distro_const/auto_install/ai_sparc_image.xml Mon Sep 20 09:00:45 2010 -0700
+++ b/usr/src/cmd/distro_const/auto_install/ai_sparc_image.xml Tue Sep 21 10:21:04 2010 +0200
@@ -156,9 +156,9 @@
<boot_archive>
<!--
If/how to compress the boot archive. Valid
- types are gzip and none
+ types are dcfs or none.
-->
- <compression type="gzip" level="9"/>
+ <compression type="dcfs"/>
<!--
SMF service profiles to apply to the boot archive.
@@ -631,6 +631,10 @@
<base_include type="dir">var/svc/manifest</base_include>
<base_include type="dir">var/svc/profile</base_include>
<base_include type="dir">var/sadm</base_include>
+
+ <!--
+ Files which have to be left uncompressed in boot archive.
+ -->
<base_include type="file" fiocompress="false">etc/svc/repository.db</base_include>
<base_include type="file" fiocompress="false">etc/dev/.devfsadm_dev.lock</base_include>
<base_include type="file" fiocompress="false">etc/name_to_major</base_include>
--- a/usr/src/cmd/distro_const/text_install/text_mode_sparc.xml Mon Sep 20 09:00:45 2010 -0700
+++ b/usr/src/cmd/distro_const/text_install/text_mode_sparc.xml Tue Sep 21 10:21:04 2010 +0200
@@ -137,9 +137,9 @@
<boot_archive>
<!--
If/how to compress the boot archive. Valid
- types are gzip and none
+ types are dcfs or none.
-->
- <compression type="gzip" level="9"/>
+ <compression type="dcfs"/>
<!--
SMF service profiles to apply to the
boot archive. If the "use_build_sys_file"
@@ -782,6 +782,9 @@
<base_include type="dir">var/svc/manifest</base_include>
<base_include type="dir">var/svc/profile</base_include>
<base_include type="dir">var/sadm</base_include>
+ <!--
+ Files which have to be left uncompressed in boot archive.
+ -->
<base_include type="file" fiocompress="false">etc/svc/repository.db</base_include>
<base_include type="file" fiocompress="false">etc/dev/.devfsadm_dev.lock</base_include>
<base_include type="file" fiocompress="false">etc/name_to_major</base_include>
--- a/usr/src/cmd/distro_const/utils/boot_archive_archive.py Mon Sep 20 09:00:45 2010 -0700
+++ b/usr/src/cmd/distro_const/utils/boot_archive_archive.py Tue Sep 21 10:21:04 2010 +0200
@@ -86,27 +86,92 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
os.chdir(src)
- compress_flist = find(["."])
+
+ #
+ # Create list of boot archive files/directories.
+ # Since passed with '.' relative path, find() generates paths
+ # starting with './'
+ #
+ ba_flist = find(["."])
errors = False
- for cfile in compress_flist:
- # strip off the leading ./ and the trailing \n
- cpio_file = cfile.lstrip("./").strip()
+
+ #
+ # Assemble list of files/directories which are not eligible for compression.
+ # Start with the files/dirs in filelist.ramdisk.
+ #
+ # Make sure that relative path start with './', so that exclusion algorithm
+ # below works as expected.
+ #
+ rdfd = open("boot/solaris/filelist.ramdisk", 'r')
+ uc_list = []
+ for filename in rdfd:
+ if not filename.startswith('./'):
+ filename = os.path.join('./', filename)
+ uc_list.append(filename.strip())
+ rdfd.close()
+
+ # Append ./usr/kernel directory
+ uc_list.append("./usr/kernel")
+
+ # Add (regular) files specified in manifest with fiocompress="false"
+ # Verify that they are non-zero-length, regular files first.
+ manflist = get_manifest_list(MANIFEST_READER_OBJ,
+ BOOT_ARCHIVE_CONTENTS_BASE_INCLUDE_NOCOMPRESS)
+ if manflist:
+ status = 0
+ for nc_file in manflist:
+ if not nc_file.startswith('./'):
+ nc_file = os.path.join('./', nc_file)
+
+ try:
+ stat_out = os.lstat(nc_file)
+ except OSError, err:
+ print >> sys.stderr, (sys.argv[0] +
+ ": Couldn't stat %s to mark as " +
+ "uncompressed in boot_archive: %s") % (
+ nc_file, err.strerror)
+ status = 1
+ continue
+ mode = stat_out.st_mode
+ if (stat.S_ISREG(mode) and not (stat_out.st_size == 0)):
+ uc_list.append(nc_file)
+ else:
+ print >> sys.stderr, (sys.argv[0] + ": " +
+ "Couldn't mark " + nc_file +
+ " as uncompressed in boot_archive: " +
+ "not a non-zero-sized regular file")
+ status = 1
+ if (status != 0):
+ raise Exception, (sys.argv[0] + ": Error building "
+ "list of uncompressed boot_archive files.")
+
+ # Get expanded uncompressed list
+ exp_uc_flist = find(uc_list)
+
+ #
+ # Create set of entries to be compressed by differentiating following sets:
+ # - set describing whole boot archive
+ # - set of entries not eligible for compression
+ #
+ compress_fset = set(ba_flist) - set(exp_uc_flist)
+
+ #
+ # Enumerate through set of entries eligible for compression and compress
+ # those entries which meet all of the following criteria:
+ #
+ # - it is a regular file
+ # - size > 0
+ # - it is NOT a hardlink
+ #
+ for cfile in compress_fset:
+ # strip off the trailing \n
+ cpio_file = cfile.strip()
if os.access(cpio_file, os.F_OK):
- # copy all files over to preserve hard links
- cmd = "echo " + cpio_file + " | " + CPIO + \
- " -pdum " + dst + " 2> /dev/null"
- status = os.system(cmd)
- if (status != 0):
- print >> sys.stderr, (sys.argv[0] + ": cpio " +
- "error copying file " + cpio_file +
- " to boot_archive: " + os.strerror(status >> 8))
- errors = True
-
- # Compress the file if it is a regular file w/ size > 0
stat_out = os.lstat(cpio_file)
mode = stat_out.st_mode
- if (stat.S_ISREG(mode) and not (stat_out.st_size == 0)):
+ if (stat.S_ISREG(mode) and not (stat_out.st_size == 0)
+ and (stat_out.st_nlink < 2)):
cmd = FIOCOMPRESS + " -mc " + cpio_file + \
" " + dst + "/" + cpio_file
status = os.system(cmd)
@@ -120,64 +185,6 @@
raise Exception, (sys.argv[0] + ": Error processing " +
"compressed boot_archive files")
- # Re-copy a couple of files we don't want compressed.
- # Start with the files/dirs in filelist.ramdisk, and append usr/kernel
- rdfd = open("boot/solaris/filelist.ramdisk", 'r')
- uc_list = []
- for filename in rdfd:
- uc_list.append(filename.strip())
- rdfd.close()
- uc_list.append("usr/kernel")
-
- # Get expanded uncompressed filelist
- exp_uc_list = find(uc_list)
-
- # Add (regular) files specified in manifest with fiocompress="false"
- # Verify that they are non-zero-length, regular files first.
- manflist = get_manifest_list(MANIFEST_READER_OBJ,
- BOOT_ARCHIVE_CONTENTS_BASE_INCLUDE_NOCOMPRESS)
- if manflist:
- status = 0
- for nc_file in manflist:
- try:
- stat_out = os.lstat(nc_file)
- except OSError, err:
- print >> sys.stderr, (sys.argv[0] +
- ": Couldn't stat %s to mark as " +
- "uncompressed in boot_archive: %s") % (
- nc_file, err.strerror)
- status = 1
- continue
- mode = stat_out.st_mode
- if (stat.S_ISREG(mode) and
- not (stat_out.st_size == 0)):
- exp_uc_list.append(nc_file)
- else:
- print >> sys.stderr, (sys.argv[0] + ": " +
- "Couldn't mark " + nc_file +
- " as uncompressed in boot_archive: " +
- "not a non-zero-sized regular file")
- status = 1
- if (status != 0):
- raise Exception, (sys.argv[0] + ": Error building "
- "list of uncompressed boot_archive files.")
-
- # List is now built; now copy the files.
- for uc_file in exp_uc_list:
- cpio_file = uc_file.strip()
- cmd = "echo " + cpio_file + " | cpio -pdum " + dst + \
- " 2> /dev/null"
- status = os.system(cmd)
- if (status != 0):
- print >> sys.stderr, (sys.argv[0] +
- ": Error recopying uncompressed file " +
- cpio_file + ": " + os.strerror(status >> 8))
- # Don't skip out on bad status here.
- # Try whole list before bombing out.
-
- if (status != 0):
- raise Exception, (sys.argv[0] +
- ": Error recopying uncompressed files to boot_archive")
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -336,7 +343,9 @@
# Boot archive compression type and level, and padding amount.
BA_COMPR_LEVEL = get_manifest_value(MANIFEST_READER_OBJ,
BOOT_ARCHIVE_COMPRESSION_LEVEL)
-if BA_COMPR_LEVEL is None:
+
+# compression level is not applicable to Sparc platform
+if not IS_SPARC and BA_COMPR_LEVEL is None:
raise Exception, (sys.argv[0] +
": boot archive compression level missing from manifest")
@@ -448,12 +457,19 @@
os.rmdir(BA_LOFI_MNT_PT + "/lost+found")
if IS_SPARC:
- print "Doing compression..."
- try:
- compress(BA_BUILD, BA_LOFI_MNT_PT)
- except Exception:
- release_archive()
- raise
+ if (BA_COMPR_TYPE == "none"):
+ print "Skipping compression..."
+ elif (BA_COMPR_TYPE == "dcfs"):
+ print "Doing compression..."
+ try:
+ compress(BA_BUILD, BA_LOFI_MNT_PT)
+ except Exception:
+ release_archive()
+ raise
+ else:
+ raise Exception, (sys.argv[0] + \
+ ": Unrecognized boot archive " +
+ "compression type: " + BA_COMPR_TYPE)
# Install the boot blocks. This only is done on a sparc image.
CMD = PKG_IMG_MNT_PT + LOFIADM + " " + PKG_IMG_MNT_PT + \