linux-truncate-race-20090109
[openafs.git] / src / afs / VNOPS / afs_vnop_attrs.c
index 26f4dfb..58b9a00 100644 (file)
@@ -40,6 +40,7 @@ extern struct vcache *afs_globalVp;
 extern struct vfs *afs_globalVFS;
 #endif
 
+
 /* copy out attributes from cache entry */
 int
 afs_CopyOutAttrs(register struct vcache *avc, register struct vattr *attrs)
@@ -191,7 +192,6 @@ afs_getattr(OSI_VC_DECL(avc), struct vattr *attrs, struct AFS_UCRED *acred)
 {
     afs_int32 code;
     struct vrequest treq;
-    extern struct unixuser *afs_FindUser();
     struct unixuser *au;
     int inited = 0;
     OSI_VC_CONVERT(avc);
@@ -352,7 +352,7 @@ afs_VAttrToAS(register struct vcache *avc, register struct vattr *av,
 #elif  defined(AFS_AIX_ENV)
 /* Boy, was this machine dependent bogosity hard to swallow????.... */
     if (av->va_mode != -1) {
-#elif  defined(AFS_LINUX22_ENV)
+#elif  defined(AFS_LINUX22_ENV) || defined(UKERNEL)
     if (av->va_mask & ATTR_MODE) {
 #elif  defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
     if (av->va_mask & AT_MODE) {
@@ -371,7 +371,7 @@ afs_VAttrToAS(register struct vcache *avc, register struct vattr *av,
     }
 #if     defined(AFS_DARWIN80_ENV)
     if (VATTR_IS_ACTIVE(av, va_gid)) {
-#elif defined(AFS_LINUX22_ENV)
+#elif defined(AFS_LINUX22_ENV) || defined(UKERNEL)
     if (av->va_mask & ATTR_GID) {
 #elif defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
     if (av->va_mask & AT_GID) {
@@ -391,7 +391,7 @@ afs_VAttrToAS(register struct vcache *avc, register struct vattr *av,
     }
 #if     defined(AFS_DARWIN80_ENV)
     if (VATTR_IS_ACTIVE(av, va_uid)) {
-#elif defined(AFS_LINUX22_ENV)
+#elif defined(AFS_LINUX22_ENV) || defined(UKERNEL)
     if (av->va_mask & ATTR_UID) {
 #elif defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
     if (av->va_mask & AT_UID) {
@@ -411,7 +411,7 @@ afs_VAttrToAS(register struct vcache *avc, register struct vattr *av,
     }
 #if     defined(AFS_DARWIN80_ENV)
     if (VATTR_IS_ACTIVE(av, va_modify_time)) {
-#elif  defined(AFS_LINUX22_ENV)
+#elif  defined(AFS_LINUX22_ENV) || defined(UKERNEL)
     if (av->va_mask & ATTR_MTIME) {
 #elif  defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
     if (av->va_mask & AT_MTIME) {
@@ -492,7 +492,7 @@ afs_setattr(OSI_VC_DECL(avc), register struct vattr *attrs,
      */
 #if    defined(AFS_DARWIN80_ENV)
     if (VATTR_IS_ACTIVE(attrs, va_data_size)) {
-#elif  defined(AFS_LINUX22_ENV)
+#elif  defined(AFS_LINUX22_ENV) || defined(UKERNEL)
     if (attrs->va_mask & ATTR_SIZE) {
 #elif  defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
     if (attrs->va_mask & AT_SIZE) {
@@ -509,7 +509,7 @@ afs_setattr(OSI_VC_DECL(avc), register struct vattr *attrs,
        }
     }
 
-    if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
+    if (AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW) {
         code = ENETDOWN;
         goto done;
     }
@@ -530,31 +530,47 @@ afs_setattr(OSI_VC_DECL(avc), register struct vattr *attrs,
 #endif
 #if    defined(AFS_DARWIN80_ENV)
     if (VATTR_IS_ACTIVE(attrs, va_data_size)) {
-#elif  defined(AFS_LINUX22_ENV)
+#elif  defined(AFS_LINUX22_ENV) || defined(UKERNEL)
     if (attrs->va_mask & ATTR_SIZE) {
 #elif  defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
     if (attrs->va_mask & AT_SIZE) {
 #elif  defined(AFS_OSF_ENV) || defined(AFS_XBSD_ENV)
     if (attrs->va_size != VNOVAL) {
-#else
+#elif  defined(AFS_AIX41_ENV)
     if (attrs->va_size != -1) {
+#else
+    if (attrs->va_size != ~0) {
 #endif
        afs_size_t tsize = attrs->va_size;
        ObtainWriteLock(&avc->lock, 128);
        avc->states |= CDirty;
+
        code = afs_TruncateAllSegments(avc, tsize, &treq, acred);
+#ifdef AFS_LINUX_26_ENV
+       /* We must update the Linux kernel's idea of file size as soon as
+        * possible, to avoid racing with delayed writepages delivered by
+        * pdflush */
+       if (code == 0) 
+           i_size_write(AFSTOV(avc), tsize);
+#endif
        /* if date not explicitly set by this call, set it ourselves, since we
         * changed the data */
        if (!(astat.Mask & AFS_SETMODTIME)) {
            astat.Mask |= AFS_SETMODTIME;
            astat.ClientModTime = osi_Time();
        }
+
        if (code == 0) {
            if (((avc->execsOrWriters <= 0) && (avc->states & CCreating) == 0)
                || (avc->execsOrWriters == 1 && AFS_NFSXLATORREQ(acred))) {
-               code = afs_StoreAllSegments(avc, &treq, AFS_ASYNC);
-               if (!code)
-                   avc->states &= ~CDirty;
+
+               /* Store files now if not disconnected. */
+               /* XXX: AFS_IS_DISCON_RW handled. */
+               if (!AFS_IS_DISCONNECTED) {
+                       code = afs_StoreAllSegments(avc, &treq, AFS_ASYNC);
+                       if (!code)
+                               avc->states &= ~CDirty;
+               }
            }
        } else
            avc->states &= ~CDirty;
@@ -579,10 +595,17 @@ afs_setattr(OSI_VC_DECL(avc), register struct vattr *attrs,
                osi_dnlc_purgedp(avc);
            /* error?  erase any changes we made to vcache entry */
         }
+
+#if defined(AFS_DISCON_ENV)
     } else {
-        /* Must be logging - but not implemented yet ... */
-        code = ENETDOWN;
-    }
+
+       ObtainSharedLock(&avc->lock, 712);
+       /* Write changes locally. */
+       code = afs_WriteVCacheDiscon(avc, &astat, attrs);
+       ReleaseSharedLock(&avc->lock);
+#endif
+    }          /* if (!AFS_IS_DISCONNECTED) */
+
 #if    defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
     if (AFS_NFSXLATORREQ(acred)) {
        avc->execsOrWriters--;