From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Date: Fri, 12 Jul 2019 17:48:07 +0300 (MSK) From: Ivan Zakharyaschev To: devel@lists.altlinux.org, community@lists.altlinux.org In-Reply-To: Message-ID: References: User-Agent: Alpine 2.20 (LFD 67 2015-01-07) MIME-Version: 1.0 Content-Type: multipart/mixed; BOUNDARY="1807885841-1278164854-1562942887=:15309" Cc: sotor@altlinux.org Subject: Re: [devel] I: rpm in p8 had problems reading *.rpm files X-BeenThere: devel@lists.altlinux.org X-Mailman-Version: 2.1.12 Precedence: list Reply-To: ALT Linux Team development discussions List-Id: ALT Linux Team development discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 Jul 2019 14:48:08 -0000 Archived-At: List-Archive: List-Post: This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. --1807885841-1278164854-1562942887=:15309 Content-Type: text/plain; charset=KOI8-R Content-Transfer-Encoding: 8BIT On Thu, 11 Jul 2019, Ivan Zakharyaschev wrote: > Из отдела тестирования сообщили, что в Workstation 8.2 i586 наблюдаются > проблемы при чтении пакетов из репозитория p8, смонтированного по NFS. > > # /usr/lib/rpm/rpmq -q -i --list --verbose --package -q --qf "[* %{CHANGELOGNAME}\n %{CHANGELOGTEXT}\n]" /mnt/repo-nhcR/pub/distributions/ALTLinux/p8/branch/files/i586/RPMS/sssd-ad-1.16.4-alt1.M80P.1.i586.rpm > ошибка: ошибка запроса /mnt/repo-nhcR/pub/distributions/ALTLinux/p8/branch/files/i586/RPMS/sssd-ad-1.16.4-alt1.M80P.1.i586.rpm > > С обновлённым rpm-4.0.4-alt101.M80P.5.5 такой проблемы нет. > > Я примерно понял, какой код там выполняется, а какой с обновлённым rpm, > когда ошибки нет. (Они идут разным путём.) Вчера я понял более точно. > Когда ошибка случается, вывод strace -fy -s1000 перед этим такой: > > open("/mnt/repo-nhcR/pub/distributions/ALTLinux/p8/branch/files/i586/RPMS/sssd-ad-1.16.4-alt1.M80P.1.i586.rpm", > O_RDONLY) = > 3 > fcntl64(3, > F_SETFD, FD_CLOEXEC) = 0 > gettimeofday({tv_sec=1562834023, tv_usec=224425}, NULL) = 0 > fstat64(3, > {st_mode=S_IFREG|0644, st_size=122129, ...}) = 0 > _newselect(4, > [3], > NULL, NULL, {tv_sec=1, tv_usec=0}) = 1 (in [3], left {tv_sec=0, > tv_usec=999999}) > gettimeofday({tv_sec=1562834023, tv_usec=224634}, NULL) = 0 > read(3, > "\355\253\356\333\3\0\0\0\0\1sssd-ad-1.16.4-alt1.M80P.1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", > 96) = 96 > gettimeofday({tv_sec=1562834023, tv_usec=224766}, NULL) = 0 > _newselect(4, > [3], > NULL, NULL, {tv_sec=1, tv_usec=0}) = 1 (in [3], left {tv_sec=0, > tv_usec=999999}) > gettimeofday({tv_sec=1562834023, tv_usec=224870}, NULL) = 0 > read(3, > "\216\255\350\1\0\0\0\0\0\0\0\5\0\0\0\230", 16) = 16 > gettimeofday({tv_sec=1562834023, tv_usec=224953}, NULL) = 0 > _newselect(4, > [3], > NULL, NULL, {tv_sec=1, tv_usec=0}) = 1 (in [3], left {tv_sec=0, > tv_usec=999999}) > gettimeofday({tv_sec=1562834023, tv_usec=225069}, NULL) = 0 > read(3, > "\0\0\0>\0\0\0\7\0\0\0\210\0\0\0\20\0\0\1\r\0\0\0\6\0\0\0\0\0\0\0\1\0\0\3\350\0\0\0\4\0\0\0,\0\0\0\1\0\0\3\354\0\0\0\7\0\0\0000\0\0\0\20\0\0\3\355\0\0\0\7\0\0\0@\0\0\0H7ce3371ed3cb8e8bcea5a341a029ac364173f7ab\0\0\0\0\0\1\333\271\271v\nq\244\1\271&VY\242\257RH\260\220\210F\4\0\21\2\0\6\5\2]\33\225b\0\n\t\20\334\236\225\302#\21\24\263GF\0\237`,L\375\226t\370s\35\206\202\"\265k\364s:\206\v\31\0\240\256VMa\356w*M\352\36\374!Z^J\277\16\356\256?\0\0\0>\0\0\0\7\377\377\377\260\0\0\0\20", > 232) = 232 > gettimeofday({tv_sec=1562834023, tv_usec=225146}, NULL) = 0 > fstat64(3, > {st_mode=S_IFREG|0644, st_size=122129, ...}) = 0 > gettimeofday({tv_sec=1562834023, tv_usec=225226}, NULL) = 0 > close(3) > = 0 > > Когда ошибки нет, аналогичный кусок у меня (правда, на x86_64) такой: > ... > > Обращает на себя внимание наличие при работе старого rpm вызовов > gettimeofday(), а в обновлённом -- просто select(). Это свидетельствует, Просто на x86_64 не делается вызов gettimeofday(), оно реализуется внутри linux-vdso.so.1, так что зря я считал, что разный код в rpm выполняется. > что в обновлённом rpm используется набор функций для работы с файлами > "ufdio", а в старом -- "fdio". Наверное, "fdio" глючный. В любом случае в rpm ufdRead() внутри использует и вызывает fdRead(). Дело не в глючности fdRead(). Дело в том, что на той системе на nfs номер inode свежих пакетов в зеркале стал слишком большим для i586 без Large File Support. (А кое-где в rpm вызывается fstat() и хоть системный вызов нормально отрабатывает, glibc возвращает ошибку, потому что не может поместить номер inode в старую структуру.) Так что коротко вывод такой же: нужно обновить rpm, а обновлённый rpm уже собран с Large File Support. Также вы можете в sources.list поменять временно file: на copy: и тогда rpm не будет обращаться к файлам на nfs. Подробности использования fstat() в rpm в этом случае такие: 1. lib/package.c static rpmRC readPackageHeaders(FD_t fd, /*@null@*/ /*@out@*/ struct rpmlead * leadPtr, /*@null@*/ /*@out@*/ Header * sigs, /*@null@*/ /*@out@*/ Header * hdrPtr) /*@modifies fd, *leadPtr, *sigs, *hdrPtr @*/ { struct stat sb; int readahead_off = 0; /* if fd points to a socket, pipe, etc, sb.st_size is *always* zero */ if (fstat(Fileno(fd), &sb) == 0 && S_ISREG(sb.st_mode)) { if (sb.st_size < sizeof(struct rpmlead)) return 1; /* Typical header size is 4-16K, and default readahead is 128K. * When scanning a large number of packages (with e.g. rpmquery), * readahead might cause negative effects on the buffer cache. */ if (sb.st_size > /* page size */ 4096) if (posix_fadvise(Fileno(fd), 0, 0, POSIX_FADV_RANDOM) == 0) readahead_off = 1; } rpmRC rc = do_readPackageHeaders(fd, leadPtr, sigs, hdrPtr); /* re-enable readahead for cpio */ if (readahead_off) posix_fadvise(Fileno(fd), 0, 0, POSIX_FADV_NORMAL); return rc; } Тут просто в случае ошибки fstat() не будет вызван posix_fadvise(), что некритично. 2. rpmio/rpmio.c static ssize_t ufdRead(void * cookie, /*@out@*/ char * buf, size_t count) /*@globals fileSystem, internalState @*/ /*@modifies *buf, fileSystem, internalState @*/ { FD_t fd = c2f(cookie); int bytesRead; int total; *buf = '\0'; /* LCL: insistent bugger. */ /* XXX preserve timedRead() behavior */ if (fdGetIo(fd) == fdio) { struct stat sb; int fdno = fdFileno(fd); (void) fstat(fdno, &sb); if (S_ISREG(sb.st_mode)) return fdRead(fd, buf, count); } UFDONLY(fd); assert(fd->rd_timeoutsecs >= 0); for (total = 0; total < count; total += bytesRead) { int rc; bytesRead = 0; /* Is there data to read? */ if (fd->bytesRemain == 0) return total; /* XXX simulate EOF */ rc = fdReadable(fd, fd->rd_timeoutsecs); switch (rc) { case -1: /* error */ case 0: /* timeout */ return total; /*@notreached@*/ /*@switchbreak@*/ break; default: /* data to read */ /*@switchbreak@*/ break; } rc = fdRead(fd, buf + total, count - total); Тут, конечно, глючная проверка S_ISREG(sb.st_mode) после того, как (void) fstat(fdno, &sb); завершился с ошибкой. Но фактически это ни на что влияет в этом случае, потому что всё равно вызывается fdRead() на обоих путях. 3. lib/signature.c static inline rpmRC checkSize(FD_t fd, int siglen, int pad, int datalen) /*@globals fileSystem @*/ /*@modifies fileSystem @*/ { struct stat st; int delta; rpmRC rc; if (fstat(Fileno(fd), &st)) return RPMRC_FAIL; if (!S_ISREG(st.st_mode)) { rpmMessage(RPMMESS_DEBUG, _("file is not regular -- skipping size check\n")); return RPMRC_OK; } Вот здесь checkSize() возвращает RPMRC_FAIL и из-за этого rpmq прекращает работу. (Хотя можно было бы пережить так же, как в случае нерегулярного файла.) Особого повода что-либо в этом коде исправлять у нас больше нет, потому что уже включён Large File Support. На практике я не знаю, каие ещё могут быть случаи отказа fstat(), которые мы хотели бы пережить. > Вероятно, выбор в > пользу "ufdio" поменялся в серии патчей Алексея Турбина at@ про Large File > Support. > > Вряд ли пакеты из репозитория как-то плохо сформированы, да этот пример > вроде и не очень большого файла пакета. > > Так что могу посоветовать всем пользователям p8 обновить сначала rpm, > чтобы избегать таких проблем. > > -- > Best regards, > Ivan --1807885841-1278164854-1562942887=:15309--