[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Ubuntu dpkg 1.15.5.6ubuntu4



This e-mail has been sent due to an upload to Ubuntu that contains Ubuntu
changes.  It contains the difference between the new version and the
previous version of the same source package in Ubuntu.
Format: 1.8
Date: Thu, 15 Apr 2010 12:38:50 +0100
Source: dpkg
Binary: dpkg dpkg-dev dselect
Architecture: source
Version: 1.15.5.6ubuntu4
Distribution: lucid
Urgency: low
Maintainer: Ubuntu Core Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Changed-By: Colin Watson <cjwatson@ubuntu.com>
Description: 
 dpkg       - Debian package management system
 dpkg-dev   - Debian package development tools
 dselect    - Debian package management front-end
Closes: 574599 575891
Launchpad-Bugs-Fixed: 540252 559915
Changes: 
 dpkg (1.15.5.6ubuntu4) lucid; urgency=low
 .
   * Backport from upstream:
     - Restore fsync during package unpack (LP: #559915).  This is now done
       by deferring the fsync and rename for normal files in tar extraction
       so that it's done in one pass afterwards, to avoid massive I/O
       degradation due to the serialization from each write + fsync.  When
       creating hard links to normal files on extraction use the .dpkg-new
       filename for source as the file is not yet in place due to the rename
       deferral.
     - Fix dpkg to not lose package metadata on filesystems where readdir()
       returns new files added after the opendir() call, btrfs in particular
       triggered the problematic behaviour. Closes: #575891
     - Report deferred trigger errors on status-fd. Closes: #574599,
       LP: #540252
       Thanks to Michael Vogt <michael.vogt@ubuntu.com>.
Checksums-Sha1: 
 3e2f1933f0961e2f92d384a3d1118e05906c3e71 2001 dpkg_1.15.5.6ubuntu4.dsc
 ac1777c9eacab9e3ef56a5aa195f392dc348bb5a 4702984 dpkg_1.15.5.6ubuntu4.tar.bz2
Checksums-Sha256: 
 1e3a6dafc5b189b001ee38b33234027534dcd58cd72998cc83ac7a58b1874892 2001 dpkg_1.15.5.6ubuntu4.dsc
 15fcc7b756986d9b47f1900c34d7b19f00ddc34874c4f70bc6ba34d90f2ca67d 4702984 dpkg_1.15.5.6ubuntu4.tar.bz2
Files: 
 727c38817d5d2bee7763023f81ec0eef 2001 admin required dpkg_1.15.5.6ubuntu4.dsc
 00acfdd2501c3e971dfa286039f8279b 4702984 admin required dpkg_1.15.5.6ubuntu4.tar.bz2
Original-Maintainer: Dpkg Developers <debian-dpkg@lists.debian.org>
diff -pruN 1.15.5.6ubuntu3/debian/changelog 1.15.5.6ubuntu4/debian/changelog
--- 1.15.5.6ubuntu3/debian/changelog	2010-03-16 10:29:48.000000000 +0000
+++ 1.15.5.6ubuntu4/debian/changelog	2010-04-15 12:38:56.000000000 +0100
@@ -1,3 +1,22 @@
+dpkg (1.15.5.6ubuntu4) lucid; urgency=low
+
+  * Backport from upstream:
+    - Restore fsync during package unpack (LP: #559915).  This is now done
+      by deferring the fsync and rename for normal files in tar extraction
+      so that it's done in one pass afterwards, to avoid massive I/O
+      degradation due to the serialization from each write + fsync.  When
+      creating hard links to normal files on extraction use the .dpkg-new
+      filename for source as the file is not yet in place due to the rename
+      deferral.
+    - Fix dpkg to not lose package metadata on filesystems where readdir()
+      returns new files added after the opendir() call, btrfs in particular
+      triggered the problematic behaviour. Closes: #575891
+    - Report deferred trigger errors on status-fd. Closes: #574599,
+      LP: #540252
+      Thanks to Michael Vogt <michael.vogt@ubuntu.com>.
+
+ -- Colin Watson <cjwatson@ubuntu.com>  Thu, 15 Apr 2010 12:38:50 +0100
+
 dpkg (1.15.5.6ubuntu3) lucid; urgency=low
 
   * Revert fsync during package unpack for now; it's unacceptably slow for
diff -pruN 1.15.5.6ubuntu3/src/archives.c 1.15.5.6ubuntu4/src/archives.c
--- 1.15.5.6ubuntu3/src/archives.c	2010-03-16 10:29:49.000000000 +0000
+++ 1.15.5.6ubuntu4/src/archives.c	2010-04-15 12:38:58.000000000 +0100
@@ -356,6 +356,7 @@ int tarobject(struct TarInfo *ti) {
   static int fd;
   const char *usename;
   struct filenamenode *usenode;
+  struct filenamenode *linknode;
 
   struct conffile *conff;
   struct tarcontext *tc= (struct tarcontext*)ti->UserData;
@@ -654,6 +655,10 @@ int tarobject(struct TarInfo *ti) {
     am=(nifd->namenode->statoverride ? nifd->namenode->statoverride->mode : ti->Mode) & ~S_IFMT;
     if (fchmod(fd,am))
       ohshite(_("error setting permissions of `%.255s'"),ti->Name);
+
+    /* Postpone the fsync, to try to avoid massive I/O degradation. */
+    nifd->namenode->flags |= fnnf_deferred_fsync;
+
     pop_cleanup(ehflag_normaltidy); /* fd= open(fnamenewvb.buf) */
     if (close(fd))
       ohshite(_("error closing/writing `%.255s'"),ti->Name);
@@ -680,7 +685,11 @@ int tarobject(struct TarInfo *ti) {
   case HardLink:
     varbufreset(&hardlinkfn);
     varbufaddstr(&hardlinkfn,instdir); varbufaddc(&hardlinkfn,'/');
-    varbufaddstr(&hardlinkfn,ti->LinkName); varbufaddc(&hardlinkfn,0);
+    varbufaddstr(&hardlinkfn, ti->LinkName);
+    linknode = findnamenode(ti->LinkName, 0);
+    if (linknode->flags & fnnf_deferred_rename)
+      varbufaddstr(&hardlinkfn, DPKGNEWEXT);
+    varbufaddc(&hardlinkfn, '\0');
     if (link(hardlinkfn.buf,fnamenewvb.buf))
       ohshite(_("error creating hard link `%.255s'"),ti->Name);
     debug(dbg_eachfiledetail,"tarobject HardLink");
@@ -789,33 +798,103 @@ int tarobject(struct TarInfo *ti) {
         
 #endif /* WITH_SELINUX */
 
-  if (rename(fnamenewvb.buf,fnamevb.buf))
-    ohshite(_("unable to install new version of `%.255s'"),ti->Name);
+  if (ti->Type == NormalFile0 || ti->Type == NormalFile1) {
+    nifd->namenode->flags |= fnnf_deferred_rename;
 
-  /* CLEANUP: now the new file is in the destination file, and the
-   * old file is in dpkg-tmp to be cleaned up later.  We now need
-   * to take a different attitude to cleanup, because we need to
-   * remove the new file.
-   */
+    debug(dbg_eachfiledetail, "tarobject done and installation deferred");
+  } else {
+    if (rename(fnamenewvb.buf,fnamevb.buf))
+      ohshite(_("unable to install new version of `%.255s'"),ti->Name);
+
+    /* CLEANUP: now the new file is in the destination file, and the
+     * old file is in dpkg-tmp to be cleaned up later.  We now need
+     * to take a different attitude to cleanup, because we need to
+     * remove the new file.
+     */
 
-  nifd->namenode->flags |= fnnf_placed_on_disk;
+    nifd->namenode->flags |= fnnf_placed_on_disk;
 
 #ifdef WITH_SELINUX
-  /*
-   * if selinux is enabled, restore the default security context
-   */
-  if (selinux_enabled > 0)
-    if(setfscreatecon(NULL) < 0)
-      perror("Error restoring default security context:");
+    /*
+     * if selinux is enabled, restore the default security context
+     */
+    if (selinux_enabled > 0)
+      if(setfscreatecon(NULL) < 0)
+        perror("Error restoring default security context:");
 #endif /* WITH_SELINUX */
 
+    nifd->namenode->flags |= fnnf_elide_other_lists;
 
-  nifd->namenode->flags |= fnnf_elide_other_lists;
+    debug(dbg_eachfiledetail,"tarobject done and installed");
+  }
 
-  debug(dbg_eachfiledetail,"tarobject done and installed");
   return 0;
 }
 
+void
+tar_deferred_extract(struct fileinlist *files, struct pkginfo *pkg)
+{
+  struct fileinlist *cfile;
+  struct filenamenode *usenode;
+  const char *usename;
+
+  for (cfile = files; cfile; cfile = cfile->next) {
+    debug(dbg_eachfile, "deferred extract of '%.255s'", cfile->namenode->name);
+
+    if (!(cfile->namenode->flags & fnnf_deferred_rename))
+      continue;
+
+    debug(dbg_eachfiledetail, "deferred extract needs rename");
+
+    usenode = namenodetouse(cfile->namenode, pkg);
+    usename = usenode->name + 1; /* Skip the leading '/'. */
+
+    setupfnamevbs(usename);
+
+    if (cfile->namenode->flags & fnnf_deferred_fsync) {
+      int fd;
+
+      debug(dbg_eachfiledetail, "deferred extract needs fsync");
+
+      fd = open(fnamenewvb.buf, O_WRONLY);
+      if (fd < 0)
+        ohshite(_("unable to open '%.255s'"), fnamenewvb.buf);
+      if (fsync(fd))
+        ohshite(_("unable to sync file '%.255s'"), fnamenewvb.buf);
+      if (close(fd))
+        ohshite(_("error closing/writing `%.255s'"), fnamenewvb.buf);
+
+      cfile->namenode->flags &= ~fnnf_deferred_fsync;
+    }
+
+    if (rename(fnamenewvb.buf, fnamevb.buf))
+      ohshite(_("unable to install new version of `%.255s'"),
+              cfile->namenode->name);
+
+    cfile->namenode->flags &= ~fnnf_deferred_rename;
+
+    /* CLEANUP: now the new file is in the destination file, and the
+     * old file is in dpkg-tmp to be cleaned up later.  We now need
+     * to take a different attitude to cleanup, because we need to
+     * remove the new file. */
+
+    cfile->namenode->flags |= fnnf_placed_on_disk;
+
+#ifdef WITH_SELINUX
+    /*
+     * if selinux is enabled, restore the default security context
+     */
+    if (selinux_enabled > 0)
+      if(setfscreatecon(NULL) < 0)
+        perror("Error restoring default security context:");
+#endif /* WITH_SELINUX */
+
+    cfile->namenode->flags |= fnnf_elide_other_lists;
+
+    debug(dbg_eachfiledetail, "deferred extract done and installed");
+  }
+}
+
 static int
 try_deconfigure_can(bool (*force_p)(struct deppossi *), struct pkginfo *pkg,
                     struct deppossi *pdep, const char *action,
diff -pruN 1.15.5.6ubuntu3/src/archives.h 1.15.5.6ubuntu4/src/archives.h
--- 1.15.5.6ubuntu3/src/archives.h	2010-03-16 10:29:49.000000000 +0000
+++ 1.15.5.6ubuntu4/src/archives.h	2010-04-15 12:38:58.000000000 +0100
@@ -66,6 +66,7 @@ int unlinkorrmdir(const char *filename);
 
 int tarobject(struct TarInfo *ti);
 int tarfileread(void *ud, char *buf, int len);
+void tar_deferred_extract(struct fileinlist *files, struct pkginfo *pkg);
 
 bool filesavespackage(struct fileinlist *, struct pkginfo *,
                       struct pkginfo *pkgbeinginstalled);
diff -pruN 1.15.5.6ubuntu3/src/filesdb.h 1.15.5.6ubuntu4/src/filesdb.h
--- 1.15.5.6ubuntu3/src/filesdb.h	2010-03-16 10:29:49.000000000 +0000
+++ 1.15.5.6ubuntu4/src/filesdb.h	2010-04-15 12:38:58.000000000 +0100
@@ -69,6 +69,8 @@ struct filenamenode {
     fnnf_elide_other_lists=   000010, /* must remove from other packages' lists */
     fnnf_no_atomic_overwrite= 000020, /* >=1 instance is a dir, cannot rename over */
     fnnf_placed_on_disk=      000040, /* new file has been placed on the disk */
+    fnnf_deferred_fsync =     000200,
+    fnnf_deferred_rename =    000400,
   } flags; /* Set to zero when a new node is created. */
   const char *oldhash; /* valid iff this namenode is in the newconffiles list */
   struct stat *filestat;
diff -pruN 1.15.5.6ubuntu3/src/processarc.c 1.15.5.6ubuntu4/src/processarc.c
--- 1.15.5.6ubuntu3/src/processarc.c	2010-03-16 10:29:49.000000000 +0000
+++ 1.15.5.6ubuntu4/src/processarc.c	2010-04-15 12:38:58.000000000 +0100
@@ -49,6 +49,12 @@
 #include "main.h"
 #include "archives.h"
 
+struct rename_list {
+  struct rename_list *next;
+  char *src;
+  char *dst;
+};
+
 static const char *
 summarize_filename(const char *filename)
 {
@@ -116,6 +122,7 @@ void process_archive(const char *filenam
   struct dirent *de;
   struct stat stab, oldfs;
   struct pkg_deconf_list *deconpil, *deconpiltemp;
+  struct rename_list *rename_head = NULL, *rename_node = NULL;
   
   cleanup_pkg_failed= cleanup_conflictor_failed= 0;
   admindirlen= strlen(admindir);
@@ -621,6 +628,8 @@ void process_archive(const char *filenam
   p1[0] = -1;
   subproc_wait_check(c1, BACKEND " --fsys-tarfile", PROCPIPE);
 
+  tar_deferred_extract(newfileslist, pkg);
+
   if (oldversionstatus == stat_halfinstalled || oldversionstatus == stat_unpacked) {
     /* Packages that were in `installed' and `postinstfailed' have been reduced
      * to `unpacked' by now, by the running of the prerm script.
@@ -831,19 +840,37 @@ void process_archive(const char *filenam
     varbufaddstr(&infofnvb,de->d_name);
     varbufaddc(&infofnvb,0);
     strcpy(cidirrest,p);
-    if (!rename(cidir,infofnvb.buf)) {
+    /* We keep files to rename in a list as doing the rename immediately
+     * might influence the current readdir(), the just renamed file might
+     * be returned a second time as it's actually a new file from the
+     * point of view of the filesystem. */
+    rename_node = m_malloc(sizeof(*rename_node));
+    rename_node->next = rename_head;
+    rename_node->src = m_strdup(cidir);
+    rename_node->dst = m_strdup(infofnvb.buf);
+    rename_head = rename_node;
+  }
+  pop_cleanup(ehflag_normaltidy); /* closedir */
+
+  while ((rename_node = rename_head)) {
+    if (!rename(rename_node->src, rename_node->dst)) {
       debug(dbg_scripts, "process_archive info installed %s as %s",
-            cidir, infofnvb.buf);
+            rename_node->src, rename_node->dst);
     } else if (errno == ENOENT) {
       /* Right, no new version. */
-      if (unlink(infofnvb.buf))
-        ohshite(_("unable to remove obsolete info file `%.250s'"),infofnvb.buf);
-      debug(dbg_scripts, "process_archive info unlinked %s",infofnvb.buf);
+      if (unlink(rename_node->dst))
+        ohshite(_("unable to remove obsolete info file `%.250s'"),
+                rename_node->dst);
+      debug(dbg_scripts, "process_archive info unlinked %s", rename_node->dst);
     } else {
-      ohshite(_("unable to install (supposed) new info file `%.250s'"),cidir);
+      ohshite(_("unable to install (supposed) new info file `%.250s'"),
+              rename_node->src);
     }
+    rename_head = rename_node->next;
+    free(rename_node->src);
+    free(rename_node->dst);
+    free(rename_node);
   }
-  pop_cleanup(ehflag_normaltidy); /* closedir */
   
   *cidirrest = '\0'; /* the directory itself */
   dsd= opendir(cidir);
diff -pruN 1.15.5.6ubuntu3/src/trigproc.c 1.15.5.6ubuntu4/src/trigproc.c
--- 1.15.5.6ubuntu3/src/trigproc.c	2010-03-16 10:29:49.000000000 +0000
+++ 1.15.5.6ubuntu4/src/trigproc.c	2010-04-15 12:38:58.000000000 +0100
@@ -103,6 +103,7 @@ trigproc_run_deferred(void)
 {
 	struct pkg_list *node;
 	struct pkginfo *pkg;
+	jmp_buf ejbuf;
 
 	debug(dbg_triggers, "trigproc_run_deferred");
 	while ((node = remove_from_some_queue(&deferred))) {
@@ -110,8 +111,18 @@ trigproc_run_deferred(void)
 		free(node);
 		if (!pkg)
 			continue;
+
+		if (setjmp(ejbuf)) {
+			error_unwind(ehflag_bombout);
+			continue;
+		}
+		push_error_handler(&ejbuf, print_error_perpackage, pkg->name);
+
 		pkg->clientdata->trigprocdeferred = NULL;
 		trigproc(pkg);
+
+		set_error_display(NULL, NULL);
+		error_unwind(ehflag_normaltidy);
 	}
 }
 

Reply to: