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"
22 #include "afs/sysincludes.h" /* Standard vendor system headers */
23 #include "afsincludes.h" /* Afs-based standard headers */
24 #include "afs/afs_stats.h" /* statistics */
25 #include "afs/afs_cbqueue.h"
26 #include "afs/nfsclient.h"
27 #include "afs/afs_osidnlc.h"
29 /* question: does afs_create need to set CDirty in the adp or the avc?
30 * I think we can get away without it, but I'm not sure. Note that
31 * afs_setattr is called in here for truncation.
35 afs_create(struct nameidata *ndp, struct vattr *attrs)
36 #else /* AFS_OSF_ENV */
39 afs_create(OSI_VC_DECL(adp), char *aname, struct vattr *attrs, int flags,
40 int amode, struct vcache **avcp, struct AFS_UCRED *acred)
41 #else /* AFS_SGI64_ENV */
43 afs_create(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
44 enum vcexcl aexcl, int amode, struct vcache **avcp,
45 struct AFS_UCRED *acred)
46 #endif /* AFS_SGI64_ENV */
47 #endif /* AFS_OSF_ENV */
50 register struct vcache *adp = VTOAFS(ndp->ni_dvp);
51 char *aname = ndp->ni_dent.d_name;
52 enum vcexcl aexcl = NONEXCL; /* XXX - create called properly */
53 int amode = 0; /* XXX - checked in higher level */
54 struct vcache **avcp = (struct vcache **)&(ndp->ni_vp);
55 struct ucred *acred = ndp->ni_cred;
58 afs_int32 origCBs, origZaps, finalZaps;
60 register afs_int32 code;
61 register struct conn *tc;
62 struct VenusFid newFid;
63 struct AFSStoreStatus InStatus;
64 struct AFSFetchStatus OutFidStatus, OutDirStatus;
65 struct AFSVolSync tsync;
66 struct AFSCallBack CallBack;
69 afs_size_t offset, len;
70 struct server *hostp = 0;
72 struct volume *volp = 0;
73 struct afs_fakestat_state fakestate;
74 XSTATS_DECLS OSI_VC_CONVERT(adp)
77 AFS_STATCNT(afs_create);
78 if ((code = afs_InitReq(&treq, acred)))
81 afs_Trace3(afs_iclSetp, CM_TRACE_CREATE, ICL_TYPE_POINTER, adp,
82 ICL_TYPE_STRING, aname, ICL_TYPE_INT32, amode);
84 afs_InitFakeStat(&fakestate);
87 /* If avcp is passed not null, it's the old reference to this file.
88 * We can use this to avoid create races. For now, just decrement
89 * the reference count on it.
92 AFS_RELE(AFSTOV(*avcp));
97 if (strlen(aname) > AFSNAMEMAX) {
102 if (!afs_ENameOK(aname)) {
106 switch (attrs->va_type) {
109 #if !defined(AFS_SUN5_ENV)
113 /* We don't support special devices or FIFOs */
119 code = afs_EvalFakeStat(&adp, &fakestate, &treq);
123 code = afs_VerifyVCache(adp, &treq);
127 /** If the volume is read-only, return error without making an RPC to the
130 if (adp->states & CRO) {
135 tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);
136 ObtainWriteLock(&adp->lock, 135);
138 ObtainSharedLock(&tdc->lock, 630);
141 * Make sure that the data in the cache is current. We may have
142 * received a callback while we were waiting for the write lock.
144 if (!(adp->states & CStatd)
145 || (tdc && !hsame(adp->m.DataVersion, tdc->f.versionNo))) {
146 ReleaseWriteLock(&adp->lock);
148 ReleaseSharedLock(&tdc->lock);
154 /* see if file already exists. If it does, we only set
155 * the size attributes (to handle O_TRUNC) */
156 code = afs_dir_Lookup(&tdc->f.inode, aname, &newFid.Fid); /* use dnlc first xxx */
158 ReleaseSharedLock(&tdc->lock);
160 ReleaseWriteLock(&adp->lock);
164 if (aexcl != NONEXCL) {
166 code = EEXIST; /* file exists in excl mode open */
169 /* found the file, so use it */
170 newFid.Cell = adp->fid.Cell;
171 newFid.Fid.Volume = adp->fid.Fid.Volume;
173 if (newFid.Fid.Unique == 0) {
174 tvc = afs_LookupVCache(&newFid, &treq, NULL, adp, aname);
176 if (!tvc) /* lookup failed or wasn't called */
177 tvc = afs_GetVCache(&newFid, &treq, NULL, NULL);
180 /* if the thing exists, we need the right access to open it.
181 * we must check that here, since no other checks are
182 * made by the open system call */
183 len = attrs->va_size; /* only do the truncate */
185 * We used to check always for READ access before; the
186 * problem is that we will fail if the existing file
187 * has mode -w-w-w, which is wrong.
190 && !afs_AccessOK(tvc, PRSFS_READ, &treq, CHECK_MODE_BITS)) {
195 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
196 if ((amode & VWRITE) || (attrs->va_mask & AT_SIZE))
198 if ((amode & VWRITE) || len != 0xffffffff)
201 /* needed for write access check */
202 tvc->parentVnode = adp->fid.Fid.Vnode;
203 tvc->parentUnique = adp->fid.Fid.Unique;
204 /* need write mode for these guys */
206 (tvc, PRSFS_WRITE, &treq, CHECK_MODE_BITS)) {
212 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
213 if (attrs->va_mask & AT_SIZE)
215 if (len != 0xffffffff)
218 if (vType(tvc) != VREG) {
224 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
225 attrs->va_mask = AT_SIZE;
229 attrs->va_size = len;
230 ObtainWriteLock(&tvc->lock, 136);
231 tvc->states |= CCreating;
232 ReleaseWriteLock(&tvc->lock);
233 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
234 #if defined(AFS_SGI64_ENV)
236 afs_setattr(VNODE_TO_FIRST_BHV((vnode_t *) tvc),
239 code = afs_setattr(tvc, attrs, 0, acred);
240 #endif /* AFS_SGI64_ENV */
241 #else /* SUN5 || SGI */
242 code = afs_setattr(tvc, attrs, acred);
243 #endif /* SUN5 || SGI */
244 ObtainWriteLock(&tvc->lock, 137);
245 tvc->states &= ~CCreating;
246 ReleaseWriteLock(&tvc->lock);
254 code = ENOENT; /* shouldn't get here */
255 /* make sure vrefCount bumped only if code == 0 */
260 /* if we create the file, we don't do any access checks, since
261 * that's how O_CREAT is supposed to work */
262 if (adp->states & CForeign) {
263 origCBs = afs_allCBs;
264 origZaps = afs_allZaps;
266 origCBs = afs_evenCBs; /* if changes, we don't really have a callback */
267 origZaps = afs_evenZaps; /* number of even numbered vnodes discarded */
269 InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE | AFS_SETGROUP;
270 InStatus.ClientModTime = osi_Time();
271 InStatus.Group = (afs_int32) acred->cr_gid;
272 if (AFS_NFSXLATORREQ(acred)) {
274 * XXX The following is mainly used to fix a bug in the HP-UX
275 * nfs client where they create files with mode of 0 without
276 * doing any setattr later on to fix it. * XXX
278 #if defined(AFS_AIX_ENV)
279 if (attrs->va_mode != -1) {
281 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
282 if (attrs->va_mask & AT_MODE) {
284 if (attrs->va_mode != ((unsigned short)-1)) {
288 attrs->va_mode = 0x1b6; /* XXX default mode: rw-rw-rw XXX */
291 InStatus.UnixModeBits = attrs->va_mode & 0xffff; /* only care about protection bits */
293 tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
295 hostp = tc->srvr->server; /* remember for callback processing */
297 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_CREATEFILE);
300 RXAFS_CreateFile(tc->id, (struct AFSFid *)&adp->fid.Fid,
301 aname, &InStatus, (struct AFSFid *)
302 &newFid.Fid, &OutFidStatus, &OutDirStatus,
306 CallBack.ExpirationTime += now;
310 (tc, code, &adp->fid, &treq, AFS_STATS_FS_RPCIDX_CREATEFILE,
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)
339 afs_lookup(VNODE_TO_FIRST_BHV((vnode_t *) adp), aname, avcp, NULL,
342 code = afs_lookup(adp, aname, avcp, NULL, 0, NULL, acred);
343 #endif /* AFS_SGI64_ENV */
344 #else /* SUN5 || SGI */
345 code = afs_lookup(adp, aname, avcp, acred);
346 #endif /* SUN5 || SGI */
349 #endif /* AFS_OSF_ENV */
352 ObtainWriteLock(&afs_xcbhash, 488);
353 afs_DequeueCallback(adp);
354 adp->states &= ~CStatd;
355 ReleaseWriteLock(&afs_xcbhash);
356 osi_dnlc_purgedp(adp);
358 ReleaseWriteLock(&adp->lock);
360 ReleaseSharedLock(&tdc->lock);
365 /* otherwise, we should see if we can make the change to the dir locally */
367 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, DO_STATS))) {
414 tvc = afs_NewVCache(&newFid, hostp);
417 ObtainWriteLock(&tvc->lock, 139);
419 ObtainWriteLock(&afs_xcbhash, 489);
420 finalCBs = afs_evenCBs;
421 /* add the callback in */
422 if (adp->states & CForeign) {
423 tvc->states |= CForeign;
424 finalCBs = afs_allCBs;
426 if (origCBs == finalCBs && origZaps == finalZaps) {
427 tvc->states |= CStatd; /* we've fake entire thing, so don't stat */
428 tvc->states &= ~CBulkFetching;
429 tvc->cbExpires = CallBack.ExpirationTime;
430 afs_QueueCallback(tvc, CBHash(CallBack.ExpirationTime), volp);
432 afs_DequeueCallback(tvc);
433 tvc->states &= ~(CStatd | CUnique);
435 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
436 osi_dnlc_purgedp(tvc);
438 ReleaseWriteLock(&afs_xcbhash);
439 afs_ProcessFS(tvc, &OutFidStatus, &treq);
440 ReleaseWriteLock(&tvc->lock);
446 /* otherwise cache entry already exists, someone else must
447 * have created it. Comments used to say: "don't need write
448 * lock to *clear* these flags" but we should do it anyway.
449 * Code used to clear stat bit and callback, but I don't see
450 * the point -- we didn't have a create race, somebody else just
451 * snuck into NewVCache before we got here, probably a racing
457 ReleaseWriteLock(&afs_xvcache);
461 afs_PutVolume(volp, READ_LOCK);
464 afs_AddMarinerName(aname, *avcp);
465 /* return the new status in vattr */
466 afs_CopyOutAttrs(*avcp, attrs);
469 if (!code && !strcmp(aname, "core"))
470 tvc->states |= CCore1;
473 afs_PutFakeStat(&fakestate);
474 code = afs_CheckCode(code, &treq, 20);
479 #endif /* AFS_OSF_ENV */
486 * Check to see if we can track the change locally: requires that
487 * we have sufficiently recent info in data cache. If so, we
488 * know the new DataVersion number, and place it correctly in both the
489 * data and stat cache entries. This routine returns 1 if we should
490 * do the operation locally, and 0 otherwise.
492 * This routine must be called with the stat cache entry write-locked,
493 * and dcache entry write-locked.
496 afs_LocalHero(register struct vcache *avc, register struct dcache *adc,
497 register AFSFetchStatus * astat, register int aincr)
499 register afs_int32 ok;
502 AFS_STATCNT(afs_LocalHero);
503 hset64(avers, astat->dataVersionHigh, astat->DataVersion);
504 /* this *is* the version number, no matter what */
506 ok = (hsame(avc->m.DataVersion, adc->f.versionNo) && avc->callback
507 && (avc->states & CStatd) && avc->cbExpires >= osi_Time());
511 #if defined(AFS_SGI_ENV)
512 osi_Assert(avc->v.v_type == VDIR);
514 /* The bulk status code used the length as a sequence number. */
515 /* Don't update the vcache entry unless the stats are current. */
516 if (avc->states & CStatd) {
517 hset(avc->m.DataVersion, avers);
518 #ifdef AFS_64BIT_CLIENT
519 FillInt64(avc->m.Length, astat->Length_hi, astat->Length);
520 #else /* AFS_64BIT_ENV */
521 avc->m.Length = astat->Length;
522 #endif /* AFS_64BIT_ENV */
523 avc->m.Date = astat->ClientModTime;
526 /* we've been tracking things correctly */
527 adc->dflags |= DFEntryMod;
528 adc->f.versionNo = avers;
535 if (avc->states & CStatd) {
536 osi_dnlc_purgedp(avc);