LINUX.ORG.RU

логика работы __generic_file_aio_read ???


0

0

Разбираясь во внутренностях VFS для 2.6.14-ого ядра

дошел до функции (mm/filemap.c:968) __generic_file_aio_read



964 * This is the "read()" routine for all filesystems
965 * that can use the page cache directly.
966 */
967 ssize_t
968 __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
969 unsigned long nr_segs, loff_t *ppos)
970 {
971 struct file *filp = iocb->ki_filp;
972 ssize_t retval;
973 unsigned long seg;
974 size_t count;
975
976 count = 0;
977 for (seg = 0; seg < nr_segs; seg++) {
978 const struct iovec *iv = &iov[seg];
979
980 /*
981 * If any segment has a negative length, or the cumulative
982 * length ever wraps negative then return -EINVAL.
983 */
984 count += iv->iov_len;
985 if (unlikely((ssize_t)(count|iv->iov_len) < 0))
986 return -EINVAL;
987 if (access_ok(VERIFY_WRITE, iv->iov_base, iv->iov_len))
988 continue;
989 if (seg == 0)
990 return -EFAULT;
991 nr_segs = seg;
992 count -= iv->iov_len; /* This segment is no good */
993 break;
994 }
995
996 /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
997 if (filp->f_flags & O_DIRECT) {
998 loff_t pos = *ppos, size;
999 struct address_space *mapping;
1000 struct inode *inode;
1001
1002 mapping = filp->f_mapping;
1003 inode = mapping->host;
1004 retval = 0;
1005 if (!count)
1006 goto out; /* skip atime */
1007 size = i_size_read(inode);
1008 if (pos < size) {
1009 retval = generic_file_direct_IO(READ, iocb,
1010 iov, pos, nr_segs);
1011 if (retval > 0 && !is_sync_kiocb(iocb))
1012 retval = -EIOCBQUEUED;
1013 if (retval > 0)
1014 *ppos = pos + retval;
1015 }
1016 file_accessed(filp);
1017 goto out;
1018 }
1019
1020 retval = 0;
1021 if (count) {
1022 for (seg = 0; seg < nr_segs; seg++) {
1023 read_descriptor_t desc;
1024
1025 desc.written = 0;
1026 desc.arg.buf = iov[seg].iov_base;
1027 desc.count = iov[seg].iov_len;
1028 if (desc.count == 0)
1029 continue;
1030 desc.error = 0;
1031 do_generic_file_read(filp,ppos,&desc,file_read_actor);
1032 retval += desc.written;
1033 if (!retval) {
1034 retval = desc.error;
1035 break;
1036 }
1037 }
1038 }
1039 out:
1040 return retval;
1041 }

Собственно в ней все понятно кроме последнего блока(for) 1022-1037стр

происходит заполнение структуры read_descriptor_t desc 1025-1030стр
и собственно чтение 1031стр
проверка прочитанного 1033

Но почему критерием выхода из цикла является (!retval) ????
ведь это правельно только в случае nr_segs=1.


Допустим обабатывая сиситемный вызов readv(fd,iovec,10) то nr_segs будет равно 10

Поадая в цикл ситуацтя может развится следующим образом
Первая итерация : seg=0
после 1025-1030стр: desc.cout=10 desc.written=0;desc.error=0;retval=0
после 1031-1032стр:desc.cout=0 ;desc.written=10;desc.error=0;retval=10
1033 проверка (!retval) так как retval=10 то продолжить


Вторая итерация : seg=1
после 1025-1030стр: desc.cout=7 desc.written=0;desc.error=0;retval=10
при чтении произошла ошибка на 1031стр
после 1031-1032стр:desc.cout=7 ;desc.written=0;desc.error=(ERRNO);retval=10

По идее теперь надо выходить но

1033 проверка (!retval) так как retval=10 то продолжить

ПОЧЕМУ проверяется не условие (desc.count==0) а условие (!retval)


>  1031 do_generic_file_read(filp,ppos,&desc,file_read_actor);
>  1032 retval += desc.written;
>  1033 if (!retval) {

и откуда вы взяли это? у меня в 2.6.14:

  1030                          desc.error = 0;
  1031                          do_generic_file_read(filp,ppos,&desc,file_read_actor);
  1032                          retval += desc.written;
  1033                          if (desc.error) {
  1034                                  retval = retval ?: desc.error;
  1035                                  break;
  1036                          }

idle ★★★★★
()
Ответ на: комментарий от idle

Да вроде стандартный с www.kernel.org

Да вроде стандартный с www.kernel.org

MD5 66d02cbd723876c6d69846a067875a22 linux-2.6.14.tar.bz2 39172170

mitya@localhost ~ $ gpg --verify /tmp/linux-2.6.14.tar.bz2.sign /usr/src/linux-2.6.14.tar.bz2
gpg: Signature made Fri Oct 28 04:23:26 2005 EEST using DSA key ID 517D0F0E
gpg: Good signature from "Linux Kernel Archives Verification Key <ftpadmin@kernel.org>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.

ia32
() автор топика
Ответ на: комментарий от idle

Если посмотреть историю изменений в дереве Линуса, то этот фикс сделали 2005-10-31. Версия 2.6.14 вышла 28 Oct 2005. Поскольку в ветке 2.6.14.3 я этих изменений не увидел, то скорее всего они есть только в релиз кандидатах 2.6.15.

http://kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=history;h=...

anonymous
()
Ответ на: комментарий от anonymous

Аааааа на 15 дней опоздал :)
Был бы совсем как взрослый
На вопрос "чем вчера занимался?"
небрежно ответил-бы "Да так Баг в ядре закоммитил" :))

ia32
() автор топика
Ответ на: комментарий от idle

> и откуда вы взяли это? у меня в 2.6.14:

прошу прощения у всех за дезинформацию, таки я
сумел перепутать у себя каталоги 6.14/ и BK/ :)

действительно, в 6.14/ еще не исправленo.

я не нарочно! :))

idle ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.