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 "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 switch (attrs->va_type) {
105 #if !defined(AFS_SUN5_ENV)
109 /* We don't support special devices or FIFOs */
115 code = afs_EvalFakeStat(&adp, &fakestate, &treq);
118 code = afs_VerifyVCache(adp, &treq);
121 /** If the volume is read-only, return error without making an RPC to the
124 if ( adp->states & CRO ) {
129 tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);
130 ObtainWriteLock(&adp->lock,135);
131 if (tdc) ObtainSharedLock(&tdc->lock,630);
134 * Make sure that the data in the cache is current. We may have
135 * received a callback while we were waiting for the write lock.
137 if (!(adp->states & CStatd)
138 || (tdc && !hsame(adp->m.DataVersion, tdc->f.versionNo))) {
139 ReleaseWriteLock(&adp->lock);
141 ReleaseSharedLock(&tdc->lock);
147 /* see if file already exists. If it does, we only set
148 * the size attributes (to handle O_TRUNC) */
149 code = afs_dir_Lookup(&tdc->f.inode, aname, &newFid.Fid); /* use dnlc first xxx */
151 ReleaseSharedLock(&tdc->lock);
153 ReleaseWriteLock(&adp->lock);
157 if (aexcl != NONEXCL) {
159 code = EEXIST; /* file exists in excl mode open */
162 /* found the file, so use it */
163 newFid.Cell = adp->fid.Cell;
164 newFid.Fid.Volume = adp->fid.Fid.Volume;
166 if (newFid.Fid.Unique == 0) {
167 tvc = afs_LookupVCache(&newFid, &treq, NULL, adp, aname);
169 if (!tvc) /* lookup failed or wasn't called */
170 tvc = afs_GetVCache(&newFid, &treq, NULL, NULL);
173 /* if the thing exists, we need the right access to open it.
174 * we must check that here, since no other checks are
175 * made by the open system call */
176 len = attrs->va_size; /* only do the truncate */
178 * We used to check always for READ access before; the
179 * problem is that we will fail if the existing file
180 * has mode -w-w-w, which is wrong.
182 if ((amode & VREAD) &&
183 !afs_AccessOK(tvc, PRSFS_READ, &treq, CHECK_MODE_BITS)) {
189 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
190 if ((amode & VWRITE) || (attrs->va_mask & AT_SIZE))
192 if ((amode & VWRITE) || len != 0xffffffff)
195 /* needed for write access check */
196 tvc->parentVnode = adp->fid.Fid.Vnode;
197 tvc->parentUnique = adp->fid.Fid.Unique;
198 /* need write mode for these guys */
199 if (!afs_AccessOK(tvc, PRSFS_WRITE, &treq, CHECK_MODE_BITS)) {
205 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
206 if (attrs->va_mask & AT_SIZE)
208 if (len != 0xffffffff)
211 if (vType(tvc) != VREG) {
217 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
218 attrs->va_mask = AT_SIZE;
222 attrs->va_size = len;
223 ObtainWriteLock(&tvc->lock,136);
224 tvc->states |= CCreating;
225 ReleaseWriteLock(&tvc->lock);
226 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
227 #if defined(AFS_SGI64_ENV)
228 code = afs_setattr(VNODE_TO_FIRST_BHV((vnode_t*)tvc),
231 code = afs_setattr(tvc, attrs, 0, acred);
232 #endif /* AFS_SGI64_ENV */
233 #else /* SUN5 || SGI */
234 code = afs_setattr(tvc, attrs, acred);
235 #endif /* SUN5 || SGI */
236 ObtainWriteLock(&tvc->lock,137);
237 tvc->states &= ~CCreating;
238 ReleaseWriteLock(&tvc->lock);
246 else code = ENOENT; /* shouldn't get here */
247 /* make sure vrefCount bumped only if code == 0 */
252 /* if we create the file, we don't do any access checks, since
253 * that's how O_CREAT is supposed to work */
254 if (adp->states & CForeign) {
255 origCBs = afs_allCBs;
256 origZaps = afs_allZaps;
258 origCBs = afs_evenCBs; /* if changes, we don't really have a callback */
259 origZaps = afs_evenZaps; /* number of even numbered vnodes discarded */
261 InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE | AFS_SETGROUP;
262 InStatus.ClientModTime = osi_Time();
263 InStatus.Group = (afs_int32)acred->cr_gid;
264 if (AFS_NFSXLATORREQ(acred)) {
266 * XXX The following is mainly used to fix a bug in the HP-UX
267 * nfs client where they create files with mode of 0 without
268 * doing any setattr later on to fix it. * XXX
270 #if defined(AFS_AIX_ENV)
271 if (attrs->va_mode != -1) {
273 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
274 if (attrs->va_mask & AT_MODE) {
276 if (attrs->va_mode != ((unsigned short)-1)) {
280 attrs->va_mode = 0x1b6; /* XXX default mode: rw-rw-rw XXX */
283 InStatus.UnixModeBits = attrs->va_mode & 0xffff; /* only care about protection bits */
285 tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
287 hostp = tc->srvr->server; /* remember for callback processing */
289 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_CREATEFILE);
291 code = RXAFS_CreateFile(tc->id, (struct AFSFid *) &adp->fid.Fid,
292 aname, &InStatus, (struct AFSFid *)
293 &newFid.Fid, &OutFidStatus,
294 &OutDirStatus, &CallBack, &tsync);
297 CallBack.ExpirationTime += now;
301 (afs_Analyze(tc, code, &adp->fid, &treq,
302 AFS_STATS_FS_RPCIDX_CREATEFILE, SHARED_LOCK, NULL));
304 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
305 if (code == EEXIST && aexcl == NONEXCL) {
306 /* This lookup was handled in the common vn_open code in the
309 ReleaseSharedLock(&tdc->lock);
312 ReleaseWriteLock(&adp->lock);
315 #else /* AFS_OSF_ENV */
317 if (code == EEXIST && !(flags & VEXCL)) {
318 #else /* AFS_SGI64_ENV */
319 if (code == EEXIST && aexcl == NONEXCL) {
320 #endif /* AFS_SGI64_ENV */
321 /* if we get an EEXIST in nonexcl mode, just do a lookup */
323 ReleaseSharedLock(&tdc->lock);
326 ReleaseWriteLock(&adp->lock);
327 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
328 #if defined(AFS_SGI64_ENV)
329 code = afs_lookup(VNODE_TO_FIRST_BHV((vnode_t*)adp), aname, avcp,
333 code = afs_lookup(adp, aname, avcp, NULL, 0,
335 #endif /* AFS_SGI64_ENV */
336 #else /* SUN5 || SGI */
337 code = afs_lookup(adp, aname, avcp, acred);
338 #endif /* SUN5 || SGI */
341 #endif /* AFS_OSF_ENV */
344 ObtainWriteLock(&afs_xcbhash, 488);
345 afs_DequeueCallback(adp);
346 adp->states &= ~CStatd;
347 ReleaseWriteLock(&afs_xcbhash);
348 osi_dnlc_purgedp(adp);
350 ReleaseWriteLock(&adp->lock);
352 ReleaseSharedLock(&tdc->lock);
357 /* otherwise, we should see if we can make the change to the dir locally */
358 if (tdc) UpgradeSToWLock(&tdc->lock, 631);
359 if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
360 /* we can do it locally */
361 code = afs_dir_Create(&tdc->f.inode, aname, &newFid.Fid);
368 ReleaseWriteLock(&tdc->lock);
371 newFid.Cell = adp->fid.Cell;
372 newFid.Fid.Volume = adp->fid.Fid.Volume;
373 ReleaseWriteLock(&adp->lock);
374 volp = afs_FindVolume(&newFid, READ_LOCK);
376 /* New tricky optimistic callback handling algorithm for file creation works
377 as follows. We create the file essentially with no locks set at all. File
378 server may thus handle operations from others cache managers as well as from
379 this very own cache manager that reference the file in question before
380 we managed to create the cache entry. However, if anyone else changes
381 any of the status information for a file, we'll see afs_evenCBs increase
382 (files always have even fids). If someone on this workstation manages
383 to do something to the file, they'll end up having to create a cache
384 entry for the new file. Either we'll find it once we've got the afs_xvcache
385 lock set, or it was also *deleted* the vnode before we got there, in which case
386 we will find evenZaps has changed, too. Thus, we only assume we have the right
387 status information if no callbacks or vnode removals have occurred to even
388 numbered files from the time the call started until the time that we got the xvcache
389 lock set. Of course, this also assumes that any call that modifies a file first
390 gets a write lock on the file's vnode, but if that weren't true, the whole cache manager
391 would fail, since no call would be able to update the local vnode status after modifying
392 a file on a file server. */
393 ObtainWriteLock(&afs_xvcache,138);
394 if (adp->states & CForeign)
395 finalZaps = afs_allZaps; /* do this before calling newvcache */
397 finalZaps = afs_evenZaps; /* do this before calling newvcache */
398 /* don't need to call RemoveVCB, since only path leaving a callback is the
399 one where we pass through afs_NewVCache. Can't have queued a VCB unless
400 we created and freed an entry between file creation time and here, and the
401 freeing of the vnode will change evenZaps. Don't need to update the VLRU
402 queue, since the find will only succeed in the event of a create race, and
403 then the vcache will be at the front of the VLRU queue anyway... */
404 if (!(tvc = afs_FindVCache(&newFid, 0, DO_STATS))) {
405 tvc = afs_NewVCache(&newFid, hostp);
408 ObtainWriteLock(&tvc->lock,139);
410 ObtainWriteLock(&afs_xcbhash, 489);
411 finalCBs = afs_evenCBs;
412 /* add the callback in */
413 if (adp->states & CForeign) {
414 tvc->states |= CForeign;
415 finalCBs = afs_allCBs;
417 if (origCBs == finalCBs && origZaps == finalZaps) {
418 tvc->states |= CStatd; /* we've fake entire thing, so don't stat */
419 tvc->states &= ~CBulkFetching;
420 tvc->cbExpires = CallBack.ExpirationTime;
421 afs_QueueCallback(tvc, CBHash(CallBack.ExpirationTime), volp);
424 afs_DequeueCallback(tvc);
425 tvc->states &= ~(CStatd | CUnique);
427 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
428 osi_dnlc_purgedp(tvc);
430 ReleaseWriteLock(&afs_xcbhash);
431 afs_ProcessFS(tvc, &OutFidStatus, &treq);
432 ReleaseWriteLock(&tvc->lock);
439 /* otherwise cache entry already exists, someone else must
440 * have created it. Comments used to say: "don't need write
441 * lock to *clear* these flags" but we should do it anyway.
442 * Code used to clear stat bit and callback, but I don't see
443 * the point -- we didn't have a create race, somebody else just
444 * snuck into NewVCache before we got here, probably a racing
450 ReleaseWriteLock(&afs_xvcache);
454 afs_PutVolume(volp, READ_LOCK);
457 afs_AddMarinerName(aname, *avcp);
458 /* return the new status in vattr */
459 afs_CopyOutAttrs(*avcp, attrs);
463 if (!code && !strcmp(aname, "core"))
464 tvc->states |= CCore1;
467 afs_PutFakeStat(&fakestate);
468 code = afs_CheckCode(code, &treq, 20);
473 #endif /* AFS_OSF_ENV */
480 * Check to see if we can track the change locally: requires that
481 * we have sufficiently recent info in data cache. If so, we
482 * know the new DataVersion number, and place it correctly in both the
483 * data and stat cache entries. This routine returns 1 if we should
484 * do the operation locally, and 0 otherwise.
486 * This routine must be called with the stat cache entry write-locked,
487 * and dcache entry write-locked.
489 int afs_LocalHero(register struct vcache *avc, register struct dcache *adc,
490 register AFSFetchStatus *astat, register int aincr)
492 register afs_int32 ok;
495 AFS_STATCNT(afs_LocalHero);
496 hset64(avers, astat->dataVersionHigh, astat->DataVersion);
497 /* this *is* the version number, no matter what */
499 ok = (hsame(avc->m.DataVersion, adc->f.versionNo) && avc->callback
500 && (avc->states & CStatd) && avc->cbExpires >= osi_Time());
505 #if defined(AFS_SGI_ENV)
506 osi_Assert(avc->v.v_type == VDIR);
508 /* The bulk status code used the length as a sequence number. */
509 /* Don't update the vcache entry unless the stats are current. */
510 if (avc->states & CStatd) {
511 hset(avc->m.DataVersion, avers);
512 #ifdef AFS_64BIT_CLIENT
513 FillInt64(avc->m.Length, astat->Length_hi, astat->Length);
514 #else /* AFS_64BIT_ENV */
515 avc->m.Length = astat->Length;
516 #endif /* AFS_64BIT_ENV */
517 avc->m.Date = astat->ClientModTime;
520 /* we've been tracking things correctly */
521 adc->dflags |= DFEntryMod;
522 adc->f.versionNo = avers;
530 if (avc->states & CStatd) {
531 osi_dnlc_purgedp(avc);