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 extern afs_rwlock_t afs_xvcache;
29 extern afs_rwlock_t afs_xcbhash;
31 /* question: does afs_create need to set CDirty in the adp or the avc?
32 * I think we can get away without it, but I'm not sure. Note that
33 * afs_setattr is called in here for truncation.
36 afs_create(ndp, attrs)
37 struct nameidata *ndp;
38 struct vattr *attrs; {
39 register struct vcache *adp = VTOAFS(ndp->ni_dvp);
40 char *aname = ndp->ni_dent.d_name;
41 enum vcexcl aexcl = NONEXCL; /* XXX - create called properly */
42 int amode = 0; /* XXX - checked in higher level */
43 struct vcache **avcp = (struct vcache **)&(ndp->ni_vp);
44 struct ucred *acred = ndp->ni_cred;
45 #else /* AFS_OSF_ENV */
47 afs_create(OSI_VC_ARG(adp), aname, attrs, flags, amode, avcp, acred)
49 #else /* AFS_SGI64_ENV */
50 afs_create(OSI_VC_ARG(adp), aname, attrs, aexcl, amode, avcp, acred)
52 #endif /* AFS_SGI64_ENV */
58 struct AFS_UCRED *acred; {
59 #endif /* AFS_OSF_ENV */
60 afs_int32 origCBs, origZaps, finalZaps;
62 register afs_int32 code;
63 register struct conn *tc;
64 struct VenusFid newFid;
65 struct AFSStoreStatus InStatus;
66 struct AFSFetchStatus OutFidStatus, OutDirStatus;
67 struct AFSVolSync tsync;
68 struct AFSCallBack CallBack;
71 afs_size_t offset, len;
72 struct server *hostp=0;
74 struct volume* volp = 0;
75 struct afs_fakestat_state fakestate;
80 AFS_STATCNT(afs_create);
81 if (code = afs_InitReq(&treq, acred))
84 afs_Trace3(afs_iclSetp, CM_TRACE_CREATE, ICL_TYPE_POINTER, adp,
85 ICL_TYPE_STRING, aname, ICL_TYPE_INT32, amode);
87 afs_InitFakeStat(&fakestate);
90 /* If avcp is passed not null, it's the old reference to this file.
91 * We can use this to avoid create races. For now, just decrement
92 * the reference count on it.
95 AFS_RELE(AFSTOV(*avcp));
100 if (strlen(aname) > AFSNAMEMAX) {
105 if (!afs_ENameOK(aname)) {
109 #if defined(AFS_SUN5_ENV)
110 if ((attrs->va_type == VBLK) || (attrs->va_type == VCHR)) {
112 if ((attrs->va_type == VBLK) || (attrs->va_type == VCHR) || (attrs->va_type == VSOCK)) {
114 /* We don't support special devices */
118 code = afs_EvalFakeStat(&adp, &fakestate, &treq);
121 code = afs_VerifyVCache(adp, &treq);
124 /** If the volume is read-only, return error without making an RPC to the
127 if ( adp->states & CRO ) {
132 tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);
133 ObtainWriteLock(&adp->lock,135);
134 if (tdc) ObtainSharedLock(&tdc->lock,630);
137 * Make sure that the data in the cache is current. We may have
138 * received a callback while we were waiting for the write lock.
140 if (!(adp->states & CStatd)
141 || (tdc && !hsame(adp->m.DataVersion, tdc->f.versionNo))) {
142 ReleaseWriteLock(&adp->lock);
144 ReleaseSharedLock(&tdc->lock);
150 /* see if file already exists. If it does, we only set
151 * the size attributes (to handle O_TRUNC) */
152 code = afs_dir_Lookup(&tdc->f.inode, aname, &newFid.Fid); /* use dnlc first xxx */
154 ReleaseSharedLock(&tdc->lock);
156 ReleaseWriteLock(&adp->lock);
160 if (aexcl != NONEXCL) {
162 code = EEXIST; /* file exists in excl mode open */
165 /* found the file, so use it */
166 newFid.Cell = adp->fid.Cell;
167 newFid.Fid.Volume = adp->fid.Fid.Volume;
168 tvc = (struct vcache *)0;
169 if (newFid.Fid.Unique == 0) {
170 tvc = afs_LookupVCache(&newFid, &treq, (afs_int32 *)0,
171 WRITE_LOCK, adp, aname);
173 if (!tvc) /* lookup failed or wasn't called */
174 tvc = afs_GetVCache(&newFid, &treq, (afs_int32 *)0,
175 (struct vcache*)0, WRITE_LOCK);
178 /* if the thing exists, we need the right access to open it.
179 * we must check that here, since no other checks are
180 * made by the open system call */
181 len = attrs->va_size; /* only do the truncate */
183 * We used to check always for READ access before; the
184 * problem is that we will fail if the existing file
185 * has mode -w-w-w, which is wrong.
187 if ((amode & VREAD) &&
188 !afs_AccessOK(tvc, PRSFS_READ, &treq, CHECK_MODE_BITS)) {
189 afs_PutVCache(tvc, READ_LOCK);
194 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
195 if ((amode & VWRITE) || (attrs->va_mask & AT_SIZE))
197 if ((amode & VWRITE) || len != 0xffffffff)
200 /* needed for write access check */
201 tvc->parentVnode = adp->fid.Fid.Vnode;
202 tvc->parentUnique = adp->fid.Fid.Unique;
203 /* need write mode for these guys */
204 if (!afs_AccessOK(tvc, PRSFS_WRITE, &treq, CHECK_MODE_BITS)) {
205 afs_PutVCache(tvc, READ_LOCK);
210 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
211 if (attrs->va_mask & AT_SIZE)
213 if (len != 0xffffffff)
216 if (vType(tvc) != VREG) {
217 afs_PutVCache(tvc, READ_LOCK);
222 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
223 attrs->va_mask = AT_SIZE;
227 attrs->va_size = len;
228 ObtainWriteLock(&tvc->lock,136);
229 tvc->states |= CCreating;
230 ReleaseWriteLock(&tvc->lock);
231 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
232 #if defined(AFS_SGI64_ENV)
233 code = afs_setattr(VNODE_TO_FIRST_BHV((vnode_t*)tvc),
236 code = afs_setattr(tvc, attrs, 0, acred);
237 #endif /* AFS_SGI64_ENV */
238 #else /* SUN5 || SGI */
239 code = afs_setattr(tvc, attrs, acred);
240 #endif /* SUN5 || SGI */
241 ObtainWriteLock(&tvc->lock,137);
242 tvc->states &= ~CCreating;
243 ReleaseWriteLock(&tvc->lock);
245 afs_PutVCache(tvc, 0);
251 else code = ENOENT; /* shouldn't get here */
252 /* make sure vrefCount bumped only if code == 0 */
257 /* if we create the file, we don't do any access checks, since
258 * that's how O_CREAT is supposed to work */
259 if (adp->states & CForeign) {
260 origCBs = afs_allCBs;
261 origZaps = afs_allZaps;
263 origCBs = afs_evenCBs; /* if changes, we don't really have a callback */
264 origZaps = afs_evenZaps; /* number of even numbered vnodes discarded */
266 InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE | AFS_SETGROUP;
267 InStatus.ClientModTime = osi_Time();
268 InStatus.Group = (afs_int32)acred->cr_gid;
269 if (AFS_NFSXLATORREQ(acred)) {
271 * XXX The following is mainly used to fix a bug in the HP-UX
272 * nfs client where they create files with mode of 0 without
273 * doing any setattr later on to fix it. * XXX
275 #if defined(AFS_AIX_ENV)
276 if (attrs->va_mode != -1) {
278 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
279 if (attrs->va_mask & AT_MODE) {
281 if (attrs->va_mode != ((unsigned short)-1)) {
285 attrs->va_mode = 0x1b6; /* XXX default mode: rw-rw-rw XXX */
288 InStatus.UnixModeBits = attrs->va_mode & 0xffff; /* only care about protection bits */
290 tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
292 hostp = tc->srvr->server; /* remember for callback processing */
294 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_CREATEFILE);
295 #ifdef RX_ENABLE_LOCKS
297 #endif /* RX_ENABLE_LOCKS */
298 code = RXAFS_CreateFile(tc->id, (struct AFSFid *) &adp->fid.Fid,
299 aname, &InStatus, (struct AFSFid *)
300 &newFid.Fid, &OutFidStatus,
301 &OutDirStatus, &CallBack, &tsync);
302 #ifdef RX_ENABLE_LOCKS
304 #endif /* RX_ENABLE_LOCKS */
306 CallBack.ExpirationTime += now;
310 (afs_Analyze(tc, code, &adp->fid, &treq,
311 AFS_STATS_FS_RPCIDX_CREATEFILE, SHARED_LOCK, (struct cell *)0));
313 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
314 if (code == EEXIST && aexcl == NONEXCL) {
315 /* This lookup was handled in the common vn_open code in the
318 ReleaseSharedLock(&tdc->lock);
321 ReleaseWriteLock(&adp->lock);
324 #else /* AFS_OSF_ENV */
326 if (code == EEXIST && !(flags & VEXCL)) {
327 #else /* AFS_SGI64_ENV */
328 if (code == EEXIST && aexcl == NONEXCL) {
329 #endif /* AFS_SGI64_ENV */
330 /* if we get an EEXIST in nonexcl mode, just do a lookup */
332 ReleaseSharedLock(&tdc->lock);
335 ReleaseWriteLock(&adp->lock);
336 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
337 #if defined(AFS_SGI64_ENV)
338 code = afs_lookup(VNODE_TO_FIRST_BHV((vnode_t*)adp), aname, avcp,
339 (struct pathname *)0, 0,
340 (struct vnode *)0, acred);
342 code = afs_lookup(adp, aname, avcp, (struct pathname *)0, 0,
343 (struct vnode *)0, acred);
344 #endif /* AFS_SGI64_ENV */
345 #else /* SUN5 || SGI */
346 code = afs_lookup(adp, aname, avcp, acred);
347 #endif /* SUN5 || SGI */
350 #endif /* AFS_OSF_ENV */
353 ObtainWriteLock(&afs_xcbhash, 488);
354 afs_DequeueCallback(adp);
355 adp->states &= ~CStatd;
356 ReleaseWriteLock(&afs_xcbhash);
357 osi_dnlc_purgedp(adp);
359 ReleaseWriteLock(&adp->lock);
361 ReleaseSharedLock(&tdc->lock);
366 /* otherwise, we should see if we can make the change to the dir locally */
367 if (tdc) UpgradeSToWLock(&tdc->lock, 631);
368 if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
369 /* we can do it locally */
370 code = afs_dir_Create(&tdc->f.inode, aname, &newFid.Fid);
377 ReleaseWriteLock(&tdc->lock);
380 newFid.Cell = adp->fid.Cell;
381 newFid.Fid.Volume = adp->fid.Fid.Volume;
382 ReleaseWriteLock(&adp->lock);
383 volp = afs_FindVolume(&newFid, READ_LOCK);
385 /* New tricky optimistic callback handling algorithm for file creation works
386 as follows. We create the file essentially with no locks set at all. File
387 server may thus handle operations from others cache managers as well as from
388 this very own cache manager that reference the file in question before
389 we managed to create the cache entry. However, if anyone else changes
390 any of the status information for a file, we'll see afs_evenCBs increase
391 (files always have even fids). If someone on this workstation manages
392 to do something to the file, they'll end up having to create a cache
393 entry for the new file. Either we'll find it once we've got the afs_xvcache
394 lock set, or it was also *deleted* the vnode before we got there, in which case
395 we will find evenZaps has changed, too. Thus, we only assume we have the right
396 status information if no callbacks or vnode removals have occurred to even
397 numbered files from the time the call started until the time that we got the xvcache
398 lock set. Of course, this also assumes that any call that modifies a file first
399 gets a write lock on the file's vnode, but if that weren't true, the whole cache manager
400 would fail, since no call would be able to update the local vnode status after modifying
401 a file on a file server. */
402 ObtainWriteLock(&afs_xvcache,138);
403 if (adp->states & CForeign)
404 finalZaps = afs_allZaps; /* do this before calling newvcache */
406 finalZaps = afs_evenZaps; /* do this before calling newvcache */
407 /* don't need to call RemoveVCB, since only path leaving a callback is the
408 one where we pass through afs_NewVCache. Can't have queued a VCB unless
409 we created and freed an entry between file creation time and here, and the
410 freeing of the vnode will change evenZaps. Don't need to update the VLRU
411 queue, since the find will only succeed in the event of a create race, and
412 then the vcache will be at the front of the VLRU queue anyway... */
413 if (!(tvc = afs_FindVCache(&newFid, 0, WRITE_LOCK,
415 tvc = afs_NewVCache(&newFid, hostp, 0, WRITE_LOCK);
418 ObtainWriteLock(&tvc->lock,139);
420 ObtainWriteLock(&afs_xcbhash, 489);
421 finalCBs = afs_evenCBs;
422 /* add the callback in */
423 if (adp->states & CForeign) {
424 tvc->states |= CForeign;
425 finalCBs = afs_allCBs;
427 if (origCBs == finalCBs && origZaps == finalZaps) {
428 tvc->states |= CStatd; /* we've fake entire thing, so don't stat */
429 tvc->states &= ~CBulkFetching;
430 tvc->cbExpires = CallBack.ExpirationTime;
431 afs_QueueCallback(tvc, CBHash(CallBack.ExpirationTime), volp);
434 afs_DequeueCallback(tvc);
435 tvc->states &= ~(CStatd | CUnique);
437 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
438 osi_dnlc_purgedp(tvc);
440 ReleaseWriteLock(&afs_xcbhash);
441 afs_ProcessFS(tvc, &OutFidStatus, &treq);
442 ReleaseWriteLock(&tvc->lock);
449 /* otherwise cache entry already exists, someone else must
450 * have created it. Comments used to say: "don't need write
451 * lock to *clear* these flags" but we should do it anyway.
452 * Code used to clear stat bit and callback, but I don't see
453 * the point -- we didn't have a create race, somebody else just
454 * snuck into NewVCache before we got here, probably a racing
460 ReleaseWriteLock(&afs_xvcache);
464 afs_PutVolume(volp, READ_LOCK);
467 afs_AddMarinerName(aname, *avcp);
468 /* return the new status in vattr */
469 afs_CopyOutAttrs(*avcp, attrs);
473 if (!code && !strcmp(aname, "core"))
474 tvc->states |= CCore1;
477 afs_PutFakeStat(&fakestate);
478 code = afs_CheckCode(code, &treq, 20);
482 afs_PutVCache(adp, 0);
483 #endif /* AFS_OSF_ENV */
490 * Check to see if we can track the change locally: requires that
491 * we have sufficiently recent info in data cache. If so, we
492 * know the new DataVersion number, and place it correctly in both the
493 * data and stat cache entries. This routine returns 1 if we should
494 * do the operation locally, and 0 otherwise.
496 * This routine must be called with the stat cache entry write-locked,
497 * and dcache entry write-locked.
499 afs_LocalHero(avc, adc, astat, aincr)
500 register struct vcache *avc;
501 register AFSFetchStatus *astat;
502 register struct dcache *adc;
503 register int aincr; {
504 register afs_int32 ok;
507 AFS_STATCNT(afs_LocalHero);
508 hset64(avers, astat->dataVersionHigh, astat->DataVersion);
509 /* this *is* the version number, no matter what */
511 ok = (hsame(avc->m.DataVersion, adc->f.versionNo) && avc->callback
512 && (avc->states & CStatd) && avc->cbExpires >= osi_Time());
517 #if defined(AFS_SGI_ENV)
518 osi_Assert(avc->v.v_type == VDIR);
520 /* The bulk status code used the length as a sequence number. */
521 /* Don't update the vcache entry unless the stats are current. */
522 if (avc->states & CStatd) {
523 hset(avc->m.DataVersion, avers);
524 #ifdef AFS_64BIT_CLIENT
525 FillInt64(avc->m.Length, astat->Length_hi, astat->Length);
526 #else /* AFS_64BIT_ENV */
527 avc->m.Length = astat->Length;
528 #endif /* AFS_64BIT_ENV */
529 avc->m.Date = astat->ClientModTime;
532 /* we've been tracking things correctly */
533 adc->dflags |= DFEntryMod;
534 adc->f.versionNo = avers;
542 if (avc->states & CStatd) {
543 osi_dnlc_purgedp(avc);