diff --git a/wcfs/__init__.py b/wcfs/__init__.py
index d3d3f61aadef18f8ad2efa91dee67da5f57b7fb2..791996483464bd698668668bf5e1a9e351f97e1b 100644
--- a/wcfs/__init__.py
+++ b/wcfs/__init__.py
@@ -168,9 +168,11 @@ def _pinner(wconn, ctx):
                 f.pinned[req.blk] = req.at
 
 
-# mmap creates file mapping representing file data as of wconn.at database state.
+# mmap creates file mapping representing file[blk_start +blk_len) data as of wconn.at database state.
 @func(Conn)
-def mmap(wconn, foid, blk, blklen): # -> Mapping
+def mmap(wconn, foid, blk_start, blk_len): # -> Mapping
+    assert blk_len >= 0
+    blk_stop = blk_start + blk_len
     with wconn._filemu:
         f = wconn._filetab.get(foid)
         if f is None:
@@ -186,8 +188,11 @@ def mmap(wconn, foid, blk, blklen): # -> Mapping
         # XXX relock wconn -> f ?
 
         # create memory with head/f mapping and applied pins
-        mem = mm.map_ro(f.headf.fileno(), blk*f.blksize, blklen*f.blksize)
-        mmap = _Mapping(f, blk_start, mem)
+        mem = mm.map_ro(f.headf.fileno(), blk_start*f.blksize, blk_len*f.blksize)
+        mmap = _Mapping()
+        mmap.file      = f
+        mmap.blk_start = blk_start
+        mmap.mem       = mem
         for blk, rev in f.pinned.items():  # XXX keep f.pinned ↑blk and use binary search?
             if not (blk_start <= blk < blk_stop):
                 continue    # blk out of this mapping