Source-Changes-HG archive

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

[src/trunk]: src/bin/cp Re-enable support for reading files of at most 8MB vi...



details:   https://anonhg.NetBSD.org/src/rev/9f7bf3a227b7
branches:  trunk
changeset: 758193:9f7bf3a227b7
user:      tron <tron%NetBSD.org@localhost>
date:      Mon Oct 25 08:19:47 2010 +0000

description:
Re-enable support for reading files of at most 8MB via mmap(2).
Write out the mmap-ed data in small chunks to avoid locking the output
file for a long time.

Suggested by David Holland on "source-changes-d" mailing list.

diffstat:

 bin/cp/utils.c |  69 +++++++++++++++++++++++++++++++++------------------------
 1 files changed, 40 insertions(+), 29 deletions(-)

diffs (135 lines):

diff -r ff2dc5455932 -r 9f7bf3a227b7 bin/cp/utils.c
--- a/bin/cp/utils.c    Mon Oct 25 07:48:03 2010 +0000
+++ b/bin/cp/utils.c    Mon Oct 25 08:19:47 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: utils.c,v 1.35 2010/10/22 17:56:06 pooka Exp $ */
+/* $NetBSD: utils.c,v 1.36 2010/10/25 08:19:47 tron Exp $ */
 
 /*-
  * Copyright (c) 1991, 1993, 1994
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)utils.c    8.3 (Berkeley) 4/1/94";
 #else
-__RCSID("$NetBSD: utils.c,v 1.35 2010/10/22 17:56:06 pooka Exp $");
+__RCSID("$NetBSD: utils.c,v 1.36 2010/10/25 08:19:47 tron Exp $");
 #endif
 #endif /* not lint */
 
@@ -47,6 +47,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <fts.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -54,6 +55,9 @@
 
 #include "extern.h"
 
+#define        MMAP_MAX_SIZE   (8 * 1048576)
+#define        MMAP_MAX_WRITE  (64 * 1024)
+
 int
 set_utimes(const char *file, struct stat *fs)
 {
@@ -75,6 +79,7 @@
        static char buf[MAXBSIZE];
        struct stat to_stat, *fs;
        int ch, checkch, from_fd, rcount, rval, to_fd, tolnk, wcount;
+       char *p;
        
        if ((from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
                warn("%s", entp->fts_path);
@@ -145,47 +150,55 @@
         */
 
        if (fs->st_size > 0) {
-
-       /*
-        * Disable use of mmap.  With the current vnode locking
-        * scheme it has a very annoying property: if the source
-        * media is slow (like a slow network), the target file
-        * will be locked for the duration of the entire max 8MB
-        * write and cause processes attempting to e.g. stat() it
-        * to "tstile".  Revisit when vnode locking gets a little
-        * smarter.
-        */
-#ifdef VNODE_LOCKING_IS_SMARTER_NOW
                /*
                 * Mmap and write if less than 8M (the limit is so
                 * we don't totally trash memory on big files).
                 * This is really a minor hack, but it wins some CPU back.
                 */
+               bool use_read;
 
-               if (fs->st_size <= 8 * 1048576) {
+               use_read = true;
+               if (fs->st_size <= MMAP_MAX_SIZE) {
                        size_t fsize = (size_t)fs->st_size;
-                       char *p;
-
                        p = mmap(NULL, fsize, PROT_READ, MAP_FILE|MAP_SHARED,
                            from_fd, (off_t)0);
-                       if (p == MAP_FAILED) {
-                               goto mmap_failed;
-                       } else {
+                       if (p != MAP_FAILED) {
+                               size_t remainder;
+
+                               use_read = false;
+
                                (void) madvise(p, (size_t)fs->st_size,
                                     MADV_SEQUENTIAL);
-                               if (write(to_fd, p, fsize) !=
-                                   fs->st_size) {
-                                       warn("%s", to.p_path);
-                                       rval = 1;
-                               }
+
+                               /*
+                                * Write out the data in small chunks to
+                                * avoid locking the output file for a
+                                * long time if the reading the data from
+                                * the source is slow.
+                                */
+                               remainder = fsize;
+                               do {
+                                       ssize_t chunk;
+
+                                       chunk = (remainder > MMAP_MAX_WRITE) ?
+                                           MMAP_MAX_WRITE : remainder;
+                                       if (write(to_fd, &p[fsize - remainder],
+                                           chunk) != chunk) {
+                                               warn("%s", to.p_path);
+                                               rval = 1;
+                                               break;
+                                       }
+                                       remainder -= chunk;
+                               } while (remainder > 0);
+
                                if (munmap(p, fsize) < 0) {
                                        warn("%s", entp->fts_path);
                                        rval = 1;
                                }
                        }
-               } else {
-mmap_failed:
-#endif
+               }
+
+               if (use_read) {
                        while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
                                wcount = write(to_fd, buf, (size_t)rcount);
                                if (rcount != wcount || wcount == -1) {
@@ -198,9 +211,7 @@
                                warn("%s", entp->fts_path);
                                rval = 1;
                        }
-#ifdef VNODE_LOCKING_IS_SMARTER_NOW
                }
-#endif
        }
 
        if (rval == 1) {



Home | Main Index | Thread Index | Old Index