static void CRTest(char *dname, char *ename, int count) { char tbuffer[200]; int i; afs_int32 fid[3]; dirhandle dir; int code; CreateDir(dname, &dir); memset(fid, 0, sizeof(fid)); afs_dir_MakeDir(&dir, fid, fid); for (i = 0; i < count; i++) { sprintf(tbuffer, "%s%d", ename, i); fid[1] = fidCounter++; fid[2] = count; code = afs_dir_Create(&dir, tbuffer, &fid); if (i % 100 == 0) { printf("#"); fflush(stdout); } if (code) { printf("code for '%s' is %d\n", tbuffer, code); return; } } DFlush(); }
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; struct dcache *tdc; struct dcache *new_dc; afs_size_t offset, len; struct vcache *tvc; struct AFSStoreStatus InStatus; struct AFSFetchStatus *OutFidStatus, *OutDirStatus; struct AFSCallBack CallBack; struct AFSVolSync tsync; afs_int32 now; 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); 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 done3; } 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->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) 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) { afs_StaleVCache(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); } /* 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 (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); } } if (tdc) { ReleaseWriteLock(&tdc->lock); afs_PutDCache(tdc); } 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); 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; }