Со ссылкой на: Является ли rename() атомарным?
Я спрашиваю что-то похожее, но не совсем то же самое, потому что я хочу знать, безопасно ли полагаться на атомарность rename()
при использовании NFS?
Вот сценарий, с которым я имею дело: у меня есть «индексный» файл, который всегда должен присутствовать.
So:
- Клиент создает новый файл
- Клиент переименовывает новый файл поверх «старого» индексного файла.
Отдельный клиент:
- Читает индексный файл
- относится к структуре диска на основе индекса.
Это предполагает, что rename()
является атомарным, что означает, что всегда будет «индексный» файл (хотя это может быть устаревшая версия из-за кэширования и синхронизации)
Однако проблема, с которой я столкнулся, заключается в том, что это происходит в NFS и работает, но некоторые из моих клиентов NFS иногда сообщают «ENOENT» — такого файла или каталога нет. (например, при сотнях операций, происходящих с интервалом в 5 м, мы получаем эту ошибку каждые пару дней).
Итак, я надеюсь, что кто-нибудь может просветить меня - действительно ли невозможно получить «ENOENT» в этом сценарии?
Причина, по которой я спрашиваю, заключается в этой записи в RFC 3530:
Операция RENAME должна быть атомарной для клиента.
Мне интересно, означает ли это, что просто клиент выдает переименование, а не клиент, просматривающий каталог? (Я согласен с кешированной/устаревшей структурой каталогов, но смысл этой операции в том, что этот файл всегда будет «присутствовать» в той или иной форме)
Последовательность операций (от клиента, выполняющего операцию записи):
21401 14:58:11 open("fleeg.ext", O_RDWR|O_CREAT|O_EXCL, 0666) = -1 EEXIST (File exists) <0.000443>
21401 14:58:11 open("fleeg.ext", O_RDWR) = 3 <0.000547>
21401 14:58:11 fstat(3, {st_mode=S_IFREG|0600, st_size=572, ...}) = 0 <0.000012>
21401 14:58:11 fadvise64(3, 0, 572, POSIX_FADV_RANDOM) = 0 <0.000008>
21401 14:58:11 fcntl(3, F_SETLKW, {type=F_WRLCK, whence=SEEK_SET, start=1, len=1}) = 0 <0.001994>
21401 14:58:11 open("fleeg.ext.i", O_RDWR|O_CREAT, 0666) = 4 <0.000538>
21401 14:58:11 fstat(4, {st_mode=S_IFREG|0600, st_size=42, ...}) = 0 <0.000008>
21401 14:58:11 fadvise64(4, 0, 42, POSIX_FADV_RANDOM) = 0 <0.000006>
21401 14:58:11 close(4) = 0 <0.000011>
21401 14:58:11 fstat(3, {st_mode=S_IFREG|0600, st_size=572, ...}) = 0 <0.000007>
21401 14:58:11 open("fleeg.ext.i", O_RDONLY) = 4 <0.000577>
21401 14:58:11 fstat(4, {st_mode=S_IFREG|0600, st_size=42, ...}) = 0 <0.000007>
21401 14:58:11 fadvise64(4, 0, 42, POSIX_FADV_RANDOM) = 0 <0.000006>
21401 14:58:11 fstat(4, {st_mode=S_IFREG|0600, st_size=42, ...}) = 0 <0.000007>
21401 14:58:11 fstat(4, {st_mode=S_IFREG|0600, st_size=42, ...}) = 0 <0.000007>
21401 14:58:11 read(4, "\3PAX\1\0\0O}\270\370\206\20\225\24\22\t\2\0\203RD\0\0\0\0\17\r\0\2\0\n"..., 42) = 42 <0.000552>
21401 14:58:11 close(4) = 0 <0.000013>
21401 14:58:11 fcntl(3, F_SETLKW, {type=F_RDLCK, whence=SEEK_SET, start=466, len=68}) = 0 <0.001418>
21401 14:58:11 pread(3, "\21@\203\244I\240\333\272\252d\316\261\3770\361#\222\200\313\224&J\253\5\354\217-\256LA\345\253"..., 38, 534) = 38 <0.000010>
21401 14:58:11 pread(3, "\21@\203\244I\240\333\272\252d\316\261\3770\361#\222\200\313\224&J\253\5\354\217-\256LA\345\253"..., 38, 534) = 38 <0.000010>
21401 14:58:11 pread(3, "\21\"\30\361\241\223\271\256\317\302\363\262F\276]\260\241-x\227b\377\205\356\252\236\211\37\17.\216\364"..., 68, 466) = 68 <0.000010>
21401 14:58:11 pread(3, "\21\302d\344\327O\207C]M\10xxM\377\2340\0319\206k\201N\372\332\265R\242\313S\24H"..., 62, 300) = 62 <0.000011>
21401 14:58:11 pread(3, "\21\362cv'\37\204]\377q\362N\302/\212\255\255\370\200\236\350\2237>7i`\346\271Cy\370"..., 104, 362) = 104 <0.000010>
21401 14:58:11 pwrite(3, "\21\302\3174\252\273.\17\v\247\313\324\267C\222P\303\n~\341F\24oh/\300a\315\n\321\31\256"..., 127, 572) = 127 <0.000012>
21401 14:58:11 pwrite(3, "\21\212Q\325\371\223\235\256\245\247\\WT$\4\227\375[\\\3263\222\0305\0\34\2049A;2U"..., 68, 699) = 68 <0.000009>
21401 14:58:11 pwrite(3, "\21\262\20Kc(!.\350\367i\253hkl~\254\335H\250.d\0036\r\342\v\242\7\255\214\31"..., 38, 767) = 38 <0.000009>
21401 14:58:11 fsync(3) = 0 <0.001007>
21401 14:58:11 fstat(3, {st_mode=S_IFREG|0600, st_size=805, ...}) = 0 <0.000009>
21401 14:58:11 open("fleeg.ext.i.tmp", O_RDWR|O_CREAT|O_TRUNC, 0666) = 4 <0.001813>
21401 14:58:11 fstat(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0 <0.000007>
21401 14:58:11 fadvise64(4, 0, 0, POSIX_FADV_RANDOM) = 0 <0.000007>
21401 14:58:11 write(4, "\3PAX\1\0\0qT2\225\226\20\225\24\22\t\2\0\205;D\0\0\0\0\17\r\0\2\0\n"..., 42) = 42 <0.000012>
21401 14:58:11 stat("fleeg.ext.i", {st_mode=S_IFREG|0600, st_size=42, ...}) = 0 <0.000011>
21401 14:58:11 fchmod(4, 0100600) = 0 <0.002517>
21401 14:58:11 fstat(4, {st_mode=S_IFREG|0600, st_size=42, ...}) = 0 <0.000008>
21401 14:58:11 close(4) = 0 <0.000011>
21401 14:58:11 rename("fleeg.ext.i.tmp", "fleeg.pax.i") = 0 <0.001201>
21401 14:58:11 close(3) = 0 <0.000795>
21401 14:58:11 munmap(0x7f1475cce000, 4198400) = 0 <0.000177>
21401 14:58:11 munmap(0x7f14760cf000, 4198400) = 0 <0.000173>
21401 14:58:11 futex(0x7f147cbcb908, FUTEX_WAKE_PRIVATE, 2147483647) = 0 <0.000010>
21401 14:58:11 exit_group(0) = ?
21401 14:58:11 +++ exited with 0 +++
NB - Пути и файлы переименованы выше для согласованности. fleeg.ext
— это файл данных, а fleeg.ext.i
— индекс. Во время этого процесса - файл fleeg.ext.i
перезаписывается (файлом .tmp
), поэтому считается, что по этому пути всегда должен быть файл (либо старый, либо новый, который просто перезаписал его).
На клиенте reading PCAP выглядит так: LOOKUP
Ошибка вызова NFS:
124 1.375777 10.10.41.35 -> 10.10.41.9 NFS 226 LOOKUP fleeg.ext.i V3 LOOKUP Call, DH: 0x6fbbff3a/fleeg.ext.i
125 1.375951 10.10.41.9 -> 10.10.41.35 NFS 186 5347 LOOKUP 0775 Directory V3 LOOKUP Reply (Call In 124) Error: NFS3ERR_NOENT
126 1.375975 10.10.41.35 -> 10.10.41.9 NFS 226 LOOKUP fleeg.ext.i V3 LOOKUP Call, DH: 0x6fbbff3a/fleeg.ext.i
127 1.376142 10.10.41.9 -> 10.10.41.35 NFS 186 5347 LOOKUP 0775 Directory V3 LOOKUP Reply (Call In 126) Error: NFS3ERR_NOENT
strace
, кажется, что это не так - «новый» файл создается вызовомopen
, а затемrename
ed во время открытия. Я проведу еще одну трассировку для подтверждения. - person Sobrique   schedule 30.12.2016ENOENT
, этоopen
илиread
? - person Maxim Egorushkin   schedule 30.12.2016open
- хотя я менее уверен, так как у меня нет следов сбоя (это происходит недостаточно часто, чтобы я мог его поймать), просто ведение журнала уровня приложения. - person Sobrique   schedule 30.12.2016