2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
16 #include <afsconfig.h>
17 #include "../afs/param.h"
21 #include "../afs/sysincludes.h" /* Standard vendor system headers */
22 #include "../afs/afsincludes.h" /* Afs-based standard headers */
23 #include "../afs/afs_stats.h" /* statistics */
24 #include "../afs/afs_cbqueue.h"
25 #include "../afs/nfsclient.h"
26 #include "../afs/afs_osidnlc.h"
28 /* question: does afs_create need to set CDirty in the adp or the avc?
29 * I think we can get away without it, but I'm not sure. Note that
30 * afs_setattr is called in here for truncation.
33 int afs_create(struct nameidata *ndp, struct vattr *attrs)
34 #else /* AFS_OSF_ENV */
36 int afs_create(OSI_VC_DECL(adp), char *aname, struct vattr *attrs, int flags,
37 int amode, struct vcache **avcp, struct AFS_UCRED *acred)
38 #else /* AFS_SGI64_ENV */
39 int afs_create(OSI_VC_DECL(adp), char *aname, struct vattr *attrs, enum vcexcl aexcl,
40 int amode, struct vcache **avcp, struct AFS_UCRED *acred)
41 #endif /* AFS_SGI64_ENV */
42 #endif /* AFS_OSF_ENV */
45 register struct vcache *adp = VTOAFS(ndp->ni_dvp);
46 char *aname = ndp->ni_dent.d_name;
47 enum vcexcl aexcl = NONEXCL; /* XXX - create called properly */
48 int amode = 0; /* XXX - checked in higher level */
49 struct vcache **avcp = (struct vcache **)&(ndp->ni_vp);
50 struct ucred *acred = ndp->ni_cred;
53 afs_int32 origCBs, origZaps, finalZaps;
55 register afs_int32 code;
56 register struct conn *tc;
57 struct VenusFid newFid;
58 struct AFSStoreStatus InStatus;
59 struct AFSFetchStatus OutFidStatus, OutDirStatus;
60 struct AFSVolSync tsync;
61 struct AFSCallBack CallBack;
64 afs_size_t offset, len;
65 struct server *hostp=0;
67 struct volume* volp = 0;
68 struct afs_fakestat_state fakestate;
73 AFS_STATCNT(afs_create);
74 if ((code = afs_InitReq(&treq, acred)))
77 afs_Trace3(afs_iclSetp, CM_TRACE_CREATE, ICL_TYPE_POINTER, adp,
78 ICL_TYPE_STRING, aname, ICL_TYPE_INT32, amode);
80 afs_InitFakeStat(&fakestate);
83 /* If avcp is passed not null, it's the old reference to this file.
84 * We can use this to avoid create races. For now, just decrement
85 * the reference count on it.
88 AFS_RELE(AFSTOV(*avcp));
93 if (strlen(aname) > AFSNAMEMAX) {
98 if (!afs_ENameOK(aname)) {
102 #if defined(AFS_SUN5_ENV)
103 if ((attrs->va_type == VBLK) || (attrs->va_type == VCHR)) {
105 if ((attrs->va_type == VBLK) || (attrs->va_type == VCHR) || (attrs->va_type == VSOCK)) {
107 /* We don't support special devices */
111 code = afs_EvalFakeStat(&adp, &fakestate, &treq);
114 code = afs_VerifyVCache(adp, &treq);
117 /** If the volume is read-only, return error without making an RPC to the
120 if ( adp->states & CRO ) {
125 tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);
126 ObtainWriteLock(&adp->lock,135);
127 if (tdc) ObtainSharedLock(&tdc->lock,630);
130 * Make sure that the data in the cache is current. We may have
131 * received a callback while we were waiting for the write lock.
133 if (!(adp->states & CStatd)
134 || (tdc && !hsame(adp->m.DataVersion, tdc->f.versionNo))) {
135 ReleaseWriteLock(&adp->lock);
137 ReleaseSharedLock(&tdc->lock);
143 /* see if file already exists. If it does, we only set
144 * the size attributes (to handle O_TRUNC) */
145 code = afs_dir_Lookup(&tdc->f.inode, aname, &newFid.Fid); /* use dnlc first xxx */
147 ReleaseSharedLock(&tdc->lock);
149 ReleaseWriteLock(&adp->lock);
153 if (aexcl != NONEXCL) {
155 code = EEXIST; /* file exists in excl mode open */
158 /* found the file, so use it */
159 newFid.Cell = adp->fid.Cell;
160 newFid.Fid.Volume = adp->fid.Fid.Volume;
162 if (newFid.Fid.Unique == 0) {
163 tvc = afs_LookupVCache(&newFid, &treq, NULL, adp, aname);
165 if (!tvc) /* lookup failed or wasn't called */
166 tvc = afs_GetVCache(&newFid, &treq, NULL, NULL);
169 /* if the thing exists, we need the right access to open it.
170 * we must check that here, since no other checks are
171 * made by the open system call */
172 len = attrs->va_size; /* only do the truncate */
174 * We used to check always for READ access before; the
175 * problem is that we will fail if the existing file
176 * has mode -w-w-w, which is wrong.
178 if ((amode & VREAD) &&
179 !afs_AccessOK(tvc, PRSFS_READ, &treq, CHECK_MODE_BITS)) {
185 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
186 if ((amode & VWRITE) || (attrs->va_mask & AT_SIZE))
188 if ((amode & VWRITE) || len != 0xffffffff)
191 /* needed for write access check */
192 tvc->parentVnode = adp->fid.Fid.Vnode;
193 tvc->parentUnique = adp->fid.Fid.Unique;
194 /* need write mode for these guys */
195 if (!afs_AccessOK(tvc, PRSFS_WRITE, &treq, CHECK_MODE_BITS)) {
201 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
202 if (attrs->va_mask & AT_SIZE)
204 if (len != 0xffffffff)
207 if (vType(tvc) != VREG) {
213 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
214 attrs->va_mask = AT_SIZE;
218 attrs->va_size = len;
219 ObtainWriteLock(&tvc->lock,136);
220 tvc->states |= CCreating;
221 ReleaseWriteLock(&tvc->lock);
222 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
223 #if defined(AFS_SGI64_ENV)
224 code = afs_setattr(VNODE_TO_FIRST_BHV((vnode_t*)tvc),
227 code = afs_setattr(tvc, attrs, 0, acred);
228 #endif /* AFS_SGI64_ENV */
229 #else /* SUN5 || SGI */
230 code = afs_setattr(tvc, attrs, acred);
231 #endif /* SUN5 || SGI */
232 ObtainWriteLock(&tvc->lock,137);
233 tvc->states &= ~CCreating;
234 ReleaseWriteLock(&tvc->lock);
242 else code = ENOENT; /* shouldn't get here */
243 /* make sure vrefCount bumped only if code == 0 */
248 /* if we create the file, we don't do any access checks, since
249 * that's how O_CREAT is supposed to work */
250 if (adp->states & CForeign) {
251 origCBs = afs_allCBs;
252 origZaps = afs_allZaps;
254 origCBs = afs_evenCBs; /* if changes, we don't really have a callback */
255 origZaps = afs_evenZaps; /* number of even numbered vnodes discarded */
257 InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE | AFS_SETGROUP;
258 InStatus.ClientModTime = osi_Time();
259 InStatus.Group = (afs_int32)acred->cr_gid;
260 if (AFS_NFSXLATORREQ(acred)) {
262 * XXX The following is mainly used to fix a bug in the HP-UX
263 * nfs client where they create files with mode of 0 without
264 * doing any setattr later on to fix it. * XXX
266 #if defined(AFS_AIX_ENV)
267 if (attrs->va_mode != -1) {
269 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
270 if (attrs->va_mask & AT_MODE) {
272 if (attrs->va_mode != ((unsigned short)-1)) {
276 attrs->va_mode = 0x1b6; /* XXX default mode: rw-rw-rw XXX */
279 InStatus.UnixModeBits = attrs->va_mode & 0xffff; /* only care about protection bits */
281 tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
283 hostp = tc->srvr->server; /* remember for callback processing */
285 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_CREATEFILE);
287 code = RXAFS_CreateFile(tc->id, (struct AFSFid *) &adp->fid.Fid,
288 aname, &InStatus, (struct AFSFid *)
289 &newFid.Fid, &OutFidStatus,
290 &OutDirStatus, &CallBack, &tsync);
293 CallBack.ExpirationTime += now;
297 (afs_Analyze(tc, code, &adp->fid, &treq,
298 AFS_STATS_FS_RPCIDX_CREATEFILE, SHARED_LOCK, NULL));
300 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
301 if (code == EEXIST && aexcl == NONEXCL) {
302 /* This lookup was handled in the common vn_open code in the
305 ReleaseSharedLock(&tdc->lock);
308 ReleaseWriteLock(&adp->lock);
311 #else /* AFS_OSF_ENV */
313 if (code == EEXIST && !(flags & VEXCL)) {
314 #else /* AFS_SGI64_ENV */
315 if (code == EEXIST && aexcl == NONEXCL) {
316 #endif /* AFS_SGI64_ENV */
317 /* if we get an EEXIST in nonexcl mode, just do a lookup */
319 ReleaseSharedLock(&tdc->lock);
322 ReleaseWriteLock(&adp->lock);
323 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
324 #if defined(AFS_SGI64_ENV)
325 code = afs_lookup(VNODE_TO_FIRST_BHV((vnode_t*)adp), aname, avcp,
329 code = afs_lookup(adp, aname, avcp, NULL, 0,
331 #endif /* AFS_SGI64_ENV */
332 #else /* SUN5 || SGI */
333 code = afs_lookup(adp, aname, avcp, acred);
334 #endif /* SUN5 || SGI */
337 #endif /* AFS_OSF_ENV */
340 ObtainWriteLock(&afs_xcbhash, 488);
341 afs_DequeueCallback(adp);
342 adp->states &= ~CStatd;
343 ReleaseWriteLock(&afs_xcbhash);
344 osi_dnlc_purgedp(adp);
346 ReleaseWriteLock(&adp->lock);
348 ReleaseSharedLock(&tdc->lock);
353 /* otherwise, we should see if we can make the change to the dir locally */
354 if (tdc) UpgradeSToWLock(&tdc->lock, 631);
355 if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
356 /* we can do it locally */
357 code = afs_dir_Create(&tdc->f.inode, aname, &newFid.Fid);
364 ReleaseWriteLock(&tdc->lock);
367 newFid.Cell = adp->fid.Cell;
368 newFid.Fid.Volume = adp->fid.Fid.Volume;
369 ReleaseWriteLock(&adp->lock);
370 volp = afs_FindVolume(&newFid, READ_LOCK);
372 /* New tricky optimistic callback handling algorithm for file creation works
373 as follows. We create the file essentially with no locks set at all. File
374 server may thus handle operations from others cache managers as well as from
375 this very own cache manager that reference the file in question before
376 we managed to create the cache entry. However, if anyone else changes
377 any of the status information for a file, we'll see afs_evenCBs increase
378 (files always have even fids). If someone on this workstation manages
379 to do something to the file, they'll end up having to create a cache
380 entry for the new file. Either we'll find it once we've got the afs_xvcache
381 lock set, or it was also *deleted* the vnode before we got there, in which case
382 we will find evenZaps has changed, too. Thus, we only assume we have the right
383 status information if no callbacks or vnode removals have occurred to even
384 numbered files from the time the call started until the time that we got the xvcache
385 lock set. Of course, this also assumes that any call that modifies a file first
386 gets a write lock on the file's vnode, but if that weren't true, the whole cache manager
387 would fail, since no call would be able to update the local vnode status after modifying
388 a file on a file server. */
389 ObtainWriteLock(&afs_xvcache,138);
390 if (adp->states & CForeign)
391 finalZaps = afs_allZaps; /* do this before calling newvcache */
393 finalZaps = afs_evenZaps; /* do this before calling newvcache */
394 /* don't need to call RemoveVCB, since only path leaving a callback is the
395 one where we pass through afs_NewVCache. Can't have queued a VCB unless
396 we created and freed an entry between file creation time and here, and the
397 freeing of the vnode will change evenZaps. Don't need to update the VLRU
398 queue, since the find will only succeed in the event of a create race, and
399 then the vcache will be at the front of the VLRU queue anyway... */
400 if (!(tvc = afs_FindVCache(&newFid, 0, DO_STATS))) {
401 tvc = afs_NewVCache(&newFid, hostp);
404 ObtainWriteLock(&tvc->lock,139);
406 ObtainWriteLock(&afs_xcbhash, 489);
407 finalCBs = afs_evenCBs;
408 /* add the callback in */
409 if (adp->states & CForeign) {
410 tvc->states |= CForeign;
411 finalCBs = afs_allCBs;
413 if (origCBs == finalCBs && origZaps == finalZaps) {
414 tvc->states |= CStatd; /* we've fake entire thing, so don't stat */
415 tvc->states &= ~CBulkFetching;
416 tvc->cbExpires = CallBack.ExpirationTime;
417 afs_QueueCallback(tvc, CBHash(CallBack.ExpirationTime), volp);
420 afs_DequeueCallback(tvc);
421 tvc->states &= ~(CStatd | CUnique);
423 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
424 osi_dnlc_purgedp(tvc);
426 ReleaseWriteLock(&afs_xcbhash);
427 afs_ProcessFS(tvc, &OutFidStatus, &treq);
428 ReleaseWriteLock(&tvc->lock);
435 /* otherwise cache entry already exists, someone else must
436 * have created it. Comments used to say: "don't need write
437 * lock to *clear* these flags" but we should do it anyway.
438 * Code used to clear stat bit and callback, but I don't see
439 * the point -- we didn't have a create race, somebody else just
440 * snuck into NewVCache before we got here, probably a racing
446 ReleaseWriteLock(&afs_xvcache);
450 afs_PutVolume(volp, READ_LOCK);
453 afs_AddMarinerName(aname, *avcp);
454 /* return the new status in vattr */
455 afs_CopyOutAttrs(*avcp, attrs);
459 if (!code && !strcmp(aname, "core"))
460 tvc->states |= CCore1;
463 afs_PutFakeStat(&fakestate);
464 code = afs_CheckCode(code, &treq, 20);
469 #endif /* AFS_OSF_ENV */
476 * Check to see if we can track the change locally: requires that
477 * we have sufficiently recent info in data cache. If so, we
478 * know the new DataVersion number, and place it correctly in both the
479 * data and stat cache entries. This routine returns 1 if we should
480 * do the operation locally, and 0 otherwise.
482 * This routine must be called with the stat cache entry write-locked,
483 * and dcache entry write-locked.
485 int afs_LocalHero(register struct vcache *avc, register struct dcache *adc,
486 register AFSFetchStatus *astat, register int aincr)
488 register afs_int32 ok;
491 AFS_STATCNT(afs_LocalHero);
492 hset64(avers, astat->dataVersionHigh, astat->DataVersion);
493 /* this *is* the version number, no matter what */
495 ok = (hsame(avc->m.DataVersion, adc->f.versionNo) && avc->callback
496 && (avc->states & CStatd) && avc->cbExpires >= osi_Time());
501 #if defined(AFS_SGI_ENV)
502 osi_Assert(avc->v.v_type == VDIR);
504 /* The bulk status code used the length as a sequence number. */
505 /* Don't update the vcache entry unless the stats are current. */
506 if (avc->states & CStatd) {
507 hset(avc->m.DataVersion, avers);
508 #ifdef AFS_64BIT_CLIENT
509 FillInt64(avc->m.Length, astat->Length_hi, astat->Length);
510 #else /* AFS_64BIT_ENV */
511 avc->m.Length = astat->Length;
512 #endif /* AFS_64BIT_ENV */
513 avc->m.Date = astat->ClientModTime;
516 /* we've been tracking things correctly */
517 adc->dflags |= DFEntryMod;
518 adc->f.versionNo = avers;
526 if (avc->states & CStatd) {
527 osi_dnlc_purgedp(avc);