.. SPDX-License-Identifier: GPL-2.0+ .. include:: ../disclaimer-zh_CN.rst :Original: Documentation/core-api/errseq.rst :翻译: 周彬彬 Binbin Zhou <zhoubinbin@loongson.cn> :æ ¡è¯‘: å´æƒ³æˆ Wu Xiangcheng <bobwxc@email.cn> ================ errseq_tæ•°æ®ç±»åž‹ ================ ``errseq_t`` 是一ç§åœ¨ä¸€ä¸ªåœ°æ–¹è®°å½•é”™è¯¯çš„方法,并å…许任æ„æ•°é‡çš„ ``订阅者`` 判æ–自上 æ¬¡é‡‡æ ·ç‚¹ä»¥æ¥æ˜¯å¦å‘生了å˜åŒ–。 最åˆçš„用例是跟踪文件åŒæ¥ç³»ç»Ÿè°ƒç”¨ï¼ˆ ``fsync``, ``fdatasync``, ``msync`` å’Œ ``sync_file_range`` )的错误,但它也å¯ä»¥ç”¨äºŽå…¶ä»–情况。 å®ƒè¢«å®žçŽ°ä¸ºä¸€ä¸ªæ— ç¬¦å·çš„32ä½å€¼ã€‚低ä½è¢«æŒ‡å®šä¿å˜é”™è¯¯ä»£ç (在1å’ŒMAX_ERRNOä¹‹é—´ï¼‰ã€‚é«˜ä½ ç”¨ä½œè®¡æ•°å™¨ã€‚è¿™é‡Œæ˜¯ç”¨åŽŸåæ“作而ä¸æ˜¯é”æ¥å®Œæˆçš„ï¼Œå› æ¤å¯ä»¥ä»Žä»»ä½•ä¸Šä¸‹æ–‡ä¸è°ƒç”¨è¿™äº›å‡½æ•°ã€‚ 请注æ„,如果频ç¹è®°å½•æ–°é”™è¯¯ï¼Œåˆ™å˜åœ¨å†²çªé£Žé™©ï¼Œå› 为我们用作计数器的ä½å¾ˆå°‘。 为了缓解这ç§æƒ…况,错误值和计数器之间的ä½è¢«ç”¨ä½œä¸€ä¸ªæ ‡å¿—,以判æ–自记录新值以æ¥æ˜¯å¦ å¯¹è¯¥å€¼è¿›è¡Œäº†é‡‡æ ·ã€‚è¿™ä½¿æˆ‘ä»¬èƒ½å¤Ÿé¿å…在上次记录错误åŽæ²¡æœ‰äººå–æ ·çš„æƒ…å†µä¸‹ç¢°æ’žè®¡æ•°å™¨ã€‚ å› æ¤ï¼Œæˆ‘ä»¬å¾—åˆ°äº†ä¸€ä¸ªç±»ä¼¼è¿™æ ·çš„å€¼ï¼š +--------------------------------------+------+------------------------+ | 31..13 | 12 | 11..0 | +--------------------------------------+------+------------------------+ | 计数器 | æ ‡å¿— | 错误值 | +--------------------------------------+------+------------------------+ 总体æ€è·¯æ˜¯è®© ``观察者`` 对errseq_tå€¼è¿›è¡Œé‡‡æ ·ï¼Œå¹¶å°†å…¶ä¿ç•™ä¸ºè¿è¡Œæ¸¸æ ‡ã€‚该值ç¨åŽå¯ç”¨ 于判æ–è‡ªé‡‡æ ·å®ŒæˆåŽæ˜¯å¦å‘生了任何新错误,并原å地记录检查时的状æ€ã€‚这使得我们能在 一个地方记录错误,然åŽæœ‰è®¸å¤š ``观察者`` å¯ä»¥åˆ¤æ–自上次检查以æ¥è¯¥å€¼æ˜¯å¦å‘生了å˜åŒ–。 æ–°çš„errseq_t应始终清零。全零的errseq_t值是从未出现错误的特殊(但常è§ï¼‰æƒ…å†µã€‚å› æ¤ï¼Œ 如果您希望知é“自首次åˆå§‹åŒ–以æ¥æ˜¯å¦æ›¾ç»æœ‰è¿‡é”™è¯¯é›†ï¼Œåˆ™å…¨é›¶å€¼è¢«ç”¨ä½œ ``纪元`` 。 API的使用方法 ============= è®©æˆ‘ç»™ä½ ä»¬è®²ä¸€ä¸ªå…³äºŽå‘˜å·¥drone的故事。现在,他总体上是个好员工,但公å¸æœ‰ç‚¹...ç®¡ç† ç¹é‡ã€‚他今天必须å‘77å主管汇报,明天 ``大è€æ¿`` è¦ä»Žå¤–地赶æ¥ï¼Œä»–肯定也会考验这个 å¯æ€œçš„家伙。 他们都把工作交给他去åš---多到他都记ä¸ä½è°äº¤ç»™ä»–什么了,但这并ä¸æ˜¯ä»€ä¹ˆå¤§é—®é¢˜ã€‚主管 们åªæƒ³çŸ¥é“他什么时候完æˆä»–们迄今为æ¢äº¤ç»™ä»–的所有工作,以åŠè‡ªä»Žä»–们上次询问以æ¥ä»– 是å¦çŠ¯äº†ä»»ä½•é”™è¯¯ã€‚ ä»–å¯èƒ½åœ¨ä»–ä»¬å®žé™…ä¸Šå¹¶æ²¡æœ‰äº¤ç»™ä»–çš„å·¥ä½œä¸ŠçŠ¯äº†é”™è¯¯ï¼Œä½†ä»–æ— æ³•åœ¨é‚£ä¹ˆè¯¦ç»†çš„å±‚é¢ä¸Šè®°å½•äº‹ 情,他所能记得的åªæ˜¯ä»–最近犯的错误。 下é¢æ˜¯æˆ‘们 ``worker_drone`` 的表达å¼:: struct worker_drone { errseq_t wd_err; /* 用æ¥è®°å½•é”™è¯¯ */ }; æ¯å¤©ï¼Œ ``worker_drone`` éƒ½æ˜¯ä»¥ä¸€å¼ ç™½çº¸å¼€å§‹çš„:: struct worker_drone wd; wd.wd_err = (errseq_t)0; 主管们进æ¥åŽå¯¹å½“天的工作进行åˆæ¥äº†è§£ã€‚他们并ä¸å…³å¿ƒåœ¨ä»–们观察开始之å‰å‘生的任何事 情:: struct supervisor { errseq_t s_wd_err; /* wd_errçš„ç§æœ‰â€œæ¸¸æ ‡â€ */ spinlock_t s_wd_err_lock; /* ä¿æŠ¤s_wd_err */ } struct supervisor su; su.s_wd_err = errseq_sample(&wd.wd_err); spin_lock_init(&su.s_wd_err_lock); 现在他们开始给他布置任务。æ¯éš”å‡ åˆ†é’Ÿï¼Œä»–ä»¬å°±è¦æ±‚他完æˆè¿„今为æ¢äº¤ç»™ä»–的所有工作。 然åŽé—®ä»–是å¦æœ‰çŠ¯ä»»ä½•é”™è¯¯:: spin_lock(&su.su_wd_err_lock); err = errseq_check_and_advance(&wd.wd_err, &su.s_wd_err); spin_unlock(&su.su_wd_err_lock); 到目å‰ä¸ºæ¢ï¼Œå®ƒåªæ˜¯ä¸æ–返回0。 现在,这家公å¸çš„è€æ¿éžå¸¸å啬,给了他ä¸åˆæ ¼çš„设备æ¥å®Œæˆä»–的工作。å¶å°”设备会出现故 障,导致他犯错。他é‡é‡åœ°å¹äº†ä¸€å£æ°”,并把它记录下æ¥:: errseq_set(&wd.wd_err, -EIO); ...然åŽç»§ç»å·¥ä½œã€‚主管们最终会å†æ¬¡æ£€æŸ¥ï¼Œä»–们在下次检查时都会å‘现这个错误。åŽç»çš„è°ƒ 用将返回0,直到记录下å¦ä¸€ä¸ªé”™è¯¯ï¼Œæ¤æ—¶å°†å‘æ¯ä¸ªè°ƒç”¨æŠ¥å‘Šä¸€æ¬¡ã€‚ 请注æ„ï¼Œä¸»ç®¡ä»¬æ— æ³•çŸ¥é“他们犯了多少错误,åªèƒ½çŸ¥é“自上次检查以æ¥æ˜¯å¦çŠ¯äº†ä¸€ä¸ªé”™è¯¯ï¼Œ 以åŠè®°å½•çš„最新值。 å¶å°”,大è€æ¿ä¼šæ¥æŠ½æŸ¥ï¼Œè¦æ±‚员工为他åšä¸€æ¬¡æ€§çš„工作。他并ä¸åƒä¸»ç®¡ä»¬é‚£æ ·å…¨èŒè§‚察员工, 但他确实需è¦çŸ¥é“在他的工作处ç†è¿‡ç¨‹ä¸æ˜¯å¦å‘生了错误。 ä»–åªéœ€å¯¹å‘˜å·¥å½“å‰çš„errseq_tè¿›è¡Œé‡‡æ ·ï¼Œç„¶åŽç”¨å®ƒæ¥åˆ¤æ–åŽæ¥æ˜¯å¦å‘生了错误:: errseq_t since = errseq_sample(&wd.wd_err); /* æ交一些工作,ç‰å¾…å®Œæˆ */ err = errseq_check(&wd.wd_err, since); 由于他åªæ˜¯è¦åœ¨é‚£ä¸ªç‚¹ä¹‹åŽä¸¢å¼ƒ ``since`` ,所以他ä¸éœ€è¦åœ¨è¿™é‡ŒæŽ¨è¿›å®ƒã€‚åŒæ—¶ä»–也ä¸éœ€è¦ 任何é”ï¼Œå› ä¸ºå®ƒä¸èƒ½è¢«å…¶ä»–人使用。 åºåˆ—化更新errseq_tæ¸¸æ ‡ ====================== 请注æ„,errseq_t API在check_and_advance_operation期间ä¸ä¿æŠ¤errseq_tæ¸¸æ ‡ã€‚åªæœ‰å…¸åž‹ 的错误代ç 是被原å化处ç†çš„。在多任务åŒæ—¶ä½¿ç”¨åŒä¸€ä¸ªerrseq_tæ¸¸æ ‡çš„æƒ…å†µä¸‹ï¼Œå¯¹è¯¥æ¸¸æ ‡ 的更新进行åºåˆ—化是很é‡è¦çš„。 如果ä¸è¿™æ ·åšï¼Œé‚£ä¹ˆæ¸¸æ ‡å°±æœ‰å¯èƒ½å‘åŽç§»åŠ¨ã€‚在这ç§æƒ…况下,åŒä¸€ä¸ªé”™è¯¯å¯èƒ½è¢«æŠ¥å‘Šå¤šæ¬¡ã€‚ å› æ¤ï¼Œé€šå¸¸å…ˆæ‰§è¡Œerrseq_check检查是å¦æœ‰ä»»ä½•å˜åŒ–,然åŽåœ¨èŽ·å–é”åŽæ‰æ‰§è¡Œ errseq_check_and_advance。例如:: if (errseq_check(&wd.wd_err, READ_ONCE(su.s_wd_err)) { /* su.s_wd_err被s_wd_err_lockä¿æŠ¤ */ spin_lock(&su.s_wd_err_lock); err = errseq_check_and_advance(&wd.wd_err, &su.s_wd_err); spin_unlock(&su.s_wd_err_lock); } 这就é¿å…了自上次检查以æ¥æ²¡æœ‰ä»»ä½•å˜åŒ–的常è§æƒ…况下的自旋é”。 函数 ==== 该APIåœ¨ä»¥ä¸‹å†…æ ¸ä»£ç ä¸: lib/errseq.c