Re: Race between vmtruncate and mapped areas?

Daniel McNeil
2003-05-15T16:38:26Z

[-- Attachment #1: Type: text/plain, Size: 940 bytes --]

On Thu, 2003-05-15 at 02:40, Andrea Arcangeli wrote:
> On Thu, May 15, 2003 at 02:20:00AM -0700, Andrew Morton wrote:
> > Andrea Arcangeli <andrea@suse.de> wrote:
> > >
> > > and it's still racy
> >
> > damn, and it just booted ;)
> >
> > I'm just a little bit concerned over the ever-expanding inode. Do you
> > think the dual sequence numbers can be replaced by a single generation
> > counter?
>
> yes, I wrote it as a single counter first, but was unreadable and it had
> more branches, so I added the other sequence number to make it cleaner.
> I don't mind another 4 bytes, that cacheline should be hot anyways.

You could use the seqlock.h sequence locking. It only uses 1 sequence
counter. The 2.5 isize patch 1 has a sequence lock without the spinlock
so it only uses 4 bytes and it is somewhat more readable. I don't
think it has more branches.

I've attached the isize seqlock.h patch.
--
Daniel McNeil <daniel@osdl.org>

[-- Attachment #2: patch-2.5.69-isize.1 --]
[-- Type: text/x-patch, Size: 1603 bytes --]

diff -rupN -X /home/daniel/dontdiff linux-2.5.69/include/linux/seqlock.h linux-2.5.69-isize/include/linux/seqlock.h
--- linux-2.5.69/include/linux/seqlock.h Sun May 4 16:53:14 2003
+++ linux-2.5.69-isize/include/linux/seqlock.h Wed May 7 16:00:25 2003
@@ -94,6 +94,57 @@ static inline int read_seqretry(const se
return (iv & 1) | (sl->sequence ^ iv);
}

+
+/*
+ * Version using sequence counter only.
+ * This can be used when code has its own mutex protecting the
+ * updating starting before the write_seqcntbeqin() and ending
+ * after the write_seqcntend().
+ */
+
+typedef struct seqcnt {
+ unsigned sequence;
+} seqcnt_t;
+
+#define SEQCNT_ZERO { 0 }
+#define seqcnt_init(x) do { *(x) = (seqcnt_t) SEQCNT_ZERO; } while (0)
+
+/* Start of read using pointer to a sequence counter only. */
+static inline unsigned read_seqcntbegin(const seqcnt_t *s)
+{
+ unsigned ret = s->sequence;
+ smp_rmb();
+ return ret;
+}
+
+/* Test if reader processed invalid data.
+ * Equivalent to: iv is odd or sequence number has changed.
+ * (iv & 1) || (*s != iv)
+ * Using xor saves one conditional branch.
+ */
+static inline int read_seqcntretry(const seqcnt_t *s, unsigned iv)
+{
+ smp_rmb();
+ return (iv & 1) | (s->sequence ^ iv);
+}
+
+
+/*
+ * Sequence counter only version assumes that callers are using their
+ * own mutexing.
+ */
+static inline void write_seqcntbegin(seqcnt_t *s)
+{
+ s->sequence++;
+ smp_wmb();
+}
+
+static inline void write_seqcntend(seqcnt_t *s)
+{
+ smp_wmb();
+ s->sequence++;
+}
+
/*
* Possible sw/hw IRQ protected versions of the interfaces.
*/