]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
ubik: Fix buffers for reading-during-writes
authorAndrew Deason <adeason@sinenomine.net>
Tue, 22 Jun 2010 19:36:42 +0000 (14:36 -0500)
committerDerrick Brashear <shadow@dementix.org>
Wed, 14 Dec 2011 18:52:55 +0000 (10:52 -0800)
If we are reading while a write transaction is in progress, we can
encounter a buffer that is dirty if we're on the same site as the
writer. Ignore these buffers for readers, since they contain
uncommitted changes. Then, when the writer commits, invalidate the
resultant duplicate buffer, if one exists.

Reviewed-on: http://gerrit.openafs.org/2231
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
(cherry picked from commit 570236dd55e79e8886b45f19cef59ec3fa9d53f6)

Change-Id: If83e077b99a77339377a36f1d1bac9182ef26e4f
Reviewed-on: http://gerrit.openafs.org/6260
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementix.org>
src/ubik/disk.c

index afedd2a93d3df55d80e2bebcbe7e61fe4c1b6f54..8b37195b9878282a51f1c9ffe657dc874017c8f2 100644 (file)
@@ -326,6 +326,12 @@ MatchBuffer(struct buffer *buf, int page, afs_int32 fid,
     if (buf->file != fid) {
        return 0;
     }
+    if (atrans->type == UBIK_READTRANS && buf->dirty) {
+       /* if 'buf' is dirty, it has uncommitted changes; we do not want to
+        * see uncommitted changes if we are a read transaction, so skip over
+        * it. */
+       return 0;
+    }
     if (buf->dbase != atrans->dbase) {
        return 0;
     }
@@ -624,6 +630,27 @@ DAbort(struct ubik_trans *atrans)
     return 0;
 }
 
+/**
+ * Invalidate any buffers that are duplicates of abuf. Duplicate buffers
+ * can appear if a read transaction reads a page that is dirty, then that
+ * dirty page is synced. The read transaction will skip over the dirty page,
+ * and create a new buffer, and when the dirty page is synced, it will be
+ * identical (except for contents) to the read-transaction buffer.
+ */
+static void
+DedupBuffer(struct buffer *abuf)
+{
+    struct buffer *tb;
+    for (tb = phTable[pHash(abuf->page)]; tb; tb = tb->hashNext) {
+       if (tb->page == abuf->page && tb != abuf && tb->file == abuf->file
+           && tb->dbase == abuf->dbase) {
+
+           tb->file = BADFID;
+           Dlru(tb);
+       }
+    }
+}
+
 /*!
  * \attention DSync() must only be called after DFlush(), due to its interpretation of dirty flag.
  */
@@ -644,8 +671,10 @@ DSync(struct ubik_trans *atrans)
            if (tb->dirty == 1) {
                if (file == BADFID)
                    file = tb->file;
-               if (file != BADFID && tb->file == file)
+               if (file != BADFID && tb->file == file) {
                    tb->dirty = 0;
+                   DedupBuffer(tb);
+               }
            }
        }
        if (file == BADFID)