emaste updated this revision to Diff 6543.
emaste added a comment.
This revision now requires review to proceed.

- give full path to file with comment explaining the deadlock avoidance
- avoid confusing page mask manipulation and just touch the last byte explicitly


CHANGES SINCE LAST UPDATE
  https://reviews.freebsd.org/D2933?vs=6524&id=6543

REVISION DETAIL
  https://reviews.freebsd.org/D2933

AFFECTED FILES
  usr.bin/ar/write.c

CHANGE DETAILS
  diff --git a/usr.bin/ar/write.c b/usr.bin/ar/write.c
  --- a/usr.bin/ar/write.c
  +++ b/usr.bin/ar/write.c
  @@ -41,6 +41,7 @@
   #include <stdlib.h>
   #include <string.h>
   #include <sysexits.h>
  +#include <unistd.h>
   
   #include "ar.h"
   
  @@ -61,6 +62,7 @@
   static void  free_obj(struct bsdar *bsdar, struct ar_obj *obj);
   static void  insert_obj(struct bsdar *bsdar, struct ar_obj *obj,
                    struct ar_obj *pos);
  +static void  prefault_buffer(const char *buf, size_t s);
   static void  read_objs(struct bsdar *bsdar, const char *archive,
                    int checkargv);
   static void  write_archive(struct bsdar *bsdar, char mode);
  @@ -551,11 +553,35 @@
   }
   
   /*
  + * Fault in the buffer prior to writing as a workaround for poor performance
  + * due to interaction with kernel fs deadlock avoidance code. See the comment
  + * above vn_io_fault_doio() in sys/kern/vfs_vnops.c for details of the issue.
  + */
  +static void
  +prefault_buffer(const char *buf, size_t s)
  +{
  +     volatile const char *p;
  +     size_t page_size;
  +
  +     if (s == 0)
  +             return;
  +     page_size = sysconf(_SC_PAGESIZE);
  +     for (p = buf; p < buf + s; p += page_size)
  +             *p;
  +     /*
  +      * Ensure we touch the last page as well, in case the buffer is not
  +      * page-aligned.
  +      */
  +     *(volatile const char *)(buf + s - 1);
  +}
  +
  +/*
    * Wrapper for archive_write_data().
    */
   static void
   write_data(struct bsdar *bsdar, struct archive *a, const void *buf, size_t s)
   {
  +     prefault_buffer(buf, s);
        if (archive_write_data(a, buf, s) != (ssize_t)s)
                bsdar_errc(bsdar, EX_SOFTWARE, 0, "%s",
                    archive_error_string(a));

EMAIL PREFERENCES
  https://reviews.freebsd.org/settings/panel/emailpreferences/

To: emaste, kib, eadler
Cc: kib, freebsd-toolchain-list, dim, davide
diff --git a/usr.bin/ar/write.c b/usr.bin/ar/write.c
--- a/usr.bin/ar/write.c
+++ b/usr.bin/ar/write.c
@@ -41,6 +41,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sysexits.h>
+#include <unistd.h>
 
 #include "ar.h"
 
@@ -61,6 +62,7 @@
 static void	free_obj(struct bsdar *bsdar, struct ar_obj *obj);
 static void	insert_obj(struct bsdar *bsdar, struct ar_obj *obj,
 		    struct ar_obj *pos);
+static void	prefault_buffer(const char *buf, size_t s);
 static void	read_objs(struct bsdar *bsdar, const char *archive,
 		    int checkargv);
 static void	write_archive(struct bsdar *bsdar, char mode);
@@ -551,11 +553,35 @@
 }
 
 /*
+ * Fault in the buffer prior to writing as a workaround for poor performance
+ * due to interaction with kernel fs deadlock avoidance code. See the comment
+ * above vn_io_fault_doio() in sys/kern/vfs_vnops.c for details of the issue.
+ */
+static void
+prefault_buffer(const char *buf, size_t s)
+{
+	volatile const char *p;
+	size_t page_size;
+
+	if (s == 0)
+		return;
+	page_size = sysconf(_SC_PAGESIZE);
+	for (p = buf; p < buf + s; p += page_size)
+		*p;
+	/*
+	 * Ensure we touch the last page as well, in case the buffer is not
+	 * page-aligned.
+	 */
+	*(volatile const char *)(buf + s - 1);
+}
+
+/*
  * Wrapper for archive_write_data().
  */
 static void
 write_data(struct bsdar *bsdar, struct archive *a, const void *buf, size_t s)
 {
+	prefault_buffer(buf, s);
 	if (archive_write_data(a, buf, s) != (ssize_t)s)
 		bsdar_errc(bsdar, EX_SOFTWARE, 0, "%s",
 		    archive_error_string(a));

_______________________________________________
freebsd-toolchain@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-toolchain
To unsubscribe, send any mail to "freebsd-toolchain-unsubscr...@freebsd.org"

Reply via email to