|
|
ca483c |
Partial backport of the sendfile removal. This backport only
|
|
|
ca483c |
updates nscd/netgroupcache.c, to avoid future conflicts.
|
|
|
ca483c |
|
|
|
ca483c |
commit 8c78faa9ef5c6cae455739f162e4b9d690e32eca
|
|
|
ca483c |
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
|
|
ca483c |
Date: Wed May 16 10:51:15 2018 -0300
|
|
|
ca483c |
|
|
|
ca483c |
Fix concurrent changes on nscd aware files (BZ #23178)
|
|
|
ca483c |
|
|
|
ca483c |
As indicated by BZ#23178, concurrent access on some files read by nscd
|
|
|
ca483c |
may result non expected data send through service requisition. This is
|
|
|
ca483c |
due 'sendfile' Linux implementation where for sockets with zero-copy
|
|
|
ca483c |
support, callers must ensure the transferred portions of the the file
|
|
|
ca483c |
reffered by input file descriptor remain unmodified until the reader
|
|
|
ca483c |
on the other end of socket has consumed the transferred data.
|
|
|
ca483c |
|
|
|
ca483c |
I could not find any explicit documentation stating this behaviour on
|
|
|
ca483c |
Linux kernel documentation. However man-pages sendfile entry [1] states
|
|
|
ca483c |
in NOTES the aforementioned remark. It was initially pushed on man-pages
|
|
|
ca483c |
with an explicit testcase [2] that shows changing the file used in
|
|
|
ca483c |
'sendfile' call prior the socket input data consumption results in
|
|
|
ca483c |
previous data being lost.
|
|
|
ca483c |
|
|
|
ca483c |
From commit message it stated on tested Linux version (3.15) only TCP
|
|
|
ca483c |
socket showed this issues, however on recent kernels (4.4) I noticed the
|
|
|
ca483c |
same behaviour for local sockets as well.
|
|
|
ca483c |
|
|
|
ca483c |
Since sendfile on HURD is a read/write operation and the underlying
|
|
|
ca483c |
issue on Linux, the straightforward fix is just remove sendfile use
|
|
|
ca483c |
altogether. I am really skeptical it is hitting some hotstop (there
|
|
|
ca483c |
are indication over internet that sendfile is helpfull only for large
|
|
|
ca483c |
files, more than 10kb) here to justify that extra code complexity or
|
|
|
ca483c |
to pursuit other possible fix (through memory or file locks for
|
|
|
ca483c |
instance, which I am not sure it is doable).
|
|
|
ca483c |
|
|
|
ca483c |
Checked on x86_64-linux-gnu.
|
|
|
ca483c |
|
|
|
ca483c |
[BZ #23178]
|
|
|
ca483c |
* nscd/nscd-client.h (sendfileall): Remove prototype.
|
|
|
ca483c |
* nscd/connections.c [HAVE_SENDFILE] (sendfileall): Remove function.
|
|
|
ca483c |
(handle_request): Use writeall instead of sendfileall.
|
|
|
ca483c |
* nscd/aicache.c (addhstaiX): Likewise.
|
|
|
ca483c |
* nscd/grpcache.c (cache_addgr): Likewise.
|
|
|
ca483c |
* nscd/hstcache.c (cache_addhst): Likewise.
|
|
|
ca483c |
* nscd/initgrcache.c (addinitgroupsX): Likewise.
|
|
|
ca483c |
* nscd/netgroupcache.c (addgetnetgrentX, addinnetgrX): Likewise.
|
|
|
ca483c |
* nscd/pwdcache.c (cache_addpw): Likewise.
|
|
|
ca483c |
* nscd/servicescache.c (cache_addserv): Likewise.
|
|
|
ca483c |
* sysdeps/unix/sysv/linux/Makefile [$(subdir) == nscd]
|
|
|
ca483c |
(sysdep-CFLAGS): Remove -DHAVE_SENDFILE.
|
|
|
ca483c |
* sysdeps/unix/sysv/linux/kernel-features.h (__ASSUME_SENDFILE):
|
|
|
ca483c |
Remove define.
|
|
|
ca483c |
|
|
|
ca483c |
[1] http://man7.org/linux/man-pages/man2/sendfile.2.html
|
|
|
ca483c |
[2] https://github.com/mkerrisk/man-pages/commit/7b6a3299776b5c1c4f169a591434a855d50c68b4#diff-efd6af3a70f0f07c578e85b51e83b3c3
|
|
|
ca483c |
|
|
|
ca483c |
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
|
|
ca483c |
index 4fce79283a9badb3..7ee0c284ed58d1e3 100644
|
|
|
ca483c |
--- a/nscd/netgroupcache.c
|
|
|
ca483c |
+++ b/nscd/netgroupcache.c
|
|
|
ca483c |
@@ -415,33 +415,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
|
ca483c |
since while inserting this thread might block and so would
|
|
|
ca483c |
unnecessarily let the receiver wait. */
|
|
|
ca483c |
writeout:
|
|
|
ca483c |
-#ifdef HAVE_SENDFILE
|
|
|
ca483c |
- if (__builtin_expect (db->mmap_used, 1) && cacheable)
|
|
|
ca483c |
- {
|
|
|
ca483c |
- assert (db->wr_fd != -1);
|
|
|
ca483c |
- assert ((char *) &dataset->resp > (char *) db->data);
|
|
|
ca483c |
- assert ((char *) dataset - (char *) db->head + total
|
|
|
ca483c |
- <= (sizeof (struct database_pers_head)
|
|
|
ca483c |
- + db->head->module * sizeof (ref_t)
|
|
|
ca483c |
- + db->head->data_size));
|
|
|
ca483c |
-# ifndef __ASSUME_SENDFILE
|
|
|
ca483c |
- ssize_t written =
|
|
|
ca483c |
-# endif
|
|
|
ca483c |
- sendfileall (fd, db->wr_fd, (char *) &dataset->resp
|
|
|
ca483c |
- - (char *) db->head, dataset->head.recsize);
|
|
|
ca483c |
-# ifndef __ASSUME_SENDFILE
|
|
|
ca483c |
- if (written == -1 && errno == ENOSYS)
|
|
|
ca483c |
- goto use_write;
|
|
|
ca483c |
-# endif
|
|
|
ca483c |
- }
|
|
|
ca483c |
- else
|
|
|
ca483c |
-#endif
|
|
|
ca483c |
- {
|
|
|
ca483c |
-#if defined HAVE_SENDFILE && !defined __ASSUME_SENDFILE
|
|
|
ca483c |
- use_write:
|
|
|
ca483c |
-#endif
|
|
|
ca483c |
- writeall (fd, &dataset->resp, dataset->head.recsize);
|
|
|
ca483c |
- }
|
|
|
ca483c |
+ writeall (fd, &dataset->resp, dataset->head.recsize);
|
|
|
ca483c |
}
|
|
|
ca483c |
|
|
|
ca483c |
if (cacheable)
|
|
|
ca483c |
@@ -596,36 +570,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
|
|
ca483c |
/* We write the dataset before inserting it to the database
|
|
|
ca483c |
since while inserting this thread might block and so would
|
|
|
ca483c |
unnecessarily let the receiver wait. */
|
|
|
ca483c |
- assert (fd != -1);
|
|
|
ca483c |
+ assert (fd != -1);
|
|
|
ca483c |
|
|
|
ca483c |
-#ifdef HAVE_SENDFILE
|
|
|
ca483c |
- if (__builtin_expect (db->mmap_used, 1) && cacheable)
|
|
|
ca483c |
- {
|
|
|
ca483c |
- assert (db->wr_fd != -1);
|
|
|
ca483c |
- assert ((char *) &dataset->resp > (char *) db->data);
|
|
|
ca483c |
- assert ((char *) dataset - (char *) db->head + sizeof (*dataset)
|
|
|
ca483c |
- <= (sizeof (struct database_pers_head)
|
|
|
ca483c |
- + db->head->module * sizeof (ref_t)
|
|
|
ca483c |
- + db->head->data_size));
|
|
|
ca483c |
-# ifndef __ASSUME_SENDFILE
|
|
|
ca483c |
- ssize_t written =
|
|
|
ca483c |
-# endif
|
|
|
ca483c |
- sendfileall (fd, db->wr_fd,
|
|
|
ca483c |
- (char *) &dataset->resp - (char *) db->head,
|
|
|
ca483c |
- sizeof (innetgroup_response_header));
|
|
|
ca483c |
-# ifndef __ASSUME_SENDFILE
|
|
|
ca483c |
- if (written == -1 && errno == ENOSYS)
|
|
|
ca483c |
- goto use_write;
|
|
|
ca483c |
-# endif
|
|
|
ca483c |
- }
|
|
|
ca483c |
- else
|
|
|
ca483c |
-#endif
|
|
|
ca483c |
- {
|
|
|
ca483c |
-#if defined HAVE_SENDFILE && !defined __ASSUME_SENDFILE
|
|
|
ca483c |
- use_write:
|
|
|
ca483c |
-#endif
|
|
|
ca483c |
- writeall (fd, &dataset->resp, sizeof (innetgroup_response_header));
|
|
|
ca483c |
- }
|
|
|
ca483c |
+ writeall (fd, &dataset->resp, sizeof (innetgroup_response_header));
|
|
|
ca483c |
}
|
|
|
ca483c |
|
|
|
ca483c |
if (cacheable)
|