disconnected-lseek-extension-20090126
authorSimon Wilkinson <sxw@inf.ed.ac.uk>
Mon, 26 Jan 2009 13:42:01 +0000 (13:42 +0000)
committerDerrick Brashear <shadow@dementia.org>
Mon, 26 Jan 2009 13:42:01 +0000 (13:42 +0000)
LICENSE IPL10
FIXES 124200

make extending a file by lseek make the extension-created parts as cache
chunks

src/afs/VNOPS/afs_vnop_write.c
src/afs/afs_dcache.c
src/afs/afs_prototypes.h

index 25189f8..27faba0 100644 (file)
@@ -264,6 +264,10 @@ afs_MemWrite(register struct vcache *avc, struct uio *auio, int aio,
        osi_Assert(filePos <= avc->m.Length);
 #else
        if (filePos > avc->m.Length) {
+#if AFS_DISCON_ENV
+           if (AFS_IS_DISCON_RW)
+               afs_PopulateDCache(avc, filePos, &treq);
+#endif
            afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH, ICL_TYPE_STRING,
                       __FILE__, ICL_TYPE_LONG, __LINE__, ICL_TYPE_OFFSET,
                       ICL_HANDLE_OFFSET(avc->m.Length), ICL_TYPE_OFFSET,
@@ -572,6 +576,10 @@ afs_UFSWrite(register struct vcache *avc, struct uio *auio, int aio,
        osi_Assert(filePos <= avc->m.Length);
 #else
        if (filePos > avc->m.Length) {
+# ifdef AFS_DISCON_ENV
+           if (AFS_IS_DISCON_RW)
+               afs_PopulateDCache(avc, filePos, &treq);
+# endif
            afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH, ICL_TYPE_STRING,
                       __FILE__, ICL_TYPE_LONG, __LINE__, ICL_TYPE_OFFSET,
                       ICL_HANDLE_OFFSET(avc->m.Length), ICL_TYPE_OFFSET,
index e5c760b..8f11b9e 100644 (file)
@@ -3889,4 +3889,46 @@ void afs_DeleteShadowDir(struct vcache *avc)
     QRemove(&avc->shadowq);
     ReleaseWriteLock(&afs_disconDirtyLock);
 }
+
+/*!
+ * Populate a dcache with empty chunks up to a given file size,
+ * used before extending a file in order to avoid 'holes' which
+ * we can't access in disconnected mode.
+ *
+ * \param avc   The vcache which is being extended (locked)
+ * \param alen  The new length of the file
+ *
+ */
+void afs_PopulateDCache(struct vcache *avc, afs_size_t apos, struct vrequest *areq) {
+    struct dcache *tdc;
+    afs_size_t len, offset;
+    afs_int32 start, end;
+
+    /* We're doing this to deal with the situation where we extend
+     * by writing after lseek()ing past the end of the file . If that 
+     * extension skips chunks, then those chunks won't be created, and 
+     * GetDCache will assume that they have to be fetched from the server. 
+     * So, for each chunk between the current file position, and the new 
+     * length we GetDCache for that chunk.
+     */
+
+    if (AFS_CHUNK(apos) == 0 || apos <= avc->m.Length) 
+       return;
+
+    if (avc->m.Length == 0)
+       start = 0;
+    else 
+       start = AFS_CHUNK(avc->m.Length)+1;
+
+    end = AFS_CHUNK(apos);
+
+    while (start<end) {
+       len = AFS_CHUNKTOSIZE(start);
+       tdc = afs_GetDCache(avc, AFS_CHUNKTOBASE(start), areq, &offset, &len, 4);
+       if (tdc)
+           afs_PutDCache(tdc);
+       start++;
+    }
+}
+
 #endif
index 86c5564..d333962 100644 (file)
@@ -285,7 +285,8 @@ extern struct dcache *afs_ObtainDCacheForWriting(struct vcache *avc,
                                                 afs_size_t len, 
                                                 struct vrequest *areq,
                                                 int noLock);
-
+extern void afs_PopulateDCache(struct vcache *avc, afs_size_t apos, 
+                              struct vrequest *areq);
 
 /* afs_disconnected.c */