Bug Summary

File:afs/VNOPS/afs_vnop_create.c
Location:line 442, column 7
Description:Assigned value is garbage or undefined

Annotated Source Code

1/*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
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
8 */
9
10/*
11 * Implements:
12 * afs_create
13 * afs_LocalHero
14 */
15
16#include <afsconfig.h>
17#include "afs/param.h"
18
19
20#include "afs/sysincludes.h" /* Standard vendor system headers */
21#include "afsincludes.h" /* Afs-based standard headers */
22#include "afs/afs_stats.h" /* statistics */
23#include "afs/afs_cbqueue.h"
24#include "afs/nfsclient.h"
25#include "afs/afs_osidnlc.h"
26#include "afs/unified_afs.h"
27
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.
31 */
32#ifdef AFS_SGI64_ENV
33int
34afs_create(OSI_VC_DECL(adp)struct vcache *adp, char *aname, struct vattrusr_vattr *attrs, int flags,
35 int amode, struct vcache **avcp, afs_ucred_tstruct usr_ucred *acred)
36#else /* AFS_SGI64_ENV */
37int
38afs_create(OSI_VC_DECL(adp)struct vcache *adp, char *aname, struct vattrusr_vattr *attrs,
39 enum vcexclusr_vcexcl aexcl, int amode, struct vcache **avcp,
40 afs_ucred_tstruct usr_ucred *acred)
41#endif /* AFS_SGI64_ENV */
42{
43 afs_int32 origCBs, origZaps, finalZaps;
44 struct vrequest treq;
45 afs_int32 code;
46 struct afs_conn *tc;
47 struct VenusFid newFid;
48 struct AFSStoreStatus InStatus;
49 struct AFSFetchStatus OutFidStatus, OutDirStatus;
50 struct AFSVolSync tsync;
51 struct AFSCallBack CallBack;
52 afs_int32 now;
53 struct dcache *tdc;
54 afs_size_t offset, len;
55 struct server *hostp = 0;
56 struct vcache *tvc;
57 struct volume *volp = 0;
58 struct afs_fakestat_state fakestate;
59 struct rx_connection *rxconn;
60 XSTATS_DECLSstruct afs_stats_opTimingData *opP = ((void *)0); osi_timeval_t
opStartTime = { 0, 0}, opStopTime, elapsedTime
;
61 OSI_VC_CONVERT(adp);
62
63
64 AFS_STATCNT(afs_create)((afs_cmstats.callInfo.C_afs_create)++);
65 if ((code = afs_InitReq(&treq, acred)))
1
Taking false branch
66 goto done2;
67
68 afs_Trace3(afs_iclSetp, CM_TRACE_CREATE, ICL_TYPE_POINTER, adp,(((afs_iclSetp) && (afs_iclSetp->states & 2)) ?
afs_icl_Event3(afs_iclSetp, (701087825L), (1<<24)+((2)
<<18)+((4)<<12)+((7)<<6), (long)(adp), (long
)(aname), (long)(amode)) : 0)
69 ICL_TYPE_STRING, aname, ICL_TYPE_INT32, amode)(((afs_iclSetp) && (afs_iclSetp->states & 2)) ?
afs_icl_Event3(afs_iclSetp, (701087825L), (1<<24)+((2)
<<18)+((4)<<12)+((7)<<6), (long)(adp), (long
)(aname), (long)(amode)) : 0)
;
70
71 afs_InitFakeStat(&fakestate);
72
73#ifdef AFS_SGI65_ENV
74 /* If avcp is passed not null, it's the old reference to this file.
75 * We can use this to avoid create races. For now, just decrement
76 * the reference count on it.
77 */
78 if (*avcp) {
79 AFS_RELE(AFSTOV(*avcp))do { do { do { if (!(pthread_self() == afs_global_owner)) { osi_Panic
("afs global lock not held"); } } while(0); do{if (!(((&(
*avcp)->v))->v_count > 0)) AssertionFailed("/home/wollman/openafs/src/afs/VNOPS/afs_vnop_create.c"
, 79);}while(0); if (--(((&(*avcp)->v))->v_count) ==
0) afs_inactive(((struct vcache *)((&(*avcp)->v))), get_user_struct
()->u_cred); } while(0); } while (0)
;
80 *avcp = NULL((void *)0);
81 }
82#endif
83
84 if (strlen(aname) > AFSNAMEMAX256) {
2
Taking false branch
85 code = ENAMETOOLONG63;
86 goto done3;
87 }
88
89 if (!afs_ENameOK(aname)) {
3
Taking false branch
90 code = EINVAL22;
91 goto done3;
92 }
93 switch (attrs->va_type) {
4
Control jumps to the 'default' case at line 103
94 case VBLK0060000:
95 case VCHR0020000:
96#if !defined(AFS_SUN5_ENV)
97 case VSOCK0140000:
98#endif
99 case VFIFO0010000:
100 /* We don't support special devices or FIFOs */
101 code = EINVAL22;
102 goto done3;
103 default:
104 ;
105 }
106 AFS_DISCON_LOCK()do { ; if (!((&afs_discon_lock)->excl_locked & 2))
((&afs_discon_lock)->readers_reading)++; else Afs_Lock_Obtain
(&afs_discon_lock, 1); (&afs_discon_lock)->pid_last_reader
= (get_user_struct()->u_procp->p_pid ); } while (0)
;
107
108 code = afs_EvalFakeStat(&adp, &fakestate, &treq);
109 if (code)
5
Taking false branch
110 goto done;
111 tagain:
112 code = afs_VerifyVCache(adp, &treq)(((adp)->f.states & 0x00000001) ? 0 : afs_VerifyVCache2
((adp),&treq))
;
113 if (code)
6
Taking false branch
114 goto done;
115
116 /** If the volume is read-only, return error without making an RPC to the
117 * fileserver
118 */
119 if (adp->f.states & CRO0x00000004) {
7
Taking false branch
120 code = EROFS30;
121 goto done;
122 }
123
124 if (AFS_IS_DISCONNECTED(afs_is_disconnected) && !AFS_IS_DISCON_RW(afs_is_discon_rw)) {
8
Taking false branch
125 code = ENETDOWN50;
126 goto done;
127 }
128
129 tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);
130 ObtainWriteLock(&adp->lock, 135)do { ; if (!(&adp->lock)->excl_locked && !(
&adp->lock)->readers_reading) (&adp->lock) ->
excl_locked = 2; else Afs_Lock_Obtain(&adp->lock, 2);
(&adp->lock)->pid_writer = (get_user_struct()->
u_procp->p_pid ); (&adp->lock)->src_indicator = 135
; } while (0)
;
131 if (tdc)
9
Taking false branch
132 ObtainSharedLock(&tdc->lock, 630)do { ; if (!(&tdc->lock)->excl_locked) (&tdc->
lock) -> excl_locked = 4; else Afs_Lock_Obtain(&tdc->
lock, 4); (&tdc->lock)->pid_writer = (get_user_struct
()->u_procp->p_pid ); (&tdc->lock)->src_indicator
= 630; } while (0)
;
133
134 /*
135 * Make sure that the data in the cache is current. We may have
136 * received a callback while we were waiting for the write lock.
137 */
138 if (!(adp->f.states & CStatd0x00000001)
10
Taking false branch
139 || (tdc && !hsame(adp->f.m.DataVersion, tdc->f.versionNo)((adp->f.m.DataVersion).low == (tdc->f.versionNo).low &&
(adp->f.m.DataVersion).high == (tdc->f.versionNo).high
)
)) {
140 ReleaseWriteLock(&adp->lock)do { ; (&adp->lock)->excl_locked &= ~2; if ((&
adp->lock)->wait_states) Afs_Lock_ReleaseR(&adp->
lock); (&adp->lock)->pid_writer=0; } while (0)
;
141 if (tdc) {
142 ReleaseSharedLock(&tdc->lock)do { ; (&tdc->lock)->excl_locked &= ~(4 | 2); if
((&tdc->lock)->wait_states) Afs_Lock_ReleaseR(&
tdc->lock); (&tdc->lock)->pid_writer=0; } while (
0)
;
143 afs_PutDCache(tdc);
144 }
145 goto tagain;
146 }
147 if (tdc) {
11
Taking false branch
148 /* see if file already exists. If it does, we only set
149 * the size attributes (to handle O_TRUNC) */
150 code = afs_dir_Lookup(tdc, aname, &newFid.Fid); /* use dnlc first xxx */
151 if (code == 0) {
152 ReleaseSharedLock(&tdc->lock)do { ; (&tdc->lock)->excl_locked &= ~(4 | 2); if
((&tdc->lock)->wait_states) Afs_Lock_ReleaseR(&
tdc->lock); (&tdc->lock)->pid_writer=0; } while (
0)
;
153 afs_PutDCache(tdc);
154 ReleaseWriteLock(&adp->lock)do { ; (&adp->lock)->excl_locked &= ~2; if ((&
adp->lock)->wait_states) Afs_Lock_ReleaseR(&adp->
lock); (&adp->lock)->pid_writer=0; } while (0)
;
155#ifdef AFS_SGI64_ENV
156 if (flags & VEXCL) {
157#else
158 if (aexcl != NONEXCLusr_NONEXCL) {
159#endif
160 code = EEXIST17; /* file exists in excl mode open */
161 goto done;
162 }
163 /* found the file, so use it */
164 newFid.Cell = adp->f.fidusr_fid.Cell;
165 newFid.Fid.Volume = adp->f.fidusr_fid.Fid.Volume;
166 tvc = NULL((void *)0);
167 if (newFid.Fid.Unique == 0) {
168 tvc = afs_LookupVCache(&newFid, &treq, NULL((void *)0), adp, aname);
169 }
170 if (!tvc) /* lookup failed or wasn't called */
171 tvc = afs_GetVCache(&newFid, &treq, NULL((void *)0), NULL((void *)0));
172
173 if (tvc) {
174 /* if the thing exists, we need the right access to open it.
175 * we must check that here, since no other checks are
176 * made by the open system call */
177 len = attrs->va_size; /* only do the truncate */
178 /*
179 * We used to check always for READ access before; the
180 * problem is that we will fail if the existing file
181 * has mode -w-w-w, which is wrong.
182 */
183 if ((amode & VREAD00400)
184 && !afs_AccessOK(tvc, PRSFS_READ1, &treq, CHECK_MODE_BITS1)) {
185 afs_PutVCache(tvc);
186 code = EACCES13;
187 goto done;
188 }
189#if defined(AFS_DARWIN80_ENV)
190 if ((amode & VWRITE00200) || VATTR_IS_ACTIVE(attrs, va_data_size))
191#elif defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
192 if ((amode & VWRITE00200) || (attrs->va_mask & AT_SIZE))
193#else
194 if ((amode & VWRITE00200) || len != 0xffffffff)
195#endif
196 {
197 /* needed for write access check */
198 tvc->f.parent.vnodeusr_vnode = adp->f.fidusr_fid.Fid.Vnode;
199 tvc->f.parent.unique = adp->f.fidusr_fid.Fid.Unique;
200 /* need write mode for these guys */
201 if (!afs_AccessOK
202 (tvc, PRSFS_WRITE2, &treq, CHECK_MODE_BITS1)) {
203 afs_PutVCache(tvc);
204 code = EACCES13;
205 goto done;
206 }
207 }
208#if defined(AFS_DARWIN80_ENV)
209 if (VATTR_IS_ACTIVE(attrs, va_data_size))
210#elif defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
211 if (attrs->va_mask & AT_SIZE)
212#else
213 if (len != 0xffffffff)
214#endif
215 {
216 if (vType(tvc)(tvc)->v.v_type != VREG0100000) {
217 afs_PutVCache(tvc);
218 code = EISDIR21;
219 goto done;
220 }
221 /* do a truncate */
222#if defined(AFS_DARWIN80_ENV)
223 VATTR_INIT(attrs);
224 VATTR_SET_SUPPORTED(attrs, va_data_size);
225 VATTR_SET_ACTIVE(attrs, va_data_size);
226#elif defined(UKERNEL1)
227 attrs->va_mask = ATTR_SIZE(1 << 4);
228#elif defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
229 attrs->va_mask = AT_SIZE;
230#else
231 VATTR_NULLusr_vattr_null(attrs);
232#endif
233 attrs->va_size = len;
234 ObtainWriteLock(&tvc->lock, 136)do { ; if (!(&tvc->lock)->excl_locked && !(
&tvc->lock)->readers_reading) (&tvc->lock) ->
excl_locked = 2; else Afs_Lock_Obtain(&tvc->lock, 2);
(&tvc->lock)->pid_writer = (get_user_struct()->
u_procp->p_pid ); (&tvc->lock)->src_indicator = 136
; } while (0)
;
235 tvc->f.states |= CCreating0x00400000;
236 ReleaseWriteLock(&tvc->lock)do { ; (&tvc->lock)->excl_locked &= ~2; if ((&
tvc->lock)->wait_states) Afs_Lock_ReleaseR(&tvc->
lock); (&tvc->lock)->pid_writer=0; } while (0)
;
237#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
238#if defined(AFS_SGI64_ENV)
239 code =
240 afs_setattr(VNODE_TO_FIRST_BHV((vnode_t *) tvc),
241 attrs, 0, acred);
242#else
243 code = afs_setattr(tvc, attrs, 0, acred);
244#endif /* AFS_SGI64_ENV */
245#else /* SUN5 || SGI */
246 code = afs_setattr(tvc, attrs, acred);
247#endif /* SUN5 || SGI */
248 ObtainWriteLock(&tvc->lock, 137)do { ; if (!(&tvc->lock)->excl_locked && !(
&tvc->lock)->readers_reading) (&tvc->lock) ->
excl_locked = 2; else Afs_Lock_Obtain(&tvc->lock, 2);
(&tvc->lock)->pid_writer = (get_user_struct()->
u_procp->p_pid ); (&tvc->lock)->src_indicator = 137
; } while (0)
;
249 tvc->f.states &= ~CCreating0x00400000;
250 ReleaseWriteLock(&tvc->lock)do { ; (&tvc->lock)->excl_locked &= ~2; if ((&
tvc->lock)->wait_states) Afs_Lock_ReleaseR(&tvc->
lock); (&tvc->lock)->pid_writer=0; } while (0)
;
251 if (code) {
252 afs_PutVCache(tvc);
253 goto done;
254 }
255 }
256 *avcp = tvc;
257 } else
258 code = ENOENT2; /* shouldn't get here */
259 /* make sure vrefCount bumped only if code == 0 */
260 goto done;
261 }
262 }
263
264 /* if we create the file, we don't do any access checks, since
265 * that's how O_CREAT is supposed to work */
266 if (adp->f.states & CForeign0x00002000) {
12
Taking false branch
267 origCBs = afs_allCBs;
268 origZaps = afs_allZaps;
269 } else {
270 origCBs = afs_evenCBs; /* if changes, we don't really have a callback */
271 origZaps = afs_evenZaps; /* number of even numbered vnodes discarded */
272 }
273 InStatus.Mask = AFS_SETMODTIME1 | AFS_SETMODE8 | AFS_SETGROUP4;
274 InStatus.ClientModTime = osi_Time()(time(((void *)0)));
275 InStatus.Group = (afs_int32) afs_cr_gid(acred)((acred)->cr_gid);
276 if (AFS_NFSXLATORREQ(acred)(((acred)->cr_rgid) == 0xaaaa)) {
13
Taking false branch
277 /*
278 * XXX The following is mainly used to fix a bug in the HP-UX
279 * nfs client where they create files with mode of 0 without
280 * doing any setattr later on to fix it. * XXX
281 */
282#if defined(AFS_AIX_ENV)
283 if (attrs->va_mode != -1) {
284#else
285#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
286 if (attrs->va_mask & AT_MODE) {
287#else
288 if (attrs->va_mode != ((unsigned short)-1)) {
289#endif
290#endif
291 if (!attrs->va_mode)
292 attrs->va_mode = 0x1b6; /* XXX default mode: rw-rw-rw XXX */
293 }
294 }
295
296 if (!AFS_IS_DISCONNECTED(afs_is_disconnected)) {
14
Taking false branch
297 /* If not disconnected, connect to the server.*/
298
299 InStatus.UnixModeBits = attrs->va_mode & 0xffff; /* only care about protection bits */
300 do {
301 tc = afs_Conn(&adp->f.fidusr_fid, &treq, SHARED_LOCK4, &rxconn);
302 if (tc) {
303 hostp = tc->parent->srvr->server; /* remember for callback processing */
304 now = osi_Time()(time(((void *)0)));
305 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_CREATEFILE)opP = &(afs_stats_cmfullperf.rpc.fsRPCTimes[7]); osi_GetTime
(&opStartTime);
;
306 RX_AFS_GUNLOCK()do { do { if (!(pthread_self() == afs_global_owner)) { osi_Panic
("afs global lock not held"); } } while(0); memset(&afs_global_owner
, 0, sizeof(pthread_t)); do{if (!(pthread_mutex_unlock(&afs_global_lock
) == 0)) AssertionFailed("/home/wollman/openafs/src/afs/VNOPS/afs_vnop_create.c"
, 306);}while(0); } while(0)
;
307 code =
308 RXAFS_CreateFile(rxconn, (struct AFSFid *)&adp->f.fidusr_fid.Fid,
309 aname, &InStatus, (struct AFSFid *)
310 &newFid.Fid, &OutFidStatus, &OutDirStatus,
311 &CallBack, &tsync);
312 RX_AFS_GLOCK()do { do{if (!(pthread_mutex_lock(&afs_global_lock) == 0))
AssertionFailed("/home/wollman/openafs/src/afs/VNOPS/afs_vnop_create.c"
, 312);}while(0); afs_global_owner = pthread_self(); } while(
0)
;
313 XSTATS_END_TIMEosi_GetTime(&opStopTime); (opP->numOps)++; if (!code) {
(opP->numSuccesses)++; { if (opStopTime.tv_usec < opStartTime
.tv_usec) { opStopTime.tv_usec += 1000000; opStopTime.tv_sec -=
1; } elapsedTime.tv_sec = opStopTime.tv_sec - opStartTime.tv_sec
; elapsedTime.tv_usec = opStopTime.tv_usec - opStartTime.tv_usec
; }; { (opP->sumTime).tv_sec += elapsedTime.tv_sec; (opP->
sumTime).tv_usec += elapsedTime.tv_usec; if ((opP->sumTime
).tv_usec > 1000000) { (opP->sumTime).tv_usec -= 1000000
; (opP->sumTime).tv_sec++; } }; { if(elapsedTime.tv_sec >
0 ) { (opP->sqrTime).tv_sec += elapsedTime.tv_sec * elapsedTime
.tv_sec + 2 * elapsedTime.tv_sec * elapsedTime.tv_usec /1000000
; (opP->sqrTime).tv_usec += (2 * elapsedTime.tv_sec * elapsedTime
.tv_usec) % 1000000 + (elapsedTime.tv_usec / 1000)*(elapsedTime
.tv_usec / 1000) + 2 * (elapsedTime.tv_usec / 1000) * (elapsedTime
.tv_usec % 1000) / 1000 + (((elapsedTime.tv_usec % 1000) >
707) ? 1 : 0); } else { (opP->sqrTime).tv_usec += (elapsedTime
.tv_usec / 1000)*(elapsedTime.tv_usec / 1000) + 2 * (elapsedTime
.tv_usec / 1000) * (elapsedTime.tv_usec % 1000) / 1000 + (((elapsedTime
.tv_usec % 1000) > 707) ? 1 : 0); } if ((opP->sqrTime).
tv_usec > 1000000) { (opP->sqrTime).tv_usec -= 1000000;
(opP->sqrTime).tv_sec++; } }; if (((elapsedTime.tv_sec <
(opP->minTime).tv_sec) ? 1 : (elapsedTime.tv_sec > (opP
->minTime).tv_sec) ? 0 : (elapsedTime.tv_usec < (opP->
minTime).tv_usec) ? 1 : 0)) { { (opP->minTime).tv_sec = elapsedTime
.tv_sec; (opP->minTime).tv_usec = elapsedTime.tv_usec; }; }
if (((elapsedTime.tv_sec > (opP->maxTime).tv_sec) ? 1 :
(elapsedTime.tv_sec < (opP->maxTime).tv_sec) ? 0 : (elapsedTime
.tv_usec > (opP->maxTime).tv_usec) ? 1 : 0)) { { (opP->
maxTime).tv_sec = elapsedTime.tv_sec; (opP->maxTime).tv_usec
= elapsedTime.tv_usec; }; } }
;
314 CallBack.ExpirationTime += now;
315 } else
316 code = -1;
317 } while (afs_Analyze
318 (tc, rxconn, code, &adp->f.fidusr_fid, &treq, AFS_STATS_FS_RPCIDX_CREATEFILE7,
319 SHARED_LOCK4, NULL((void *)0)));
320
321 if ((code == EEXIST17 || code == UAEEXIST(49733392L)) &&
322#ifdef AFS_SGI64_ENV
323 !(flags & VEXCL)
324#else /* AFS_SGI64_ENV */
325 aexcl == NONEXCLusr_NONEXCL
326#endif
327 ) {
328 /* if we get an EEXIST in nonexcl mode, just do a lookup */
329 if (tdc) {
330 ReleaseSharedLock(&tdc->lock)do { ; (&tdc->lock)->excl_locked &= ~(4 | 2); if
((&tdc->lock)->wait_states) Afs_Lock_ReleaseR(&
tdc->lock); (&tdc->lock)->pid_writer=0; } while (
0)
;
331 afs_PutDCache(tdc);
332 }
333 ReleaseWriteLock(&adp->lock)do { ; (&adp->lock)->excl_locked &= ~2; if ((&
adp->lock)->wait_states) Afs_Lock_ReleaseR(&adp->
lock); (&adp->lock)->pid_writer=0; } while (0)
;
334
335
336#if defined(AFS_SGI64_ENV)
337 code = afs_lookup(VNODE_TO_FIRST_BHV((vnode_t *) adp), aname, avcp,
338 NULL((void *)0), 0, NULL((void *)0), acred);
339#elif defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
340 code = afs_lookup(adp, aname, avcp, NULL((void *)0), 0, NULL((void *)0), acred);
341#elif defined(UKERNEL1)
342 code = afs_lookup(adp, aname, avcp, acred, 0);
343#elif !defined(AFS_DARWIN_ENV)
344 code = afs_lookup(adp, aname, avcp, acred);
345#endif
346 goto done;
347 }
348
349 if (code) {
350 if (code < 0) {
351 ObtainWriteLock(&afs_xcbhash, 488)do { ; if (!(&afs_xcbhash)->excl_locked && !(&
afs_xcbhash)->readers_reading) (&afs_xcbhash) -> excl_locked
= 2; else Afs_Lock_Obtain(&afs_xcbhash, 2); (&afs_xcbhash
)->pid_writer = (get_user_struct()->u_procp->p_pid )
; (&afs_xcbhash)->src_indicator = 488; } while (0)
;
352 afs_DequeueCallback(adp);
353 adp->f.states &= ~CStatd0x00000001;
354 ReleaseWriteLock(&afs_xcbhash)do { ; (&afs_xcbhash)->excl_locked &= ~2; if ((&
afs_xcbhash)->wait_states) Afs_Lock_ReleaseR(&afs_xcbhash
); (&afs_xcbhash)->pid_writer=0; } while (0)
;
355 osi_dnlc_purgedp(adp);
356 }
357 ReleaseWriteLock(&adp->lock)do { ; (&adp->lock)->excl_locked &= ~2; if ((&
adp->lock)->wait_states) Afs_Lock_ReleaseR(&adp->
lock); (&adp->lock)->pid_writer=0; } while (0)
;
358 if (tdc) {
359 ReleaseSharedLock(&tdc->lock)do { ; (&tdc->lock)->excl_locked &= ~(4 | 2); if
((&tdc->lock)->wait_states) Afs_Lock_ReleaseR(&
tdc->lock); (&tdc->lock)->pid_writer=0; } while (
0)
;
360 afs_PutDCache(tdc);
361 }
362 goto done;
363 }
364
365 } else {
366 /* Generate a fake FID for disconnected mode. */
367 newFid.Cell = adp->f.fidusr_fid.Cell;
368 newFid.Fid.Volume = adp->f.fidusr_fid.Fid.Volume;
369 afs_GenFakeFid(&newFid, VREG0100000, 1);
370 } /* if (!AFS_IS_DISCON_RW) */
371
372 /* otherwise, we should see if we can make the change to the dir locally */
373 if (tdc)
15
Taking false branch
374 UpgradeSToWLock(&tdc->lock, 631)do { ; if (!(&tdc->lock)->readers_reading) (&tdc
->lock)->excl_locked = 2; else Afs_Lock_Obtain(&tdc
->lock, 6); (&tdc->lock)->pid_writer = (get_user_struct
()->u_procp->p_pid ); (&tdc->lock)->src_indicator
= 631; } while (0)
;
375 if (AFS_IS_DISCON_RW(afs_is_discon_rw) || afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
16
Taking false branch
376 /* we can do it locally */
377 ObtainWriteLock(&afs_xdcache, 291)do { ; if (!(&afs_xdcache)->excl_locked && !(&
afs_xdcache)->readers_reading) (&afs_xdcache) -> excl_locked
= 2; else Afs_Lock_Obtain(&afs_xdcache, 2); (&afs_xdcache
)->pid_writer = (get_user_struct()->u_procp->p_pid )
; (&afs_xdcache)->src_indicator = 291; } while (0)
;
378 code = afs_dir_Create(tdc, aname, &newFid.Fid);
379 ReleaseWriteLock(&afs_xdcache)do { ; (&afs_xdcache)->excl_locked &= ~2; if ((&
afs_xdcache)->wait_states) Afs_Lock_ReleaseR(&afs_xdcache
); (&afs_xdcache)->pid_writer=0; } while (0)
;
380 if (code) {
381 ZapDCE(tdc)do { (tdc)->f.usr_fid.Fid.Unique = 0; afs_indexUnique[(tdc
)->index] = 0; (tdc)->dflags |= 0x02; } while(0)
;
382 DZap(tdc);
383 }
384 }
385 if (tdc) {
17
Taking false branch
386 ReleaseWriteLock(&tdc->lock)do { ; (&tdc->lock)->excl_locked &= ~2; if ((&
tdc->lock)->wait_states) Afs_Lock_ReleaseR(&tdc->
lock); (&tdc->lock)->pid_writer=0; } while (0)
;
387 afs_PutDCache(tdc);
388 }
389 if (AFS_IS_DISCON_RW(afs_is_discon_rw))
18
Taking false branch
390 adp->f.m.LinkCount++;
391
392 newFid.Cell = adp->f.fidusr_fid.Cell;
393 newFid.Fid.Volume = adp->f.fidusr_fid.Fid.Volume;
394 ReleaseWriteLock(&adp->lock)do { ; (&adp->lock)->excl_locked &= ~2; if ((&
adp->lock)->wait_states) Afs_Lock_ReleaseR(&adp->
lock); (&adp->lock)->pid_writer=0; } while (0)
;
395 volp = afs_FindVolume(&newFid, READ_LOCK1);
396
397 /* New tricky optimistic callback handling algorithm for file creation works
398 * as follows. We create the file essentially with no locks set at all. File
399 * server may thus handle operations from others cache managers as well as from
400 * this very own cache manager that reference the file in question before
401 * we managed to create the cache entry. However, if anyone else changes
402 * any of the status information for a file, we'll see afs_evenCBs increase
403 * (files always have even fids). If someone on this workstation manages
404 * to do something to the file, they'll end up having to create a cache
405 * entry for the new file. Either we'll find it once we've got the afs_xvcache
406 * lock set, or it was also *deleted* the vnode before we got there, in which case
407 * we will find evenZaps has changed, too. Thus, we only assume we have the right
408 * status information if no callbacks or vnode removals have occurred to even
409 * numbered files from the time the call started until the time that we got the xvcache
410 * lock set. Of course, this also assumes that any call that modifies a file first
411 * gets a write lock on the file's vnode, but if that weren't true, the whole cache manager
412 * would fail, since no call would be able to update the local vnode status after modifying
413 * a file on a file server. */
414 ObtainWriteLock(&afs_xvcache, 138)do { ; if (!(&afs_xvcache)->excl_locked && !(&
afs_xvcache)->readers_reading) (&afs_xvcache) -> excl_locked
= 2; else Afs_Lock_Obtain(&afs_xvcache, 2); (&afs_xvcache
)->pid_writer = (get_user_struct()->u_procp->p_pid )
; (&afs_xvcache)->src_indicator = 138; } while (0)
;
415 if (adp->f.states & CForeign0x00002000)
19
Taking false branch
416 finalZaps = afs_allZaps; /* do this before calling newvcache */
417 else
418 finalZaps = afs_evenZaps; /* do this before calling newvcache */
419 /* don't need to call RemoveVCB, since only path leaving a callback is the
420 * one where we pass through afs_NewVCache. Can't have queued a VCB unless
421 * we created and freed an entry between file creation time and here, and the
422 * freeing of the vnode will change evenZaps. Don't need to update the VLRU
423 * queue, since the find will only succeed in the event of a create race, and
424 * then the vcache will be at the front of the VLRU queue anyway... */
425 if (!(tvc = afs_FindVCache(&newFid, 0, DO_STATS1))) {
20
Taking true branch
426 tvc = afs_NewVCache(&newFid, hostp);
427 if (tvc) {
21
Taking true branch
428 int finalCBs;
429 ObtainWriteLock(&tvc->lock, 139)do { ; if (!(&tvc->lock)->excl_locked && !(
&tvc->lock)->readers_reading) (&tvc->lock) ->
excl_locked = 2; else Afs_Lock_Obtain(&tvc->lock, 2);
(&tvc->lock)->pid_writer = (get_user_struct()->
u_procp->p_pid ); (&tvc->lock)->src_indicator = 139
; } while (0)
;
430
431 ObtainWriteLock(&afs_xcbhash, 489)do { ; if (!(&afs_xcbhash)->excl_locked && !(&
afs_xcbhash)->readers_reading) (&afs_xcbhash) -> excl_locked
= 2; else Afs_Lock_Obtain(&afs_xcbhash, 2); (&afs_xcbhash
)->pid_writer = (get_user_struct()->u_procp->p_pid )
; (&afs_xcbhash)->src_indicator = 489; } while (0)
;
432 finalCBs = afs_evenCBs;
433 /* add the callback in */
434 if (adp->f.states & CForeign0x00002000) {
22
Taking false branch
435 tvc->f.states |= CForeign0x00002000;
436 finalCBs = afs_allCBs;
437 }
438 if (origCBs == finalCBs && origZaps == finalZaps) {
23
Taking true branch
439 tvc->f.states |= CStatd0x00000001; /* we've fake entire thing, so don't stat */
440 tvc->f.states &= ~CBulkFetching0x04000000;
441 if (!AFS_IS_DISCON_RW(afs_is_discon_rw)) {
24
Taking true branch
442 tvc->cbExpires = CallBack.ExpirationTime;
25
Assigned value is garbage or undefined
443 afs_QueueCallback(tvc, CBHash(CallBack.ExpirationTime)((CallBack.ExpirationTime)>>7), volp);
444 }
445 } else {
446 afs_DequeueCallback(tvc);
447 tvc->f.states &= ~(CStatd0x00000001 | CUnique0x00001000);
448 tvc->callback = 0;
449 if (tvc->f.fidusr_fid.Fid.Vnode & 1 || (vType(tvc)(tvc)->v.v_type == VDIR0040000))
450 osi_dnlc_purgedp(tvc);
451 }
452 ReleaseWriteLock(&afs_xcbhash)do { ; (&afs_xcbhash)->excl_locked &= ~2; if ((&
afs_xcbhash)->wait_states) Afs_Lock_ReleaseR(&afs_xcbhash
); (&afs_xcbhash)->pid_writer=0; } while (0)
;
453 if (AFS_IS_DISCON_RW(afs_is_discon_rw)) {
454 afs_DisconAddDirty(tvc, VDisconCreate0x00004000, 0);
455 afs_GenDisconStatus(adp, tvc, &newFid, attrs, &treq, VREG0100000);
456 } else {
457 afs_ProcessFS(tvc, &OutFidStatus, &treq);
458 }
459
460 tvc->f.parent.vnodeusr_vnode = adp->f.fidusr_fid.Fid.Vnode;
461 tvc->f.parent.unique = adp->f.fidusr_fid.Fid.Unique;
462 ReleaseWriteLock(&tvc->lock)do { ; (&tvc->lock)->excl_locked &= ~2; if ((&
tvc->lock)->wait_states) Afs_Lock_ReleaseR(&tvc->
lock); (&tvc->lock)->pid_writer=0; } while (0)
;
463 *avcp = tvc;
464 code = 0;
465 } else
466 code = ENOENT2;
467 } else {
468 /* otherwise cache entry already exists, someone else must
469 * have created it. Comments used to say: "don't need write
470 * lock to *clear* these flags" but we should do it anyway.
471 * Code used to clear stat bit and callback, but I don't see
472 * the point -- we didn't have a create race, somebody else just
473 * snuck into NewVCache before we got here, probably a racing
474 * lookup.
475 */
476 *avcp = tvc;
477 code = 0;
478 }
479 ReleaseWriteLock(&afs_xvcache)do { ; (&afs_xvcache)->excl_locked &= ~2; if ((&
afs_xvcache)->wait_states) Afs_Lock_ReleaseR(&afs_xvcache
); (&afs_xvcache)->pid_writer=0; } while (0)
;
480
481 done:
482 AFS_DISCON_UNLOCK()do { ; if (!(--((&afs_discon_lock)->readers_reading)) &&
(&afs_discon_lock)->wait_states) Afs_Lock_ReleaseW(&
afs_discon_lock) ; if ( (&afs_discon_lock)->pid_last_reader
== (get_user_struct()->u_procp->p_pid ) ) (&afs_discon_lock
)->pid_last_reader =0; } while (0)
;
483
484 done3:
485 if (volp)
486 afs_PutVolume(volp, READ_LOCK)((volp)->refCount--);
487
488 if (code == 0) {
489 afs_AddMarinerName(aname, *avcp);
490 /* return the new status in vattr */
491 afs_CopyOutAttrs(*avcp, attrs);
492 afs_MarinerLog("store$Creating", *avcp);
493 }
494
495 afs_PutFakeStat(&fakestate);
496 code = afs_CheckCode(code, &treq, 20);
497
498 done2:
499 return code;
500}
501
502
503/*
504 * Check to see if we can track the change locally: requires that
505 * we have sufficiently recent info in data cache. If so, we
506 * know the new DataVersion number, and place it correctly in both the
507 * data and stat cache entries. This routine returns 1 if we should
508 * do the operation locally, and 0 otherwise.
509 *
510 * This routine must be called with the stat cache entry write-locked,
511 * and dcache entry write-locked.
512 */
513int
514afs_LocalHero(struct vcache *avc, struct dcache *adc,
515 AFSFetchStatus * astat, int aincr)
516{
517 afs_int32 ok;
518 afs_hyper_t avers;
519
520 AFS_STATCNT(afs_LocalHero)((afs_cmstats.callInfo.C_afs_LocalHero)++);
521 hset64(avers, astat->dataVersionHigh, astat->DataVersion)((avers).high = (astat->dataVersionHigh), (avers).low = (astat
->DataVersion))
;
522 /* this *is* the version number, no matter what */
523 if (adc) {
524 ok = (hsame(avc->f.m.DataVersion, adc->f.versionNo)((avc->f.m.DataVersion).low == (adc->f.versionNo).low &&
(avc->f.m.DataVersion).high == (adc->f.versionNo).high
)
&& avc->callback
525 && (avc->f.states & CStatd0x00000001) && avc->cbExpires >= osi_Time()(time(((void *)0))));
526 } else {
527 ok = 0;
528 }
529#if defined(AFS_SGI_ENV)
530 osi_Assert(avc->v.v_type == VDIR)(void)((avc->v.v_type == 0040000) || (osi_AssertFailK( "avc->v.v_type == VDIR"
, "/home/wollman/openafs/src/afs/VNOPS/afs_vnop_create.c", 530
), 0))
;
531#endif
532 /* The bulk status code used the length as a sequence number. */
533 /* Don't update the vcache entry unless the stats are current. */
534 if (avc->f.states & CStatd0x00000001) {
535 hset(avc->f.m.DataVersion, avers)((avc->f.m.DataVersion) = (avers));
536#ifdef AFS_64BIT_CLIENT
537 FillInt64(avc->f.m.Length, astat->Length_hi, astat->Length)(avc->f.m.Length) = ((afs_int64)(astat->Length_hi) <<
32) | (astat->Length);
;
538#else /* AFS_64BIT_CLIENT */
539 avc->f.m.Length = astat->Length;
540#endif /* AFS_64BIT_CLIENT */
541 avc->f.m.Date = astat->ClientModTime;
542 }
543 if (ok) {
544 /* we've been tracking things correctly */
545 adc->dflags |= DFEntryMod0x02;
546 adc->f.versionNo = avers;
547 return 1;
548 } else {
549 if (adc) {
550 ZapDCE(adc)do { (adc)->f.usr_fid.Fid.Unique = 0; afs_indexUnique[(adc
)->index] = 0; (adc)->dflags |= 0x02; } while(0)
;
551 DZap(adc);
552 }
553 if (avc->f.states & CStatd0x00000001) {
554 osi_dnlc_purgedp(avc);
555 }
556 return 0;
557 }
558}