*
*/
-#include "../afs/param.h" /* Should be always first */
-#include "../afs/sysincludes.h" /* Standard vendor system headers */
-#include "../afs/afsincludes.h" /* Afs-based standard headers */
-#include "../afs/afs_stats.h" /* statistics */
-#include "../afs/afs_cbqueue.h"
-#include "../afs/nfsclient.h"
-#include "../afs/afs_osidnlc.h"
+#include <afsconfig.h>
+#include "afs/param.h"
+
+
+#include "afs/sysincludes.h" /* Standard vendor system headers */
+#include "afsincludes.h" /* Afs-based standard headers */
+#include "afs/afs_stats.h" /* statistics */
+#include "afs/afs_cbqueue.h"
+#include "afs/nfsclient.h"
+#include "afs/afs_osidnlc.h"
extern afs_rwlock_t afs_xvcache;
extern afs_rwlock_t afs_xcbhash;
/* don't set CDirty in here because RPC is called synchronously */
-#ifdef AFS_OSF_ENV
-afs_mkdir(ndp, attrs)
- struct nameidata *ndp;
- struct vattr *attrs; {
- register struct vcache *adp = (struct vcache *)ndp->ni_dvp;
- char *aname = ndp->ni_dent.d_name;
- register struct vcache **avcp = (struct vcache **)&(ndp->ni_vp);
- struct ucred *acred = ndp->ni_cred;
-#else /* AFS_OSF_ENV */
-afs_mkdir(OSI_VC_ARG(adp), aname, attrs, avcp, acred)
- OSI_VC_DECL(adp);
- register struct vcache **avcp;
- char *aname;
- struct vattr *attrs;
- struct AFS_UCRED *acred; {
-#endif
- struct vrequest treq;
- register afs_int32 code;
- register struct conn *tc;
+int
+afs_mkdir(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
+ struct vcache **avcp, afs_ucred_t *acred)
+{
+ struct vrequest *treq = NULL;
+ afs_int32 code;
+ struct afs_conn *tc;
+ struct rx_connection *rxconn;
struct VenusFid newFid;
- register struct dcache *tdc;
- afs_int32 offset, len;
- register struct vcache *tvc;
+ struct dcache *tdc;
+ struct dcache *new_dc;
+ afs_size_t offset, len;
+ struct vcache *tvc;
struct AFSStoreStatus InStatus;
- struct AFSFetchStatus OutFidStatus, OutDirStatus;
+ struct AFSFetchStatus *OutFidStatus, *OutDirStatus;
struct AFSCallBack CallBack;
struct AFSVolSync tsync;
afs_int32 now;
- XSTATS_DECLS
- OSI_VC_CONVERT(adp)
+ struct afs_fakestat_state fakestate;
+ XSTATS_DECLS;
+ OSI_VC_CONVERT(adp);
AFS_STATCNT(afs_mkdir);
afs_Trace2(afs_iclSetp, CM_TRACE_MKDIR, ICL_TYPE_POINTER, adp,
ICL_TYPE_STRING, aname);
- if (code = afs_InitReq(&treq, acred)) return code;
+ OutFidStatus = osi_AllocSmallSpace(sizeof(struct AFSFetchStatus));
+ OutDirStatus = osi_AllocSmallSpace(sizeof(struct AFSFetchStatus));
+ memset(&InStatus, 0, sizeof(InStatus));
+
+ if ((code = afs_CreateReq(&treq, acred)))
+ goto done2;
+ afs_InitFakeStat(&fakestate);
+
+ if (strlen(aname) > AFSNAMEMAX) {
+ code = ENAMETOOLONG;
+ goto done3;
+ }
if (!afs_ENameOK(aname)) {
code = EINVAL;
- goto done;
+ goto done3;
}
- code = afs_VerifyVCache(adp, &treq);
- if (code) goto done;
+
+ AFS_DISCON_LOCK();
+
+ code = afs_EvalFakeStat(&adp, &fakestate, treq);
+ if (code)
+ goto done;
+ code = afs_VerifyVCache(adp, treq);
+ if (code)
+ goto done;
/** If the volume is read-only, return error without making an RPC to the
* fileserver
*/
- if ( adp->states & CRO ) {
- code = EROFS;
- goto done;
+ if (adp->f.states & CRO) {
+ code = EROFS;
+ goto done;
+ }
+
+ if (AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW) {
+ /*printf("Network is down in afs_mkdir\n");*/
+ code = ENETDOWN;
+ goto done;
}
-
InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE | AFS_SETGROUP;
InStatus.ClientModTime = osi_Time();
- InStatus.UnixModeBits = attrs->va_mode & 0xffff; /* only care about protection bits */
- InStatus.Group = (afs_int32)acred->cr_gid;
- tdc = afs_GetDCache(adp, 0, &treq, &offset, &len, 1);
- ObtainWriteLock(&adp->lock,153);
- do {
- tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_MAKEDIR);
- now = osi_Time();
-#ifdef RX_ENABLE_LOCKS
- AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
- code = RXAFS_MakeDir(tc->id, (struct AFSFid *) &adp->fid.Fid, aname,
- &InStatus, (struct AFSFid *) &newFid.Fid,
- &OutFidStatus, &OutDirStatus, &CallBack, &tsync);
-#ifdef RX_ENABLE_LOCKS
- AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
- XSTATS_END_TIME;
- CallBack.ExpirationTime += now;
- /* DON'T forget to Set the callback value... */
- }
- else code = -1;
- } while
- (afs_Analyze(tc, code, &adp->fid, &treq,
- AFS_STATS_FS_RPCIDX_MAKEDIR, SHARED_LOCK, (struct cell *)0));
-
- if (code) {
- if (code < 0) {
- ObtainWriteLock(&afs_xcbhash, 490);
- afs_DequeueCallback(adp);
- adp->states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
+ InStatus.UnixModeBits = attrs->va_mode & 0xffff; /* only care about protection bits */
+ InStatus.Group = (afs_int32) afs_cr_gid(acred);
+ tdc = afs_GetDCache(adp, (afs_size_t) 0, treq, &offset, &len, 1);
+ ObtainWriteLock(&adp->lock, 153);
+
+ if (!AFS_IS_DISCON_RW) {
+ do {
+ tc = afs_Conn(&adp->f.fid, treq, SHARED_LOCK, &rxconn);
+ if (tc) {
+ XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_MAKEDIR);
+ now = osi_Time();
+ RX_AFS_GUNLOCK();
+ code =
+ RXAFS_MakeDir(rxconn,
+ (struct AFSFid *)&adp->f.fid.Fid,
+ aname,
+ &InStatus,
+ (struct AFSFid *)&newFid.Fid,
+ OutFidStatus,
+ OutDirStatus,
+ &CallBack,
+ &tsync);
+ RX_AFS_GLOCK();
+ XSTATS_END_TIME;
+ CallBack.ExpirationTime += now;
+ /* DON'T forget to Set the callback value... */
+ } else
+ code = -1;
+ } while (afs_Analyze
+ (tc, rxconn, code, &adp->f.fid, treq, AFS_STATS_FS_RPCIDX_MAKEDIR,
+ SHARED_LOCK, NULL));
+
+ if (code) {
+ if (code < 0) {
+ ObtainWriteLock(&afs_xcbhash, 490);
+ afs_DequeueCallback(adp);
+ adp->f.states &= ~CStatd;
+ ReleaseWriteLock(&afs_xcbhash);
+ osi_dnlc_purgedp(adp);
+ }
+ ReleaseWriteLock(&adp->lock);
+ if (tdc)
+ afs_PutDCache(tdc);
+ goto done;
+ }
+
+ } else {
+ /* Disconnected. */
+
+ /* We have the dir entry now, we can use it while disconnected. */
+ if (adp->mvid.target_root == NULL) {
+ /* If not mount point, generate a new fid. */
+ newFid.Cell = adp->f.fid.Cell;
+ newFid.Fid.Volume = adp->f.fid.Fid.Volume;
+ afs_GenFakeFid(&newFid, VDIR, 1);
}
- ReleaseWriteLock(&adp->lock);
- if (tdc) afs_PutDCache(tdc);
- goto done;
- }
+ /* XXX: If mount point???*/
+
+ /* Operations with the actual dir's cache entry are further
+ * down, where the dir entry gets created.
+ */
+ } /* if (!AFS_IS_DISCON_RW) */
+
/* otherwise, we should see if we can make the change to the dir locally */
- if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
- /* we can do it locally */
- code = afs_dir_Create(&tdc->f.inode, aname, &newFid.Fid);
- if (code) {
+ if (tdc)
+ ObtainWriteLock(&tdc->lock, 632);
+ if (AFS_IS_DISCON_RW || afs_LocalHero(adp, tdc, OutDirStatus, 1)) {
+ /* we can do it locally */
+ ObtainWriteLock(&afs_xdcache, 294);
+ code = afs_dir_Create(tdc, aname, &newFid.Fid);
+ ReleaseWriteLock(&afs_xdcache);
+ if (code) {
ZapDCE(tdc); /* surprise error -- use invalid value */
- DZap(&tdc->f.inode);
+ DZap(tdc);
}
}
if (tdc) {
+ ReleaseWriteLock(&tdc->lock);
afs_PutDCache(tdc);
}
- adp->m.LinkCount = OutDirStatus.LinkCount;
- newFid.Cell = adp->fid.Cell;
- newFid.Fid.Volume = adp->fid.Fid.Volume;
+
+ if (AFS_IS_DISCON_RW)
+ /* We will have to settle with the local link count. */
+ adp->f.m.LinkCount++;
+ else
+ adp->f.m.LinkCount = OutDirStatus->LinkCount;
+ newFid.Cell = adp->f.fid.Cell;
+ newFid.Fid.Volume = adp->f.fid.Fid.Volume;
ReleaseWriteLock(&adp->lock);
- /* now we're done with parent dir, create the real dir's cache entry */
- tvc = afs_GetVCache(&newFid, &treq, (afs_int32 *)0, (struct vcache*)0, 0);
- if (tvc) {
- code = 0;
- *avcp = tvc;
- }
- else code = ENOENT;
-done:
-#ifdef AFS_OSF_ENV
- AFS_RELE(ndp->ni_dvp);
-#endif /* AFS_OSF_ENV */
- code = afs_CheckCode(code, &treq, 26);
+ if (AFS_IS_DISCON_RW) {
+ /* When disconnected, we have to create the full dir here. */
+
+ /* Generate a new vcache and fill it. */
+ tvc = afs_NewVCache(&newFid, NULL);
+ if (tvc) {
+ *avcp = tvc;
+ } else {
+ code = EIO;
+ goto done;
+ }
+
+ ObtainWriteLock(&tvc->lock, 738);
+ afs_GenDisconStatus(adp, tvc, &newFid, attrs, treq, VDIR);
+ ReleaseWriteLock(&tvc->lock);
+
+ /* And now make an empty dir, containing . and .. : */
+ /* Get a new dcache for it first. */
+ new_dc = afs_GetDCache(tvc, (afs_size_t) 0, treq, &offset, &len, 1);
+ if (!new_dc) {
+ /* printf("afs_mkdir: can't get new dcache for dir.\n"); */
+ code = EIO;
+ goto done;
+ }
+
+ ObtainWriteLock(&afs_xdcache, 739);
+ code = afs_dir_MakeDir(new_dc,
+ (afs_int32 *) &newFid.Fid,
+ (afs_int32 *) &adp->f.fid.Fid);
+ ReleaseWriteLock(&afs_xdcache);
+ /* if (code) printf("afs_mkdir: afs_dirMakeDir code = %u\n", code); */
+
+ afs_PutDCache(new_dc);
+
+ ObtainWriteLock(&tvc->lock, 731);
+ /* Update length in the vcache. */
+ tvc->f.m.Length = new_dc->f.chunkBytes;
+
+ afs_DisconAddDirty(tvc, VDisconCreate, 1);
+ ReleaseWriteLock(&tvc->lock);
+ } else {
+ /* now we're done with parent dir, create the real dir's cache entry */
+ tvc = afs_GetVCache(&newFid, treq, NULL, NULL);
+ if (tvc) {
+ code = 0;
+ *avcp = tvc;
+
+ } else {
+ /* For some reason, we cannot fetch the vcache for our
+ * newly-created dir. */
+ code = EIO;
+ }
+ } /* if (AFS_DISCON_RW) */
+
+ done:
+ AFS_DISCON_UNLOCK();
+ done3:
+ afs_PutFakeStat(&fakestate);
+ code = afs_CheckCode(code, treq, 26);
+ afs_DestroyReq(treq);
+ done2:
+ osi_FreeSmallSpace(OutFidStatus);
+ osi_FreeSmallSpace(OutDirStatus);
return code;
}
-#ifdef AFS_OSF_ENV
-afs_rmdir(ndp)
- struct nameidata *ndp; {
- register struct vcache *adp = (struct vcache *)ndp->ni_dvp;
- char *aname = ndp->ni_dent.d_name;
- struct ucred *acred = ndp->ni_cred;
-#else /* AFS_OSF_ENV */
+int
/* don't set CDirty in here because RPC is called synchronously */
#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
-afs_rmdir(OSI_VC_ARG(adp), aname, cdirp, acred)
- struct vnode *cdirp;
+afs_rmdir(OSI_VC_DECL(adp), char *aname, struct vnode *cdirp,
+ afs_ucred_t *acred)
#else
-afs_rmdir(adp, aname, acred)
-#endif
- OSI_VC_DECL(adp);
- char *aname;
- struct AFS_UCRED *acred; {
+afs_rmdir(OSI_VC_DECL(adp), char *aname, afs_ucred_t *acred)
#endif
- struct vrequest treq;
- register struct dcache *tdc;
- register struct vcache *tvc = (struct vcache *)0;
- register afs_int32 code;
- register struct conn *tc;
- afs_int32 offset, len;
+{
+ struct vrequest *treq = NULL;
+ struct dcache *tdc;
+ struct vcache *tvc = NULL;
+ afs_int32 code;
+ struct afs_conn *tc;
+ afs_size_t offset, len;
struct AFSFetchStatus OutDirStatus;
struct AFSVolSync tsync;
- XSTATS_DECLS
- OSI_VC_CONVERT(adp)
+ struct afs_fakestat_state fakestate;
+ struct rx_connection *rxconn;
+ XSTATS_DECLS;
+ OSI_VC_CONVERT(adp);
AFS_STATCNT(afs_rmdir);
- afs_Trace2(afs_iclSetp, CM_TRACE_RMDIR, ICL_TYPE_POINTER, adp,
+ afs_Trace2(afs_iclSetp, CM_TRACE_RMDIR, ICL_TYPE_POINTER, adp,
ICL_TYPE_STRING, aname);
- if (code = afs_InitReq(&treq, acred)) return code;
- code = afs_VerifyVCache(adp, &treq);
- if (code) goto done;
+ if ((code = afs_CreateReq(&treq, acred)))
+ goto done2;
+ afs_InitFakeStat(&fakestate);
+
+ if (strlen(aname) > AFSNAMEMAX) {
+ code = ENAMETOOLONG;
+ goto done;
+ }
+
+ AFS_DISCON_LOCK();
+
+ code = afs_EvalFakeStat(&adp, &fakestate, treq);
+ if (code)
+ goto done;
+
+ code = afs_VerifyVCache(adp, treq);
+ if (code)
+ goto done;
/** If the volume is read-only, return error without making an RPC to the
* fileserver
*/
- if ( adp->states & CRO ) {
- code = EROFS;
+ if (adp->f.states & CRO) {
+ code = EROFS;
+ goto done;
+ }
+
+ if (AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW) {
+ /* Disconnected read only mode. */
+ code = ENETDOWN;
goto done;
}
- tdc = afs_GetDCache(adp, 0, &treq, &offset, &len, 1); /* test for error below */
- ObtainWriteLock(&adp->lock,154);
- if (tdc && (adp->states & CForeign)) {
+ tdc = afs_GetDCache(adp, (afs_size_t) 0, treq, &offset, &len, 1); /* test for error below */
+ ObtainWriteLock(&adp->lock, 154);
+ if (tdc)
+ ObtainSharedLock(&tdc->lock, 633);
+ if (tdc && (adp->f.states & CForeign)) {
struct VenusFid unlinkFid;
unlinkFid.Fid.Vnode = 0;
- code = afs_dir_Lookup(&tdc->f.inode, aname, &unlinkFid.Fid);
- if (code == 0) {
- afs_int32 cached=0;
+ code = afs_dir_Lookup(tdc, aname, &unlinkFid.Fid);
+ if (code == 0) {
+ afs_int32 cached = 0;
- unlinkFid.Cell = adp->fid.Cell;
- unlinkFid.Fid.Volume = adp->fid.Fid.Volume;
+ unlinkFid.Cell = adp->f.fid.Cell;
+ unlinkFid.Fid.Volume = adp->f.fid.Fid.Volume;
if (unlinkFid.Fid.Unique == 0) {
- tvc = afs_LookupVCache(&unlinkFid, &treq, &cached,
- WRITE_LOCK, adp, aname);
+ tvc =
+ afs_LookupVCache(&unlinkFid, treq, &cached, adp, aname);
} else {
ObtainReadLock(&afs_xvcache);
- tvc = afs_FindVCache(&unlinkFid, 1, WRITE_LOCK,
- 0, 1/* do xstats */);
+ tvc = afs_FindVCache(&unlinkFid, 0, 1 /* do xstats */ );
ReleaseReadLock(&afs_xvcache);
}
}
}
- do {
- tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEDIR);
-#ifdef RX_ENABLE_LOCKS
- AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
- code = RXAFS_RemoveDir(tc->id, (struct AFSFid *) &adp->fid.Fid,
- aname, &OutDirStatus, &tsync);
-#ifdef RX_ENABLE_LOCKS
- AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
- XSTATS_END_TIME;
+ if (!AFS_IS_DISCON_RW) {
+ /* Not disconnected, can connect to server. */
+ do {
+ tc = afs_Conn(&adp->f.fid, treq, SHARED_LOCK, &rxconn);
+ if (tc) {
+ XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEDIR);
+ RX_AFS_GUNLOCK();
+ code =
+ RXAFS_RemoveDir(rxconn,
+ (struct AFSFid *)&adp->f.fid.Fid,
+ aname,
+ &OutDirStatus,
+ &tsync);
+ RX_AFS_GLOCK();
+ XSTATS_END_TIME;
+ } else
+ code = -1;
+ } while (afs_Analyze
+ (tc, rxconn, code, &adp->f.fid, treq, AFS_STATS_FS_RPCIDX_REMOVEDIR,
+ SHARED_LOCK, NULL));
+
+ if (code) {
+ if (tdc) {
+ ReleaseSharedLock(&tdc->lock);
+ afs_PutDCache(tdc);
+ }
+
+ if (code < 0) {
+ ObtainWriteLock(&afs_xcbhash, 491);
+ afs_DequeueCallback(adp);
+ adp->f.states &= ~CStatd;
+ ReleaseWriteLock(&afs_xcbhash);
+ osi_dnlc_purgedp(adp);
+ }
+ ReleaseWriteLock(&adp->lock);
+ goto done;
+ }
+
+ /* here if rpc worked; update the in-core link count */
+ adp->f.m.LinkCount = OutDirStatus.LinkCount;
+
+ } else {
+ /* Disconnected. */
+
+ if (!tdc) {
+ ReleaseWriteLock(&adp->lock);
+ /* printf("afs_rmdir: No local dcache!\n"); */
+ code = ENETDOWN;
+ goto done;
+ }
+
+ if (!tvc) {
+ /* Find the vcache. */
+ struct VenusFid tfid;
+
+ tfid.Cell = adp->f.fid.Cell;
+ tfid.Fid.Volume = adp->f.fid.Fid.Volume;
+ code = afs_dir_Lookup(tdc, aname, &tfid.Fid);
+
+ ObtainSharedLock(&afs_xvcache, 764);
+ tvc = afs_FindVCache(&tfid, 0, 1 /* do xstats */ );
+ ReleaseSharedLock(&afs_xvcache);
+
+ if (!tvc) {
+ /* printf("afs_rmdir: Can't find dir's vcache!\n"); */
+ ReleaseSharedLock(&tdc->lock);
+ afs_PutDCache(tdc); /* drop ref count */
+ ReleaseWriteLock(&adp->lock);
+ code = ENETDOWN;
+ goto done;
+ }
}
- else code = -1;
- } while
- (afs_Analyze(tc, code, &adp->fid, &treq,
- AFS_STATS_FS_RPCIDX_REMOVEDIR, SHARED_LOCK, (struct cell *)0));
-
- if (code) {
- if (tdc) afs_PutDCache(tdc);
- if (code < 0) {
- ObtainWriteLock(&afs_xcbhash, 491);
- afs_DequeueCallback(adp);
- adp->states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
+
+ if (tvc->f.m.LinkCount > 2) {
+ /* This dir contains more than . and .., thus it can't be
+ * deleted.
+ */
+ ReleaseSharedLock(&tdc->lock);
+ afs_PutDCache(tdc);
+ afs_PutVCache(tvc);
+ ReleaseWriteLock(&adp->lock);
+ code = ENOTEMPTY;
+ goto done;
}
- ReleaseWriteLock(&adp->lock);
- goto done;
- }
- /* here if rpc worked; update the in-core link count */
- adp->m.LinkCount = OutDirStatus.LinkCount;
- if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
+
+ /* Make a shadow copy of the parent dir (if not done already).
+ * If we were created locally, then we don't need to have a shadow
+ * directory (as there's no server state to remember)
+ */
+ if (!adp->f.shadow.vnode && !(adp->f.ddirty_flags & VDisconCreate)) {
+ afs_MakeShadowDir(adp, tdc);
+ }
+
+ adp->f.m.LinkCount--;
+ } /* if (!AFS_IS_DISCON_RW) */
+
+ if (tdc)
+ UpgradeSToWLock(&tdc->lock, 634);
+ if (AFS_IS_DISCON_RW || afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
/* we can do it locally */
- code = afs_dir_Delete(&tdc->f.inode, aname);
- if (code) {
+ code = afs_dir_Delete(tdc, aname);
+ if (code) {
ZapDCE(tdc); /* surprise error -- invalid value */
- DZap(&tdc->f.inode);
+ DZap(tdc);
}
}
if (tdc) {
+ ReleaseWriteLock(&tdc->lock);
afs_PutDCache(tdc); /* drop ref count */
}
+ if (tvc)
+ osi_dnlc_purgedp(tvc); /* get rid of any entries for this directory */
+ else
+ osi_dnlc_remove(adp, aname, 0);
if (tvc) {
- osi_dnlc_purgedp (tvc); /* get rid of any entries for this directory */
- afs_symhint_inval(tvc);
- } else
- osi_dnlc_remove (adp, aname, 0);
-
- if (tvc) {
- ObtainWriteLock(&tvc->lock,155);
- tvc->states &= ~CUnique; /* For the dfs xlator */
+ ObtainWriteLock(&tvc->lock, 155);
+ tvc->f.states &= ~CUnique; /* For the dfs xlator */
+ if (AFS_IS_DISCON_RW) {
+ if (tvc->f.ddirty_flags & VDisconCreate) {
+ /* If we we were created whilst disconnected, removal doesn't
+ * need to get logged. Just go away gracefully */
+ afs_DisconRemoveDirty(tvc);
+ } else {
+ afs_DisconAddDirty(tvc, VDisconRemove, 1);
+ }
+ }
ReleaseWriteLock(&tvc->lock);
- afs_PutVCache(tvc, WRITE_LOCK);
+ afs_PutVCache(tvc);
}
ReleaseWriteLock(&adp->lock);
/* don't worry about link count since dirs can not be hardlinked */
code = 0;
-done:
-#ifdef AFS_OSF_ENV
- afs_PutVCache(adp, 0);
- afs_PutVCache(ndp->ni_vp, 0);
-#endif /* AFS_OSF_ENV */
- code = afs_CheckCode(code, &treq, 27);
+ done:
+ AFS_DISCON_UNLOCK();
+ afs_PutFakeStat(&fakestate);
+ code = afs_CheckCode(code, treq, 27);
+ afs_DestroyReq(treq);
+ done2:
return code;
}