extern struct vfs *afs_globalVFS;
#endif
+
/* copy out attributes from cache entry */
int
afs_CopyOutAttrs(register struct vcache *avc, register struct vattr *attrs)
/* The mount point's vnode. */
if (tvp) {
attrs->va_nodeid =
- tvp->mtpoint.Fid.Vnode + (tvp->mtpoint.Fid.Volume << 16);
+ afs_calc_inum (tvp->mtpoint.Fid.Volume,
+ tvp->mtpoint.Fid.Vnode);
if (FidCmp(&afs_rootFid, &avc->fid) && !attrs->va_nodeid)
attrs->va_nodeid = 2;
afs_PutVolume(tvp, READ_LOCK);
} else
attrs->va_nodeid = 2;
} else
- attrs->va_nodeid = avc->fid.Fid.Vnode + (avc->fid.Fid.Volume << 16);
+ attrs->va_nodeid =
+ afs_calc_inum (avc->fid.Fid.Volume,
+ avc->fid.Fid.Vnode);
attrs->va_nodeid &= 0x7fffffff; /* Saber C hates negative inode #s! */
attrs->va_nlink = fakedir ? 100 : avc->m.LinkCount;
attrs->va_size = fakedir ? 4096 : avc->m.Length;
attrs->va_flags = 0;
#endif
#if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
- attrs->va_blksize = PAGESIZE; /* XXX Was 8192 XXX */
+ attrs->va_blksize = AFS_BLKSIZE; /* XXX Was 8192 XXX */
#else
- attrs->va_blocksize = PAGESIZE; /* XXX Was 8192 XXX */
+ attrs->va_blocksize = AFS_BLKSIZE; /* XXX Was 8192 XXX */
#endif
attrs->va_rdev = 1;
#if defined(AFS_HPUX110_ENV)
* Below return 0 (and not 1) blocks if the file is zero length. This conforms
* better with the other filesystems that do return 0.
*/
-#ifdef AFS_HPUX_ENV
- attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023) >> 10) : 0);
-#elif defined(AFS_SGI_ENV)
- attrs->va_blocks = BTOBB(attrs->va_size);
-#elif defined(AFS_XBSD_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
+#if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
attrs->va_bytes = (attrs->va_size ? (attrs->va_size + 1023) : 1024);
#ifdef va_bytes_rsv
attrs->va_bytes_rsv = -1;
#endif
-#else
- attrs->va_blocks =
- (attrs->va_size ? ((attrs->va_size + 1023) >> 10) << 1 : 0);
+#elif defined(AFS_HPUX_ENV)
+ attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10) : 0);
+#elif defined(AFS_SGI_ENV)
+ attrs->va_blocks = BTOBB(attrs->va_size);
+#elif defined(AFS_SUN5_ENV)
+ attrs->va_nblocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10)<<1:0);
+#else /* everything else */
+ attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10)<<1:0);
#endif
-
return 0;
}
{
afs_int32 code;
struct vrequest treq;
- extern struct unixuser *afs_FindUser();
struct unixuser *au;
int inited = 0;
OSI_VC_CONVERT(avc);
}
#endif
+ AFS_DISCON_LOCK();
+
#ifdef AFS_BOZONLOCK_ENV
afs_BozonLock(&avc->pvnLock, avc);
#endif
}
}
}
+
+ AFS_DISCON_UNLOCK();
+
if (!code)
return 0;
code = afs_CheckCode(code, &treq, 14);
#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) {
}
#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) {
}
#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) {
}
#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) {
if ((code = afs_InitReq(&treq, acred)))
return code;
+ AFS_DISCON_LOCK();
+
afs_InitFakeStat(&fakestate);
code = afs_EvalFakeStat(&avc, &fakestate, &treq);
if (code)
*/
#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) {
}
}
+ if (AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW) {
+ code = ENETDOWN;
+ goto done;
+ }
+
afs_VAttrToAS(avc, attrs, &astat); /* interpret request */
code = 0;
#ifdef AFS_BOZONLOCK_ENV
#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;
hzero(avc->flushDV);
osi_FlushText(avc); /* do this after releasing all locks */
}
- if (code == 0) {
- ObtainSharedLock(&avc->lock, 16); /* lock entry */
- code = afs_WriteVCache(avc, &astat, &treq); /* send request */
- ReleaseSharedLock(&avc->lock); /* release lock */
- }
- if (code) {
- ObtainWriteLock(&afs_xcbhash, 487);
- afs_DequeueCallback(avc);
- avc->states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- osi_dnlc_purgedp(avc);
- /* error? erase any changes we made to vcache entry */
- }
+
+ if (!AFS_IS_DISCONNECTED) {
+ if (code == 0) {
+ ObtainSharedLock(&avc->lock, 16); /* lock entry */
+ code = afs_WriteVCache(avc, &astat, &treq); /* send request */
+ ReleaseSharedLock(&avc->lock); /* release lock */
+ }
+ if (code) {
+ ObtainWriteLock(&afs_xcbhash, 487);
+ afs_DequeueCallback(avc);
+ avc->states &= ~CStatd;
+ ReleaseWriteLock(&afs_xcbhash);
+ if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
+ osi_dnlc_purgedp(avc);
+ /* error? erase any changes we made to vcache entry */
+ }
+
+#if defined(AFS_DISCON_ENV)
+ } else {
+
+ 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--;
#endif
done:
afs_PutFakeStat(&fakestate);
+
+ AFS_DISCON_UNLOCK();
code = afs_CheckCode(code, &treq, 15);
return code;
}