{"id":1535,"date":"2012-03-17T14:03:42","date_gmt":"2012-03-17T05:03:42","guid":{"rendered":"http:\/\/peta.okechan.net\/blog\/?p=1535"},"modified":"2012-03-17T14:03:42","modified_gmt":"2012-03-17T05:03:42","slug":"xv6-42-chapter-3-locking-exercises","status":"publish","type":"post","link":"https:\/\/peta.okechan.net\/blog\/archives\/1535","title":{"rendered":"[xv6 #42] Chapter 3 &#8211; Locking &#8211; Exercises"},"content":{"rendered":"<p>\u30c6\u30ad\u30b9\u30c8\u306e49\u301c50\u30da\u30fc\u30b8<\/p>\n<h3>\u672c\u6587<\/h3>\n<p>1. acquire\u95a2\u6570\u304b\u3089xchg\u547d\u4ee4\u3092\u53d6\u308a\u9664\u304d\u306a\u3055\u3044\u3002<br \/>\n\u305d\u3057\u3066xv6\u3092\u5b9f\u884c\u3057\u305f\u3068\u304d\u4f55\u304c\u8d77\u304d\u308b\u304b\u8aac\u660e\u3057\u306a\u3055\u3044\u3002<\/p>\n<p>2. iderw\u95a2\u6570\u306eacquire\u306e\u547c\u3073\u51fa\u3057\u3092sleep\u95a2\u6570\u306e\u524d\u306b\u79fb\u52d5\u3057\u306a\u3055\u3044\u3002<br \/>\n\u7af6\u5408\u306f\u5b58\u5728\u3057\u307e\u3059\u304b\uff1f<br \/>\nxv6\u3092\u8d77\u52d5\u3057\u3066stressfs\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u5b9f\u884c\u3057\u89b3\u5bdf\u3057\u3066\u307f\u3088\u3046\u3002<br \/>\n\u4eca\u5ea6\u306f\u3001\u30c0\u30df\u30fc\u306e\u30eb\u30fc\u30d7\u3092\u4f7f\u3063\u3066\u5371\u967a\u306a\u7b87\u6240\u3092\u5897\u3084\u3057\u3066\u307f\u307e\u3057\u3087\u3046\u3002<br \/>\n\u305d\u3057\u305f\u3089\u4f55\u304c\u8d77\u304d\u307e\u3059\u304b\uff1f\u8aac\u660e\u3057\u306a\u3055\u3044\u3002<\/p>\n<p>3. \u6295\u7a3f\u3055\u308c\u305f\u5bbf\u984c\u3092\u3084\u308a\u306a\u3055\u3044\u3002\uff08\u8b0e\uff09<\/p>\n<p>4. \u30d0\u30c3\u30d5\u30a1\u306eflags\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u8a2d\u5b9a\u306f\u3001\u30a2\u30c8\u30df\u30c3\u30af\u306a\u64cd\u4f5c\u3067\u306f\u306a\u3044\u3002<br \/>\n\u30d7\u30ed\u30bb\u30c3\u30b5\u306f\u3001flags\u306e\u30b3\u30d4\u30fc\u3092\u30ec\u30b8\u30b9\u30bf\u306b\u4f5c\u308a\u3001\u305d\u306e\u30ec\u30b8\u30b9\u30bf\u3092\u5909\u66f4\u3057\u3001\u305d\u308c\u3092\u66f8\u304d\u623b\u3059\u3002<br \/>\n\u306a\u306e\u3067\u30012\u3064\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u304c\u540c\u6642\u306bflags\u3092\u66f8\u304d\u63db\u3048\u306a\u3044\u3053\u3068\u304c\u91cd\u8981\u3067\u3042\u308b\u3002<br \/>\nxv6\u306f\u3001B_BUSY\u30d5\u30e9\u30b0\u3092\u7de8\u96c6\u3059\u308b\u3068\u304d\u3060\u3051buflock\u3092\u4fdd\u6301\u3059\u308b\u304c\u3001B_VALID\u3068B_WRITE\u3092\u7de8\u96c6\u3059\u308b\u3068\u304d\u306f\u3069\u306e\u30ed\u30c3\u30af\u3082\u4f7f\u308f\u306a\u3044\u3002<br \/>\n\u306a\u305c\u3053\u308c\u306f\u5b89\u5168\u306a\u306e\u3060\u308d\u3046\uff1f<\/p>\n<h3>\u4f5c\u696d<\/h3>\n<p>1. \u306b\u3064\u3044\u3066<br \/>\nspinlock.c\u306eacquire\u95a2\u6570\u306exchg\u547d\u4ee4\u3092\u5b9f\u884c\u3057\u3066\u308bwhile\u6587\u3054\u3068\u30b3\u30e1\u30f3\u30c8\u30a2\u30a6\u30c8\u3057\u3066\u307f\u307e\u3057\u305f\u3002<br \/>\nrelease\u95a2\u6570\u5185\u3067\u3001\u30ed\u30c3\u30af\u304c\u4fdd\u6301\u3055\u308c\u3066\u306a\u3044\u306e\u306b\u547c\u3070\u308c\u308b\u3068panic\u3059\u308b\u3088\u3046\u306b\u306a\u3063\u3066\u308b\u306e\u3067\u3001\u305d\u306e\u3068\u304a\u308a\u306b\u306a\u308a\u307e\u3057\u305f\u3002<br \/>\n\uff08\u3053\u308c\u3063\u3066\u8cea\u554f\u306e\u610f\u56f3\u3068\u5408\u3063\u3066\u308b\u306e\u304b\u306a\uff09<\/p>\n<p>2. \u306b\u3064\u3044\u3066<br \/>\nide.c\u306eiderw\u95a2\u6570\u306eacquire\u547c\u3073\u51fa\u3057\u306f\u5143\u3005sleep\u95a2\u6570\u306e\u524d\u306b\u3042\u308a\u307e\u3059\u304c\u3001\u9593\u306b\u30ad\u30e5\u30fc\u306e\u64cd\u4f5c\u304c\u5165\u3063\u3066\u308b\u306e\u3067\u3001\u305d\u306e\u76f4\u5f8c\u3068\u89e3\u91c8\u3057\u3066\uff08stressfs\u306e\u30bd\u30fc\u30b9\u306b\u66f8\u3044\u3066\u3042\u308b\u3057\uff09\u3001\u30ad\u30e5\u30fc\u64cd\u4f5c\u306e\u76f4\u5f8c\uff08*pp = b;\u306e\u76f4\u5f8c\uff09\u306bacquire\u3092\u79fb\u52d5\u3057\u3066\u307f\u307e\u3057\u305f\u3002<br \/>\n\u8d77\u52d5\u3084stressfs\u306e\u5b9f\u884c\u7a0b\u5ea6\u3067\u306f\u554f\u984c\u306f\u8868\u9762\u5316\u3057\u307e\u305b\u3093\u3067\u3057\u305f\u3002<br \/>\n\u3061\u306a\u307f\u306bstressfs\u306f\u30014\u3064\u306e\u5b50\u30d7\u30ed\u30bb\u30b9\u3092\u6570\u73e0\u3064\u306a\u304e\uff1f\u306b\u751f\u6210\u3057\u306a\u304c\u3089\u3001\u6700\u521d\u306e\u89aa\u30d7\u30ed\u30bb\u30b9\u3082\u542b\u3081\u305f\u8a085\u3064\u306e\u30d7\u30ed\u30bb\u30b9\u3067\u3001\u305d\u308c\u305e\u308c\u540c\u6642\u306b\u500b\u5225\u306e\u30d5\u30a1\u30a4\u30eb\u306b0\u301c99\u3092\u51fa\u529b\u3059\u308b\u3068\u3044\u3046\u30d7\u30ed\u30b0\u30e9\u30e0\u3067\u3059\u3002<\/p>\n<p>\u6b21\u306b\u3001acquire\u306e\u76f4\u524d\u306e\u30ad\u30e5\u30fc\u64cd\u4f5c\u306e\u6700\u4e2d\uff08*pp = b;\u306e\u76f4\u524d\u3001\u30eb\u30fc\u30d7\u306e\u5916\uff09\u306b\u3001\u30c0\u30df\u30fc\u30674\u4e07\u56de\u30eb\u30fc\u30d7\u3059\u308b\u30b3\u30fc\u30c9\uff08volatile int i;\u3092\u4f7f\u3063\u30664\u4e07\u56defor\u30eb\u30fc\u30d7\uff09\u3092\u633f\u5165\u3057\u307e\u3057\u305f\u3002<br \/>\n\u3057\u304b\u3057\u4f55\u56de\u304bstressfs\u3057\u3066\u3082\u7af6\u5408\u306f\u8d77\u304d\u305a\u3002<br \/>\n\u30c0\u30df\u30fc\u30eb\u30fc\u30d7\u306e\u56de\u6570\u3092\u5897\u3084\u3057\u305f\u308a\u3001\u958b\u767a\u74b0\u5883\u3092\u5b9f\u6a5f\u3067\u52d5\u304b\u3057\u305f\u308a\uff08\u3044\u307e\u307e\u3067VMware\u4e0a\u30672\u30b3\u30a2\u5272\u308a\u5f53\u3066\u305fFedora\u3067\u30b3\u30f3\u30d1\u30a4\u30eb\u30fb\u5b9f\u884c\u3057\u3066\u305f\uff09\u3001QEMU\u306e\u8a2d\u5b9a\u3067CPU\u30b3\u30a2\u6570\u30928\u30b3\u30a2\u3050\u3089\u3044\u307e\u3067\u5897\u3084\u3057\u305f\u308a\u3001\u30b3\u30f3\u30d1\u30a4\u30eb\u3067\u751f\u6210\u3055\u308c\u305f\u30c7\u30a3\u30b9\u30af\u30a4\u30e1\u30fc\u30b8\u3092VMware\u306b\u5272\u308a\u5f53\u3066\u3066\u76f4\u63a5\u8d77\u52d5\u3057\u3066\u307f\u305f\u308a\u3001stressfs\u306e\u30bd\u30fc\u30b9\u3082\u5f04\u3063\u3066\u8ca0\u8377\u3092\u4e0a\u3052\u308b\u3088\u3046\u306b\u3057\u305f\u308a\u8272\u3005\u3084\u308a\u307e\u3057\u305f\u304c\u3001\u7af6\u5408\u306f\u89b3\u6e2c\u3067\u304d\u305a\u3002<\/p>\n<p>\u7af6\u5408\u304c\u8d77\u304d\u308b\u3068\u3001idequeue\u306e\u6700\u5f8c\u306e\u8981\u7d20\u304c\u4e0a\u66f8\u304d\u3055\u308c\u3066\u5931\u308f\u308c\u308b\u5834\u5408\u304c\u51fa\u3066\u304f\u308b\u306f\u305a\u3067\u3001\u305d\u3046\u306a\u308b\u3068stressfs\u3067\u51fa\u529b\u3055\u308c\u308b\u30d5\u30a1\u30a4\u30eb\u306e\u30b5\u30a4\u30ba\u304c\u666e\u6bb5\u3088\u308a\u5c11\u3057\u5c0f\u3055\u304f\u306a\u308b\u306f\u305a\u3001\u3068\u601d\u3063\u3066stressfs\u5f8c\u306b\u5404\u30d5\u30a1\u30a4\u30eb\u306e\u30b5\u30a4\u30ba\u3092\u8abf\u3079\u3066\u7af6\u5408\u304c\u8d77\u304d\u3066\u308b\u304b\u3069\u3046\u304b\u5224\u65ad\u3057\u3066\u305f\u3093\u3067\u3059\u304c\u3001\u3082\u3057\u304b\u3057\u3066\u305d\u308c\u304c\u60aa\u304b\u3063\u305f\u3093\u3067\u3057\u3087\u3046\u304b\u3002<\/p>\n<p>\u306a\u3093\u3068\u3057\u3066\u3067\u3082\u7af6\u5408\u3092\u89b3\u6e2c\u3057\u305f\u304b\u3063\u305f\u3093\u3067\u3059\u304c\u3001\u5f8c\u306e\u7ae0\u3082\u3042\u308b\u306e\u3067\u3001\u3053\u306e\u554f\u984c\u306f\u4e00\u65e6\u3053\u3053\u3067\u7f6e\u3044\u3066\u304a\u304d\u307e\u3059\u3002<br \/>\n\u304f\u3084\u3057\u3044\u3002<\/p>\n<p>ide.c\u306eiderw\u95a2\u6570\uff08\u5909\u66f4\u524d\uff09<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/ Sync buf with disk. \r\n\/\/ If B_DIRTY is set, write buf to disk, clear B_DIRTY, set B_VALID.\r\n\/\/ Else if B_VALID is not set, read buf from disk, set B_VALID.\r\nvoid\r\niderw(struct buf *b)\r\n{\r\n  struct buf **pp;\r\n\r\n  if(!(b-&gt;flags &amp; B_BUSY))\r\n    panic(&quot;iderw: buf not busy&quot;);\r\n  if((b-&gt;flags &amp; (B_VALID|B_DIRTY)) == B_VALID)\r\n    panic(&quot;iderw: nothing to do&quot;);\r\n  if(b-&gt;dev != 0 &amp;&amp; !havedisk1)\r\n    panic(&quot;iderw: ide disk 1 not present&quot;);\r\n\r\n  acquire(&amp;idelock);  \/\/ DOC:acquire-lock\r\n\r\n  \/\/ Append b to idequeue.\r\n  b-&gt;qnext = 0;\r\n  for(pp=&amp;idequeue; *pp; pp=&amp;(*pp)-&gt;qnext)  \/\/ DOC:insert-queue\r\n    ;\r\n  *pp = b;\r\n  \r\n  \/\/ Start disk if necessary.\r\n  if(idequeue == b)\r\n    idestart(b);\r\n  \r\n  \/\/ Wait for request to finish.\r\n  \/\/ Assuming will not sleep too long: ignore proc-&gt;killed.\r\n  while((b-&gt;flags &amp; (B_VALID|B_DIRTY)) != B_VALID){\r\n    sleep(b, &amp;idelock);\r\n  }\r\n\r\n  release(&amp;idelock);\r\n}<\/pre>\n<p>stressfs.c<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/ Demonstrate that moving the &quot;acquire&quot; in iderw after the loop that\r\n\/\/ appends to the idequeue results in a race.\r\n\r\n\/\/ For this to work, you should also add a spin within iderw's\r\n\/\/ idequeue traversal loop.  Spinning 40000 times demonstrated the bug\r\n\/\/ after about 5 runs of stressfs in QEMU on a 2.1GHz CPU.\r\n\r\n#include &quot;types.h&quot;\r\n#include &quot;stat.h&quot;\r\n#include &quot;user.h&quot;\r\n#include &quot;fs.h&quot;\r\n#include &quot;fcntl.h&quot;\r\n\r\nint\r\nmain(int argc, char *argv&#x5B;])\r\n{\r\n  int fd, i;\r\n  char path&#x5B;] = &quot;stressfs0&quot;;\r\n\r\n  printf(1, &quot;stressfs starting\\n&quot;);\r\n\r\n  for(i = 0; i &lt; 4; i++)\r\n    if(fork() &gt; 0)\r\n      break;\r\n\r\n  printf(1, &quot;%d\\n&quot;, i);\r\n\r\n  path&#x5B;8] += i;\r\n  fd = open(path, O_CREATE | O_RDWR);\r\n  for(i = 0; i &lt; 100; i++)\r\n    printf(fd, &quot;%d\\n&quot;, i);\r\n  close(fd);\r\n\r\n  wait();\r\n  \r\n  exit();\r\n}<\/pre>\n<p>3. \u306b\u3064\u3044\u3066<br \/>\n\u8b0e\u3067\u3059\u3002<\/p>\n<p>4. \u306b\u3064\u3044\u3066<br \/>\n\u672c\u6587\u306bB_WRITE\u3068\u3042\u308a\u307e\u3059\u304c\u3001\u30bd\u30fc\u30b9\u306b\u305d\u3093\u306a\u5b9a\u7fa9\u306f\u306a\u3044\u306e\u3067\u3001\u4ed6\u306e\u5b9a\u7fa9\u304b\u3089\u3057\u3066\u591a\u5206B_DIRTY\u306e\u9593\u9055\u3044\u3067\u3057\u3087\u3046\u3002<br \/>\n\u3042\u3068buflock\u3068\u3044\u3046\u30ed\u30c3\u30af\u5909\u6570\u3082\u306a\u3044\u306e\u3067\u3001\u72b6\u6cc1\u304b\u3089\u3057\u3066bcache.lock\u306e\u3053\u3068\u304b\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n<p>bio.c<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/ Buffer cache.\r\n\/\/\r\n\/\/ The buffer cache is a linked list of buf structures holding\r\n\/\/ cached copies of disk block contents.  Caching disk blocks\r\n\/\/ in memory reduces the number of disk reads and also provides\r\n\/\/ a synchronization point for disk blocks used by multiple processes.\r\n\/\/ \r\n\/\/ Interface:\r\n\/\/ * To get a buffer for a particular disk block, call bread.\r\n\/\/ * After changing buffer data, call bwrite to flush it to disk.\r\n\/\/ * When done with the buffer, call brelse.\r\n\/\/ * Do not use the buffer after calling brelse.\r\n\/\/ * Only one process at a time can use a buffer,\r\n\/\/     so do not keep them longer than necessary.\r\n\/\/ \r\n\/\/ The implementation uses three state flags internally:\r\n\/\/ * B_BUSY: the block has been returned from bread\r\n\/\/     and has not been passed back to brelse.  \r\n\/\/ * B_VALID: the buffer data has been initialized\r\n\/\/     with the associated disk block contents.\r\n\/\/ * B_DIRTY: the buffer data has been modified\r\n\/\/     and needs to be written to disk.\r\n\r\n#include &quot;types.h&quot;\r\n#include &quot;defs.h&quot;\r\n#include &quot;param.h&quot;\r\n#include &quot;spinlock.h&quot;\r\n#include &quot;buf.h&quot;\r\n\r\nstruct {\r\n  struct spinlock lock;\r\n  struct buf buf&#x5B;NBUF];\r\n\r\n  \/\/ Linked list of all buffers, through prev\/next.\r\n  \/\/ head.next is most recently used.\r\n  struct buf head;\r\n} bcache;\r\n\r\nvoid\r\nbinit(void)\r\n{\r\n  struct buf *b;\r\n\r\n  initlock(&amp;bcache.lock, &quot;bcache&quot;);\r\n\r\n\/\/PAGEBREAK!\r\n  \/\/ Create linked list of buffers\r\n  bcache.head.prev = &amp;bcache.head;\r\n  bcache.head.next = &amp;bcache.head;\r\n  for(b = bcache.buf; b &lt; bcache.buf+NBUF; b++){\r\n    b-&gt;next = bcache.head.next;\r\n    b-&gt;prev = &amp;bcache.head;\r\n    b-&gt;dev = -1;\r\n    bcache.head.next-&gt;prev = b;\r\n    bcache.head.next = b;\r\n  }\r\n}\r\n\r\n\/\/ Look through buffer cache for sector on device dev.\r\n\/\/ If not found, allocate fresh block.\r\n\/\/ In either case, return locked buffer.\r\nstatic struct buf*\r\nbget(uint dev, uint sector)\r\n{\r\n  struct buf *b;\r\n\r\n  acquire(&amp;bcache.lock);\r\n\r\n loop:\r\n  \/\/ Try for cached block.\r\n  for(b = bcache.head.next; b != &amp;bcache.head; b = b-&gt;next){\r\n    if(b-&gt;dev == dev &amp;&amp; b-&gt;sector == sector){\r\n      if(!(b-&gt;flags &amp; B_BUSY)){\r\n        b-&gt;flags |= B_BUSY;\r\n        release(&amp;bcache.lock);\r\n        return b;\r\n      }\r\n      sleep(b, &amp;bcache.lock);\r\n      goto loop;\r\n    }\r\n  }\r\n\r\n  \/\/ Allocate fresh block.\r\n  for(b = bcache.head.prev; b != &amp;bcache.head; b = b-&gt;prev){\r\n    if((b-&gt;flags &amp; B_BUSY) == 0){\r\n      b-&gt;dev = dev;\r\n      b-&gt;sector = sector;\r\n      b-&gt;flags = B_BUSY;\r\n      release(&amp;bcache.lock);\r\n      return b;\r\n    }\r\n  }\r\n  panic(&quot;bget: no buffers&quot;);\r\n}\r\n\r\n\/\/ Return a B_BUSY buf with the contents of the indicated disk sector.\r\nstruct buf*\r\nbread(uint dev, uint sector)\r\n{\r\n  struct buf *b;\r\n\r\n  b = bget(dev, sector);\r\n  if(!(b-&gt;flags &amp; B_VALID))\r\n    iderw(b);\r\n  return b;\r\n}\r\n\r\n\/\/ Write b's contents to disk.  Must be locked.\r\nvoid\r\nbwrite(struct buf *b)\r\n{\r\n  if((b-&gt;flags &amp; B_BUSY) == 0)\r\n    panic(&quot;bwrite&quot;);\r\n  b-&gt;flags |= B_DIRTY;\r\n  iderw(b);\r\n}\r\n\r\n\/\/ Release the buffer b.\r\nvoid\r\nbrelse(struct buf *b)\r\n{\r\n  if((b-&gt;flags &amp; B_BUSY) == 0)\r\n    panic(&quot;brelse&quot;);\r\n\r\n  acquire(&amp;bcache.lock);\r\n\r\n  b-&gt;next-&gt;prev = b-&gt;prev;\r\n  b-&gt;prev-&gt;next = b-&gt;next;\r\n  b-&gt;next = bcache.head.next;\r\n  b-&gt;prev = &amp;bcache.head;\r\n  bcache.head.next-&gt;prev = b;\r\n  bcache.head.next = b;\r\n\r\n  b-&gt;flags &amp;= ~B_BUSY;\r\n  wakeup(b);\r\n\r\n  release(&amp;bcache.lock);\r\n}<\/pre>\n<p>\u305d\u308c\u305e\u308c\u306e\u30d5\u30e9\u30b0\u306e\u610f\u5473\u3092\u307e\u3068\u307e\u308b\u3068\u6b21\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>B_BUSY<br \/>\n\u305d\u306e\u30d0\u30c3\u30d5\u30a1\u306fbread\u3067\u8aad\u307f\u8fbc\u307e\u308c\u305f\u304c\u3001\u307e\u3060brelse\u3055\u308c\u3066\u306a\u3044\u3002<br \/>\nbread\u306f\u30c7\u30a3\u30b9\u30af\u304b\u3089\u30d0\u30c3\u30d5\u30a1\u3078\u306e\u8aad\u307f\u8fbc\u307f\u3092\u884c\u3046\u3002<br \/>\nbrelse\u306f\u30c7\u30fc\u30bf\u3092\u30d0\u30c3\u30d5\u30a1\u304b\u3089\u30ad\u30e3\u30c3\u30b7\u30e5\u3078\u79fb\u52d5\u3059\u308b\u3002<br \/>\nbio.c\u306ebget\u95a2\u6570\uff08bread\u304b\u3089\u547c\u3070\u308c\u308b\uff09\u306e\u307f\u3067\u30bb\u30c3\u30c8\u3055\u308c\u308b\u3002<\/p>\n<p>B_VALID<br \/>\n\u305d\u306e\u30d0\u30c3\u30d5\u30a1\u306f\u8aad\u307f\u8fbc\u307e\u308c\u307e\u3060\u5909\u66f4\u3055\u308c\u3066\u306a\u3044\u3002<br \/>\n\u30bb\u30c3\u30c8\u3055\u308c\u3066\u308b\u306e\u306f\u3001ide.c\u306eideintr\u95a2\u6570\u3067\u306e\u307f\u3002<\/p>\n<p>B_DIRTY<br \/>\n\u30d0\u30c3\u30d5\u30a1\u306e\u5185\u5bb9\u304c\u5909\u66f4\u3055\u308c\u305f\u306e\u3067\u66f8\u304d\u8fbc\u307f\u306e\u5fc5\u8981\u3042\u308a\u3002<br \/>\n\u30bb\u30c3\u30c8\u3055\u308c\u3066\u308b\u306e\u306f\u3001bio.c\u306ebwrite\u95a2\u6570\u3067\u306e\u307f\u3002<br \/>\n\u30ed\u30c3\u30af\u306finode\u30ec\u30d9\u30eb\u3067\u884c\u308f\u308c\u308b\u3002<\/p>\n<p>\u8ab2\u984c\u306e\u610f\u56f3\u3068\u3057\u3066\u306f\u3001bio.c\u306ebget\u95a2\u6570\u3067B_BUSY\u30d5\u30e9\u30b0\u3092\u7acb\u3066\u308b\u3068\u304d\u306fbcache.lock\u3092\u4f7f\u3063\u3066\u308b\u306e\u306b\u3001\u4ed6\u306e\u30d5\u30e9\u30b0\u3092\u7acb\u3066\u308b\u3068\u304d\u306fbcache.lock\u3092\u4f7f\u3063\u3066\u306a\u3044\u306e\u306f\u306a\u305c\uff1f\u3068\u3044\u3046\u3053\u3068\u304b\u306a\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n<p>\u307e\u305aB_VALID\u306b\u3064\u3044\u3066\u306f\u3001ide.c\u306eideintr\u95a2\u6570\u3067\u30d5\u30e9\u30b0\u3092\u7acb\u3066\u307e\u3059\u304c\u3001ideintr\u306f\u5272\u308a\u8fbc\u307f\u4e2d\u304b\u3064\u4ed6\u306e\u30ed\u30c3\u30af\uff08idelock\uff09\u3092\u7372\u5f97\u6e08\u307f\u3067\u3042\u308a\u3001\u4ed6\u3067\u30ed\u30c3\u30af\u304c\u5fc5\u8981\u306a\u64cd\u4f5c\u304c\u3055\u308c\u3066\u306a\u3044\u4e8b\u304c\u660e\u3089\u304b\u306a\u306e\u3067\u30ed\u30c3\u30af\u3059\u308b\u5fc5\u8981\u304c\u306a\u3044\u3001\u3063\u3066\u3068\u3053\u308d\u304b\u306a\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n<p>B_DIRTY\u306b\u3064\u3044\u3066\u306f\u3061\u3087\u3068\u8ffd\u3046\u306e\u304c\u96e3\u3057\u304b\u3063\u305f\u306e\u3067\u3059\u304c\u3001\u8981\u306finode\u306e\u30ec\u30d9\u30eb\u3067\u30ed\u30c3\u30af\u3092\u7372\u5f97\u6e08\u307f\u3060\u304b\u3089\u5fc5\u8981\u306a\u3044\u306e\u304b\u306a\u3068\u601d\u3044\u307e\u3059\u3002<br \/>\n\u307e\u3060\u51fa\u3066\u304d\u3066\u306a\u3044fs.c\u3092\u8aad\u3093\u3060\u3068\u3053\u308d\u3001\u30b7\u30b9\u30c6\u30e0\u30b3\u30fc\u30eb\u3092\u4f7f\u3063\u3066\u66f8\u304d\u8fbc\u3080\u5834\u5408\u3001\u8d85\u5927\u96d1\u628a\u306b\u306f<br \/>\nsys_write\u95a2\u6570\u2192filewrite\u95a2\u6570\uff08\u3053\u306e\u4e2d\u3067inode\u5358\u4f4d\u3067\u30ed\u30c3\u30af\u3092\u7372\u5f97\uff09\u2192writei\u95a2\u6570\u2192bwrite\u95a2\u6570<br \/>\n\u3068\u3044\u3046\u968e\u5c64\u95a2\u4fc2\u3067\u95a2\u6570\u304c\u547c\u3070\u308c\u307e\u3059\u3002<br \/>\n\u30d0\u30c3\u30d5\u30a1\u3092\u5185\u5305\u3059\u308binode\u5358\u4f4d\u3067\u30ed\u30c3\u30af\u3092\u7372\u5f97\u6e08\u307f\u306a\u3089\u3001\u30d0\u30c3\u30d5\u30a1\u306e\u64cd\u4f5c\u3082\u4ed6\u3068\u88ab\u308b\u3053\u3068\u304c\u306a\u3044\u304b\u3089\u6539\u3081\u3066\u30d0\u30c3\u30d5\u30a1\u5358\u4f4d\u3067\u30ed\u30c3\u30af\u3092\u7372\u5f97\u3059\u308b\u5fc5\u8981\u306f\u306a\u3044\u306e\u304b\u306a\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n<h3>\u611f\u60f3<\/h3>\n<p>\u306a\u3093\u3060\u304b\u4e0d\u5b8c\u5168\u71c3\u713c\u3067\u3059\u3002<br \/>\n\u3057\u304b\u3057\u3044\u3064\u307e\u3067\u3082\u3053\u3053\u3067\u7559\u307e\u3063\u3066\u308b\u308f\u3051\u306b\u3082\u884c\u304b\u306a\u3044\u306e\u3067\u5148\u306b\u9032\u307f\u307e\u3059\u304c\u3001\u3061\u3087\u304f\u3061\u3087\u304f\u8a66\u3057\u3066\u307f\u3066\u3068\u306b\u304b\u304f\u7af6\u5408\u72b6\u614b\u306f\u78ba\u8a8d\u3057\u305f\u3044\u306a\u3068\u601d\u3063\u3066\u307e\u3059\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u30c6\u30ad\u30b9\u30c8\u306e49\u301c50\u30da\u30fc\u30b8<\/p>\n<h3>\u672c\u6587<\/h3>\n<p>1. acquire\u95a2\u6570\u304b\u3089xchg\u547d\u4ee4\u3092\u53d6\u308a\u9664\u304d\u306a\u3055\u3044\u3002<br \/>\n\u305d\u3057\u3066xv6\u3092\u5b9f\u884c\u3057\u305f\u3068\u304d\u4f55\u304c\u8d77\u304d\u308b\u304b\u8aac\u660e\u3057\u306a\u3055\u3044\u3002<\/p>\n<p>2. iderw\u95a2\u6570\u306eacquire\u306e\u547c\u3073\u51fa\u3057\u3092sleep\u95a2\u6570\u306e\u524d\u306b\u79fb\u52d5\u3057\u306a\u3055\u3044\u3002<br \/>\n\u7af6\u5408\u306f\u5b58\u5728\u3057\u307e\u3059\u304b\uff1f<br \/>\nxv6\u3092\u8d77\u52d5\u3057\u3066stressfs\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u5b9f\u884c\u3057\u89b3\u5bdf\u3057\u3066\u307f\u3088\u3046\u3002<br \/>\n\u4eca\u5ea6\u306f\u3001\u30c0\u30df\u30fc\u306e\u30eb\u30fc\u30d7\u3092\u4f7f\u3063\u3066\u5371\u967a\u306a\u7b87\u6240\u3092\u5897\u3084\u3057\u3066\u307f\u307e\u3057\u3087\u3046\u3002<br \/>\n\u305d\u3057\u305f\u3089\u4f55\u304c\u8d77\u304d\u307e\u3059\u304b\uff1f\u8aac\u660e\u3057\u306a\u3055\u3044\u3002<\/p>\n<p>3. \u6295\u7a3f\u3055\u308c\u305f\u5bbf\u984c\u3092\u3084\u308a\u306a\u3055\u3044\u3002\uff08\u8b0e\uff09<\/p>\n<p>4. \u30d0\u30c3\u30d5\u30a1\u306eflags\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u8a2d\u5b9a\u306f\u3001\u30a2\u30c8\u30df\u30c3\u30af\u306a\u64cd\u4f5c\u3067\u306f\u306a\u3044\u3002<br \/>\n\u30d7\u30ed\u30bb\u30c3\u30b5\u306f\u3001flags\u306e\u30b3\u30d4\u30fc\u3092\u30ec\u30b8\u30b9\u30bf\u306b\u4f5c\u308a\u3001\u305d\u306e\u30ec\u30b8\u30b9\u30bf\u3092\u5909\u66f4\u3057\u3001\u305d\u308c\u3092\u66f8\u304d\u623b\u3059\u3002<br \/>\n\u306a\u306e\u3067\u30012\u3064\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u304c\u540c\u6642\u306bflags\u3092\u66f8\u304d\u63db\u3048\u306a\u3044\u3053\u3068\u304c\u91cd\u8981\u3067\u3042\u308b\u3002<br \/>\nxv6\u306f\u3001B_BUSY\u30d5\u30e9\u30b0\u3092\u7de8\u96c6\u3059\u308b\u3068\u304d\u3060\u3051buflock\u3092\u4fdd\u6301\u3059\u308b\u304c\u3001B_VALID\u3068B_WRITE\u3092\u7de8\u96c6\u3059\u308b\u3068\u304d\u306f\u3069\u306e\u30ed\u30c3\u30af\u3082\u4f7f\u308f\u306a\u3044\u3002<br \/>\n\u306a\u305c\u3053\u308c\u306f\u5b89\u5168\u306a\u306e\u3060\u308d\u3046\uff1f<\/p>\n<h3>\u4f5c\u696d<\/h3>\n<p>1. \u306b\u3064\u3044\u3066<br \/>\nspinlock.c\u306eacquire\u95a2\u6570\u306exchg\u547d\u4ee4\u3092\u5b9f\u884c\u3057\u3066\u308bwhile\u6587\u3054\u3068\u30b3\u30e1\u30f3\u30c8\u30a2\u30a6\u30c8\u3057\u3066\u307f\u307e\u3057\u305f\u3002<br \/>\nrelease\u95a2\u6570\u5185\u3067\u3001\u30ed\u30c3\u30af\u304c\u4fdd\u6301\u3055\u308c\u3066\u306a\u3044\u306e\u306b\u547c\u3070\u308c\u308b\u3068panic\u3059\u308b\u3088\u3046\u306b\u306a\u3063\u3066\u308b\u306e\u3067\u3001\u305d\u306e\u3068\u304a\u308a\u306b\u306a\u308a\u307e\u3057\u305f\u3002<br \/>\n\uff08\u3053\u308c\u3063\u3066\u8cea\u554f\u306e\u610f\u56f3\u3068\u5408\u3063\u3066\u308b\u306e\u304b\u306a\uff09<\/p>\n<p>2. \u306b\u3064\u3044\u3066<br \/>\nide.c\u306eiderw\u95a2\u6570\u306eacquire\u547c\u3073\u51fa\u3057\u306f\u5143\u3005sleep\u95a2\u6570\u306e\u524d\u306b\u3042\u308a\u307e\u3059\u304c\u3001\u9593\u306b\u30ad\u30e5\u30fc\u306e\u64cd\u4f5c\u304c\u5165\u3063\u3066\u308b\u306e\u3067\u3001\u305d\u306e\u76f4\u5f8c\u3068\u89e3\u91c8\u3057\u3066\uff08stressfs\u306e\u30bd\u30fc\u30b9\u306b\u66f8\u3044\u3066\u3042\u308b\u3057\uff09\u3001\u30ad\u30e5\u30fc\u64cd\u4f5c\u306e\u76f4\u5f8c\uff08*pp = b;\u306e\u76f4\u5f8c\uff09\u306bacquire\u3092\u79fb\u52d5\u3057\u3066\u307f\u307e\u3057\u305f\u3002<br \/>\n\u8d77\u52d5\u3084stressfs\u306e\u5b9f\u884c\u7a0b\u5ea6\u3067\u306f\u554f\u984c\u306f\u8868\u9762\u5316\u3057\u307e\u305b\u3093\u3067\u3057\u305f\u3002<br \/>\n\u3061\u306a\u307f\u306bstressfs\u306f\u30014\u3064\u306e\u5b50\u30d7\u30ed\u30bb\u30b9\u3092\u6570\u73e0\u3064\u306a\u304e\uff1f\u306b\u751f\u6210\u3057\u306a\u304c\u3089\u3001\u6700\u521d\u306e\u89aa\u30d7\u30ed\u30bb\u30b9\u3082\u542b\u3081\u305f\u8a085\u3064\u306e\u30d7\u30ed\u30bb\u30b9\u3067\u3001\u305d\u308c\u305e\u308c\u540c\u6642\u306b\u500b\u5225\u306e\u30d5\u30a1\u30a4\u30eb\u306b0\u301c99\u3092\u51fa\u529b\u3059\u308b\u3068\u3044\u3046\u30d7\u30ed\u30b0\u30e9\u30e0\u3067\u3059\u3002<\/p>\n<p>\u6b21\u306b\u3001acquire\u306e\u76f4\u524d\u306e\u30ad\u30e5\u30fc\u64cd\u4f5c\u306e\u6700\u4e2d\uff08*pp = b;\u306e\u76f4\u524d\u3001\u30eb\u30fc\u30d7\u306e\u5916\uff09\u306b\u3001\u30c0\u30df\u30fc\u30674\u4e07\u56de\u30eb\u30fc\u30d7\u3059\u308b\u30b3\u30fc\u30c9\uff08volatile int i;\u3092\u4f7f\u3063\u30664\u4e07\u56defor\u30eb\u30fc\u30d7\uff09\u3092\u633f\u5165\u3057\u307e\u3057\u305f\u3002<br \/>\n\u3057\u304b\u3057\u4f55\u56de\u304bstressfs\u3057\u3066\u3082\u7af6\u5408\u306f\u8d77\u304d\u305a\u3002<br \/>\n\u30c0\u30df\u30fc\u30eb\u30fc\u30d7\u306e\u56de\u6570\u3092\u5897\u3084\u3057\u305f\u308a\u3001\u958b\u767a\u74b0\u5883\u3092\u5b9f\u6a5f\u3067\u52d5\u304b\u3057\u305f\u308a\uff08\u3044\u307e\u307e\u3067VMware\u4e0a\u30672\u30b3\u30a2\u5272\u308a\u5f53\u3066\u305fFedora\u3067\u30b3\u30f3\u30d1\u30a4\u30eb\u30fb\u5b9f\u884c\u3057\u3066\u305f\uff09\u3001QEMU\u306e\u8a2d\u5b9a\u3067CPU\u30b3\u30a2\u6570\u30928\u30b3\u30a2\u3050\u3089\u3044\u307e\u3067\u5897\u3084\u3057\u305f\u308a\u3001\u30b3\u30f3\u30d1\u30a4\u30eb\u3067\u751f\u6210\u3055\u308c\u305f\u30c7\u30a3\u30b9\u30af\u30a4\u30e1\u30fc\u30b8\u3092VMware\u306b\u5272\u308a\u5f53\u3066\u3066\u76f4\u63a5\u8d77\u52d5\u3057\u3066\u307f\u305f\u308a\u3001stressfs\u306e\u30bd\u30fc\u30b9\u3082\u5f04\u3063\u3066\u8ca0\u8377\u3092\u4e0a\u3052\u308b\u3088\u3046\u306b\u3057\u305f\u308a\u8272\u3005\u3084\u308a\u307e\u3057\u305f\u304c\u3001\u7af6\u5408\u306f\u89b3\u6e2c\u3067\u304d\u305a\u3002<\/p>\n<p>\u7af6\u5408\u304c\u8d77\u304d\u308b\u3068\u3001idequeue\u306e\u6700\u5f8c\u306e\u8981\u7d20\u304c\u4e0a\u66f8\u304d\u3055\u308c\u3066\u5931\u308f\u308c\u308b\u5834\u5408\u304c\u51fa\u3066\u304f\u308b\u306f\u305a\u3067\u3001\u305d\u3046\u306a\u308b\u3068stressfs\u3067\u51fa\u529b\u3055\u308c\u308b\u30d5\u30a1\u30a4\u30eb\u306e\u30b5\u30a4\u30ba\u304c\u666e\u6bb5\u3088\u308a\u5c11\u3057\u5c0f\u3055\u304f\u306a\u308b\u306f\u305a\u3001\u3068\u601d\u3063\u3066stressfs\u5f8c\u306b\u5404\u30d5\u30a1\u30a4\u30eb\u306e\u30b5\u30a4\u30ba\u3092\u8abf\u3079\u3066\u7af6\u5408\u304c\u8d77\u304d\u3066\u308b\u304b\u3069\u3046\u304b\u5224\u65ad\u3057\u3066\u305f\u3093\u3067\u3059\u304c\u3001\u3082\u3057\u304b\u3057\u3066\u305d\u308c\u304c\u60aa\u304b\u3063\u305f\u3093\u3067\u3057\u3087\u3046\u304b\u3002<\/p>\n<p>\u306a\u3093\u3068\u3057\u3066\u3067\u3082\u7af6\u5408\u3092\u89b3\u6e2c\u3057\u305f\u304b\u3063\u305f\u3093\u3067\u3059\u304c\u3001\u5f8c\u306e\u7ae0\u3082\u3042\u308b\u306e\u3067\u3001\u3053\u306e\u554f\u984c\u306f\u4e00\u65e6\u3053\u3053\u3067\u7f6e\u3044\u3066\u304a\u304d\u307e\u3059\u3002<br \/>\n\u304f\u3084\u3057\u3044\u3002<\/p>\n<p>ide.c\u306eiderw\u95a2\u6570\uff08\u5909\u66f4\u524d\uff09<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/ Sync buf with disk. \r\n\/\/ If B_DIRTY is set, write buf to disk, clear B_DIRTY, set B_VALID.\r\n\/\/ Else if B_VALID is not set, read buf from disk, set B_VALID.\r\nvoid\r\niderw(struct buf *b)\r\n{\r\n  struct buf **pp;\r\n\r\n  if(!(b-&gt;flags &amp; B_BUSY))\r\n    panic(&quot;iderw: buf not busy&quot;);\r\n  if((b-&gt;flags &amp; (B_VALID|B_DIRTY)) == B_VALID)\r\n    panic(&quot;iderw: nothing to do&quot;);\r\n  if(b-&gt;dev != 0 &amp;&amp; !havedisk1)\r\n    panic(&quot;iderw: ide disk 1 not present&quot;);\r\n\r\n  acquire(&amp;idelock);  \/\/ DOC:acquire-lock\r\n\r\n  \/\/ Append b to idequeue.\r\n  b-&gt;qnext = 0;\r\n  for(pp=&amp;idequeue; *pp; pp=&amp;(*pp)-&gt;qnext)  \/\/ DOC:insert-queue\r\n    ;\r\n  *pp = b;\r\n  \r\n  \/\/ Start disk if necessary.\r\n  if(idequeue == b)\r\n    idestart(b);\r\n  \r\n  \/\/ Wait for request to finish.\r\n  \/\/ Assuming will not sleep too long: ignore proc-&gt;killed.\r\n  while((b-&gt;flags &amp; (B_VALID|B_DIRTY)) != B_VALID){\r\n    sleep(b, &amp;idelock);\r\n  }\r\n\r\n  release(&amp;idelock);\r\n}<\/pre>\n<p>stressfs.c<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/ Demonstrate that moving the &quot;acquire&quot; in iderw after the loop that\r\n\/\/ appends to the idequeue results in a race.\r\n\r\n\/\/ For this to work, you should also add a spin within iderw's\r\n\/\/ idequeue traversal loop.  Spinning 40000 times demonstrated the bug\r\n\/\/ after about 5 runs of stressfs in QEMU on a 2.1GHz CPU.\r\n\r\n#include &quot;types.h&quot;\r\n#include &quot;stat.h&quot;\r\n#include &quot;user.h&quot;\r\n#include &quot;fs.h&quot;\r\n#include &quot;fcntl.h&quot;\r\n\r\nint\r\nmain(int argc, char *argv&#x5B;])\r\n{\r\n  int fd, i;\r\n  char path&#x5B;] = &quot;stressfs0&quot;;\r\n\r\n  printf(1, &quot;stressfs starting\\n&quot;);\r\n\r\n  for(i = 0; i &lt; 4; i++)\r\n    if(fork() &gt; 0)\r\n      break;\r\n\r\n  printf(1, &quot;%d\\n&quot;, i);\r\n\r\n  path&#x5B;8] += i;\r\n  fd = open(path, O_CREATE | O_RDWR);\r\n  for(i = 0; i &lt; 100; i++)\r\n    printf(fd, &quot;%d\\n&quot;, i);\r\n  close(fd);\r\n\r\n  wait();\r\n  \r\n  exit();\r\n}<\/pre>\n<p>3. \u306b\u3064\u3044\u3066<br \/>\n\u8b0e\u3067\u3059\u3002<\/p>\n<p>4. \u306b\u3064\u3044\u3066<br \/>\n\u672c\u6587\u306bB_WRITE\u3068\u3042\u308a\u307e\u3059\u304c\u3001\u30bd\u30fc\u30b9\u306b\u305d\u3093\u306a\u5b9a\u7fa9\u306f\u306a\u3044\u306e\u3067\u3001\u4ed6\u306e\u5b9a\u7fa9\u304b\u3089\u3057\u3066\u591a\u5206B_DIRTY\u306e\u9593\u9055\u3044\u3067\u3057\u3087\u3046\u3002<br \/>\n\u3042\u3068buflock\u3068\u3044\u3046\u30ed\u30c3\u30af\u5909\u6570\u3082\u306a\u3044\u306e\u3067\u3001\u72b6\u6cc1\u304b\u3089\u3057\u3066bcache.lock\u306e\u3053\u3068\u304b\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n<p>bio.c<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/ Buffer cache.\r\n\/\/\r\n\/\/ The buffer cache is a linked list of buf structures holding\r\n\/\/ cached copies of disk block contents.  Caching disk blocks\r\n\/\/ in memory reduces the number of disk reads and also provides\r\n\/\/ a synchronization point for disk blocks used by multiple processes.\r\n\/\/ \r\n\/\/ Interface:\r\n\/\/ * To get a buffer for a particular disk block, call bread.\r\n\/\/ * After changing buffer data, call bwrite to flush it to disk.\r\n\/\/ * When done with the buffer, call brelse.\r\n\/\/ * Do not use the buffer after calling brelse.\r\n\/\/ * Only one process at a time can use a buffer,\r\n\/\/     so do not keep them longer than necessary.\r\n\/\/ \r\n\/\/ The implementation uses three state flags internally:\r\n\/\/ * B_BUSY: the block has been returned from bread\r\n\/\/     and has not been passed back to brelse.  \r\n\/\/ * B_VALID: the buffer data has been initialized\r\n\/\/     with the associated disk block contents.\r\n\/\/ * B_DIRTY: the buffer data has been modified\r\n\/\/     and needs to be written to disk.\r\n\r\n#include &quot;types.h&quot;\r\n#include &quot;defs.h&quot;\r\n#include &quot;param.h&quot;\r\n#include &quot;spinlock.h&quot;\r\n#include &quot;buf.h&quot;\r\n\r\nstruct {\r\n  struct spinlock lock;\r\n  struct buf buf&#x5B;NBUF];\r\n\r\n  \/\/ Linked list of all buffers, through prev\/next.\r\n  \/\/ head.next is most recently used.\r\n  struct buf head;\r\n} bcache;\r\n\r\nvoid\r\nbinit(void)\r\n{\r\n  struct buf *b;\r\n\r\n  initlock(&amp;bcache.lock, &quot;bcache&quot;);\r\n\r\n\/\/PAGEBREAK!\r\n  \/\/ Create linked list of buffers\r\n  bcache.head.prev = &amp;bcache.head;\r\n  bcache.head.next = &amp;bcache.head;\r\n  for(b = bcache.buf; b &lt; bcache.buf+NBUF; b++){\r\n    b-&gt;next = bcache.head.next;\r\n    b-&gt;prev = &amp;bcache.head;\r\n    b-&gt;dev = -1;\r\n    bcache.head.next-&gt;prev = b;\r\n    bcache.head.next = b;\r\n  }\r\n}\r\n\r\n\/\/ Look through buffer cache for sector on device dev.\r\n\/\/ If not found, allocate fresh block.\r\n\/\/ In either case, return locked buffer.\r\nstatic struct buf*\r\nbget(uint dev, uint sector)\r\n{\r\n  struct buf *b;\r\n\r\n  acquire(&amp;bcache.lock);\r\n\r\n loop:\r\n  \/\/ Try for cached block.\r\n  for(b = bcache.head.next; b != &amp;bcache.head; b = b-&gt;next){\r\n    if(b-&gt;dev == dev &amp;&amp; b-&gt;sector == sector){\r\n      if(!(b-&gt;flags &amp; B_BUSY)){\r\n        b-&gt;flags |= B_BUSY;\r\n        release(&amp;bcache.lock);\r\n        return b;\r\n      }\r\n      sleep(b, &amp;bcache.lock);\r\n      goto loop;\r\n    }\r\n  }\r\n\r\n  \/\/ Allocate fresh block.\r\n  for(b = bcache.head.prev; b != &amp;bcache.head; b = b-&gt;prev){\r\n    if((b-&gt;flags &amp; B_BUSY) == 0){\r\n      b-&gt;dev = dev;\r\n      b-&gt;sector = sector;\r\n      b-&gt;flags = B_BUSY;\r\n      release(&amp;bcache.lock);\r\n      return b;\r\n    }\r\n  }\r\n  panic(&quot;bget: no buffers&quot;);\r\n}\r\n\r\n\/\/ Return a B_BUSY buf with the contents of the indicated disk sector.\r\nstruct buf*\r\nbread(uint dev, uint sector)\r\n{\r\n  struct buf *b;\r\n\r\n  b = bget(dev, sector);\r\n  if(!(b-&gt;flags &amp; B_VALID))\r\n    iderw(b);\r\n  return b;\r\n}\r\n\r\n\/\/ Write b's contents to disk.  Must be locked.\r\nvoid\r\nbwrite(struct buf *b)\r\n{\r\n  if((b-&gt;flags &amp; B_BUSY) == 0)\r\n    panic(&quot;bwrite&quot;);\r\n  b-&gt;flags |= B_DIRTY;\r\n  iderw(b);\r\n}\r\n\r\n\/\/ Release the buffer b.\r\nvoid\r\nbrelse(struct buf *b)\r\n{\r\n  if((b-&gt;flags &amp; B_BUSY) == 0)\r\n    panic(&quot;brelse&quot;);\r\n\r\n  acquire(&amp;bcache.lock);\r\n\r\n  b-&gt;next-&gt;prev = b-&gt;prev;\r\n  b-&gt;prev-&gt;next = b-&gt;next;\r\n  b-&gt;next = bcache.head.next;\r\n  b-&gt;prev = &amp;bcache.head;\r\n  bcache.head.next-&gt;prev = b;\r\n  bcache.head.next = b;\r\n\r\n  b-&gt;flags &amp;= ~B_BUSY;\r\n  wakeup(b);\r\n\r\n  release(&amp;bcache.lock);\r\n}<\/pre>\n<p>\u305d\u308c\u305e\u308c\u306e\u30d5\u30e9\u30b0\u306e\u610f\u5473\u3092\u307e\u3068\u307e\u308b\u3068\u6b21\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>B_BUSY<br \/>\n\u305d\u306e\u30d0\u30c3\u30d5\u30a1\u306fbread\u3067\u8aad\u307f\u8fbc\u307e\u308c\u305f\u304c\u3001\u307e\u3060brelse\u3055\u308c\u3066\u306a\u3044\u3002<br \/>\nbread\u306f\u30c7\u30a3\u30b9\u30af\u304b\u3089\u30d0\u30c3\u30d5\u30a1\u3078\u306e\u8aad\u307f\u8fbc\u307f\u3092\u884c\u3046\u3002<br \/>\nbrelse\u306f\u30c7\u30fc\u30bf\u3092\u30d0\u30c3\u30d5\u30a1\u304b\u3089\u30ad\u30e3\u30c3\u30b7\u30e5\u3078\u79fb\u52d5\u3059\u308b\u3002<br \/>\nbio.c\u306ebget\u95a2\u6570\uff08bread\u304b\u3089\u547c\u3070\u308c\u308b\uff09\u306e\u307f\u3067\u30bb\u30c3\u30c8\u3055\u308c\u308b\u3002<\/p>\n<p>B_VALID<br \/>\n\u305d\u306e\u30d0\u30c3\u30d5\u30a1\u306f\u8aad\u307f\u8fbc\u307e\u308c\u307e\u3060\u5909\u66f4\u3055\u308c\u3066\u306a\u3044\u3002<br \/>\n\u30bb\u30c3\u30c8\u3055\u308c\u3066\u308b\u306e\u306f\u3001ide.c\u306eideintr\u95a2\u6570\u3067\u306e\u307f\u3002<\/p>\n<p>B_DIRTY<br \/>\n\u30d0\u30c3\u30d5\u30a1\u306e\u5185\u5bb9\u304c\u5909\u66f4\u3055\u308c\u305f\u306e\u3067\u66f8\u304d\u8fbc\u307f\u306e\u5fc5\u8981\u3042\u308a\u3002<br \/>\n\u30bb\u30c3\u30c8\u3055\u308c\u3066\u308b\u306e\u306f\u3001bio.c\u306ebwrite\u95a2\u6570\u3067\u306e\u307f\u3002<br \/>\n\u30ed\u30c3\u30af\u306finode\u30ec\u30d9\u30eb\u3067\u884c\u308f\u308c\u308b\u3002<\/p>\n<p>\u8ab2\u984c\u306e\u610f\u56f3\u3068\u3057\u3066\u306f\u3001bio.c\u306ebget\u95a2\u6570\u3067B_BUSY\u30d5\u30e9\u30b0\u3092\u7acb\u3066\u308b\u3068\u304d\u306fbcache.lock\u3092\u4f7f\u3063\u3066\u308b\u306e\u306b\u3001\u4ed6\u306e\u30d5\u30e9\u30b0\u3092\u7acb\u3066\u308b\u3068\u304d\u306fbcache.lock\u3092\u4f7f\u3063\u3066\u306a\u3044\u306e\u306f\u306a\u305c\uff1f\u3068\u3044\u3046\u3053\u3068\u304b\u306a\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n<p>\u307e\u305aB_VALID\u306b\u3064\u3044\u3066\u306f\u3001ide.c\u306eideintr\u95a2\u6570\u3067\u30d5\u30e9\u30b0\u3092\u7acb\u3066\u307e\u3059\u304c\u3001ideintr\u306f\u5272\u308a\u8fbc\u307f\u4e2d\u304b\u3064\u4ed6\u306e\u30ed\u30c3\u30af\uff08idelock\uff09\u3092\u7372\u5f97\u6e08\u307f\u3067\u3042\u308a\u3001\u4ed6\u3067\u30ed\u30c3\u30af\u304c\u5fc5\u8981\u306a\u64cd\u4f5c\u304c\u3055\u308c\u3066\u306a\u3044\u4e8b\u304c\u660e\u3089\u304b\u306a\u306e\u3067\u30ed\u30c3\u30af\u3059\u308b\u5fc5\u8981\u304c\u306a\u3044\u3001\u3063\u3066\u3068\u3053\u308d\u304b\u306a\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n<p>B_DIRTY\u306b\u3064\u3044\u3066\u306f\u3061\u3087\u3068\u8ffd\u3046\u306e\u304c\u96e3\u3057\u304b\u3063\u305f\u306e\u3067\u3059\u304c\u3001\u8981\u306finode\u306e\u30ec\u30d9\u30eb\u3067\u30ed\u30c3\u30af\u3092\u7372\u5f97\u6e08\u307f\u3060\u304b\u3089\u5fc5\u8981\u306a\u3044\u306e\u304b\u306a\u3068\u601d\u3044\u307e\u3059\u3002<br \/>\n\u307e\u3060\u51fa\u3066\u304d\u3066\u306a\u3044fs.c\u3092\u8aad\u3093\u3060\u3068\u3053\u308d\u3001\u30b7\u30b9\u30c6\u30e0\u30b3\u30fc\u30eb\u3092\u4f7f\u3063\u3066\u66f8\u304d\u8fbc\u3080\u5834\u5408\u3001\u8d85\u5927\u96d1\u628a\u306b\u306f<br \/>\nsys_write\u95a2\u6570\u2192filewrite\u95a2\u6570\uff08\u3053\u306e\u4e2d\u3067inode\u5358\u4f4d\u3067\u30ed\u30c3\u30af\u3092\u7372\u5f97\uff09\u2192writei\u95a2\u6570\u2192bwrite\u95a2\u6570<br \/>\n\u3068\u3044\u3046\u968e\u5c64\u95a2\u4fc2\u3067\u95a2\u6570\u304c\u547c\u3070\u308c\u307e\u3059\u3002<br \/>\n\u30d0\u30c3\u30d5\u30a1\u3092\u5185\u5305\u3059\u308binode\u5358\u4f4d\u3067\u30ed\u30c3\u30af\u3092\u7372\u5f97\u6e08\u307f\u306a\u3089\u3001\u30d0\u30c3\u30d5\u30a1\u306e\u64cd\u4f5c\u3082\u4ed6\u3068\u88ab\u308b\u3053\u3068\u304c\u306a\u3044\u304b\u3089\u6539\u3081\u3066\u30d0\u30c3\u30d5\u30a1\u5358\u4f4d\u3067\u30ed\u30c3\u30af\u3092\u7372\u5f97\u3059\u308b\u5fc5\u8981\u306f\u306a\u3044\u306e\u304b\u306a\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n<h3>\u611f\u60f3<\/h3>\n<p>\u306a\u3093\u3060\u304b\u4e0d\u5b8c\u5168\u71c3\u713c\u3067\u3059\u3002<br \/>\n\u3057\u304b\u3057\u3044\u3064\u307e\u3067\u3082\u3053\u3053\u3067\u7559\u307e\u3063\u3066\u308b\u308f\u3051\u306b\u3082\u884c\u304b\u306a\u3044\u306e\u3067\u5148\u306b\u9032\u307f\u307e\u3059\u304c\u3001\u3061\u3087\u304f\u3061\u3087\u304f\u8a66\u3057\u3066\u307f\u3066\u3068\u306b\u304b\u304f\u7af6\u5408\u72b6\u614b\u306f\u78ba\u8a8d\u3057\u305f\u3044\u306a\u3068\u601d\u3063\u3066\u307e\u3059\u3002<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[32],"tags":[405],"class_list":["post-1535","post","type-post","status-publish","format-standard","hentry","category-tech","tag-xv6"],"_links":{"self":[{"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/posts\/1535","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/comments?post=1535"}],"version-history":[{"count":0,"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/posts\/1535\/revisions"}],"wp:attachment":[{"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/media?parent=1535"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/categories?post=1535"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/tags?post=1535"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}