Bug Summary

File:afs/VNOPS/afs_vnop_remove.c
Location:line 296, column 2
Description:Access to field 'excl_locked' results in a dereference of a null pointer

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 * FetchWholeEnchilada
13 * afsremove
14 * afs_remove
15 * afs_newname
16 *
17 */
18#include <afsconfig.h>
19#include "afs/param.h"
20
21
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"
28
29
30extern afs_rwlock_t afs_xvcache;
31extern afs_rwlock_t afs_xcbhash;
32
33
34static void
35FetchWholeEnchilada(struct vcache *avc, struct vrequest *areq)
36{
37 afs_int32 nextChunk;
38 struct dcache *tdc;
39 afs_size_t pos, offset, len;
40
41 AFS_STATCNT(FetchWholeEnchilada)((afs_cmstats.callInfo.C_FetchWholeEnchilada)++);
42 if ((avc->f.states & CStatd0x00000001) == 0)
43 return; /* don't know size */
44 for (nextChunk = 0; nextChunk < 1024; nextChunk++) { /* sanity check on N chunks */
45 pos = AFS_CHUNKTOBASE(nextChunk)((nextChunk == 0) ? 0 : ((afs_size_t) afs_FirstCSize + ((afs_size_t
) (nextChunk - 1) << afs_LogChunk)))
;
46 if (pos >= avc->f.m.Length)
47 return; /* all done */
48 tdc = afs_GetDCache(avc, pos, areq, &offset, &len, 0);
49 if (!tdc)
50 return;
51 afs_PutDCache(tdc);
52 }
53}
54
55int
56afsremove(struct vcache *adp, struct dcache *tdc,
57 struct vcache *tvc, char *aname, afs_ucred_tstruct usr_ucred *acred,
58 struct vrequest *treqp)
59{
60 afs_int32 code = 0;
61 struct afs_conn *tc;
62 struct AFSFetchStatus OutDirStatus;
63 struct AFSVolSync tsync;
64 struct rx_connection *rxconn;
65 XSTATS_DECLSstruct afs_stats_opTimingData *opP = ((void *)0); osi_timeval_t
opStartTime = { 0, 0}, opStopTime, elapsedTime
;
66 if (!AFS_IS_DISCONNECTED(afs_is_disconnected)) {
67 do {
68 tc = afs_Conn(&adp->f.fidusr_fid, treqp, SHARED_LOCK4, &rxconn);
69 if (tc) {
70 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE)opP = &(afs_stats_cmfullperf.rpc.fsRPCTimes[6]); osi_GetTime
(&opStartTime);
;
71 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_remove.c"
, 71);}while(0); } while(0)
;
72 code =
73 RXAFS_RemoveFile(rxconn, (struct AFSFid *)&adp->f.fidusr_fid.Fid,
74 aname, &OutDirStatus, &tsync);
75 RX_AFS_GLOCK()do { do{if (!(pthread_mutex_lock(&afs_global_lock) == 0))
AssertionFailed("/home/wollman/openafs/src/afs/VNOPS/afs_vnop_remove.c"
, 75);}while(0); afs_global_owner = pthread_self(); } while(0
)
;
76 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; }; } }
;
77 } else
78 code = -1;
79 } while (afs_Analyze
80 (tc, rxconn, code, &adp->f.fidusr_fid, treqp, AFS_STATS_FS_RPCIDX_REMOVEFILE6,
81 SHARED_LOCK4, NULL((void *)0)));
82 }
83
84 osi_dnlc_remove(adp, aname, tvc);
85
86 if (code) {
87 if (tdc) {
88 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)
;
89 afs_PutDCache(tdc);
90 }
91
92 if (tvc)
93 afs_PutVCache(tvc);
94
95 if (code < 0) {
96 ObtainWriteLock(&afs_xcbhash, 497)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 = 497; } while (0)
;
97 afs_DequeueCallback(adp);
98 adp->f.states &= ~CStatd0x00000001;
99 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)
;
100 osi_dnlc_purgedp(adp);
101 }
102 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)
;
103 code = afs_CheckCode(code, treqp, 21);
104 return code;
105 }
106 if (tdc)
107 UpgradeSToWLock(&tdc->lock, 637)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
= 637; } while (0)
;
108 if (AFS_IS_DISCON_RW(afs_is_discon_rw) || afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
109 /* we can do it locally */
110 code = afs_dir_Delete(tdc, aname);
111 if (code) {
112 ZapDCE(tdc)do { (tdc)->f.usr_fid.Fid.Unique = 0; afs_indexUnique[(tdc
)->index] = 0; (tdc)->dflags |= 0x02; } while(0)
; /* surprise error -- invalid value */
113 DZap(tdc);
114 }
115 }
116 if (tdc) {
117 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)
;
118 afs_PutDCache(tdc); /* drop ref count */
119 }
120 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)
;
121
122 /* now, get vnode for unlinked dude, and see if we should force it
123 * from cache. adp is now the deleted files vnode. Note that we
124 * call FindVCache instead of GetVCache since if the file's really
125 * gone, we won't be able to fetch the status info anyway. */
126 if (tvc) {
127 afs_MarinerLog("store$Removing", tvc);
128#ifdef AFS_BOZONLOCK_ENV
129 afs_BozonLock(&tvc->pvnLock, tvc);
130 /* Since afs_TryToSmush will do a pvn_vptrunc */
131#endif
132 ObtainWriteLock(&tvc->lock, 141)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 = 141
; } while (0)
;
133 /* note that callback will be broken on the deleted file if there are
134 * still >0 links left to it, so we'll get the stat right */
135 tvc->f.m.LinkCount--;
136 tvc->f.states &= ~CUnique0x00001000; /* For the dfs xlator */
137 if (tvc->f.m.LinkCount == 0 && !osi_Active(tvc)) {
138 if (!AFS_NFSXLATORREQ(acred)(((acred)->cr_rgid) == 0xaaaa))
139 afs_TryToSmush(tvc, acred, 0);
140 }
141 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)
;
142#ifdef AFS_BOZONLOCK_ENV
143 afs_BozonUnlock(&tvc->pvnLock, tvc);
144#endif
145 afs_PutVCache(tvc);
146 }
147 return (0);
148}
149
150char *
151afs_newname(void)
152{
153 char *name, *sp, *p = ".__afs";
154 afs_int32 rd = afs_random() & 0xffff;
155
156 sp = name = osi_AllocSmallSpace(AFS_SMALLOCSIZ(64*sizeof(void *)));
157 while (*p != '\0')
158 *sp++ = *p++;
159 while (rd) {
160 *sp++ = "0123456789ABCDEF"[rd & 0x0f];
161 rd >>= 4;
162 }
163 *sp = '\0';
164 return (name);
165}
166
167/* these variables appear to exist for debugging purposes */
168struct vcache *Tadp1, *Ttvc;
169int Tadpr, Ttvcr;
170char *Tnam;
171char *Tnam1;
172
173/* Note that we don't set CDirty here, this is OK because the unlink
174 * RPC is called synchronously */
175int
176afs_remove(OSI_VC_DECL(adp)struct vcache *adp, char *aname, afs_ucred_tstruct usr_ucred *acred)
177{
178 struct vrequest treq;
179 struct dcache *tdc;
180 struct VenusFid unlinkFid;
181 afs_int32 code;
182 struct vcache *tvc;
183 afs_size_t offset, len;
184 struct afs_fakestat_state fakestate;
185 OSI_VC_CONVERT(adp);
186
187 AFS_STATCNT(afs_remove)((afs_cmstats.callInfo.C_afs_remove)++);
188 afs_Trace2(afs_iclSetp, CM_TRACE_REMOVE, ICL_TYPE_POINTER, adp,(((afs_iclSetp) && (afs_iclSetp->states & 2)) ?
afs_icl_Event2(afs_iclSetp, (701087826L), (1<<24)+((2)
<<18)+((4)<<12), (long)(adp), (long)(aname)) : 0)
189 ICL_TYPE_STRING, aname)(((afs_iclSetp) && (afs_iclSetp->states & 2)) ?
afs_icl_Event2(afs_iclSetp, (701087826L), (1<<24)+((2)
<<18)+((4)<<12), (long)(adp), (long)(aname)) : 0)
;
190
191
192 if ((code = afs_InitReq(&treq, acred))) {
1
Taking false branch
193 return code;
194 }
195
196 afs_InitFakeStat(&fakestate);
197 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)
;
198 code = afs_EvalFakeStat(&adp, &fakestate, &treq);
199 if (code)
2
Taking false branch
200 goto done;
201
202 /* Check if this is dynroot */
203 if (afs_IsDynroot(adp)) {
3
Taking false branch
204 code = afs_DynrootVOPRemove(adp, acred, aname);
205 goto done;
206 }
207 if (afs_IsDynrootMount(adp)) {
4
Taking false branch
208 code = ENOENT2;
209 goto done;
210 }
211
212 if (strlen(aname) > AFSNAMEMAX256) {
5
Taking false branch
213 code = ENAMETOOLONG63;
214 goto done;
215 }
216 tagain:
217 code = afs_VerifyVCache(adp, &treq)(((adp)->f.states & 0x00000001) ? 0 : afs_VerifyVCache2
((adp),&treq))
;
218 tvc = NULL((void *)0);
219 if (code) {
6
Taking false branch
220 code = afs_CheckCode(code, &treq, 23);
221 goto done;
222 }
223
224 /** If the volume is read-only, return error without making an RPC to the
225 * fileserver
226 */
227 if (adp->f.states & CRO0x00000004) {
7
Taking false branch
228 code = EROFS30;
229 goto done;
230 }
231
232 /* If we're running disconnected without logging, go no further... */
233 if (AFS_IS_DISCONNECTED(afs_is_disconnected) && !AFS_IS_DISCON_RW(afs_is_discon_rw)) {
8
Taking false branch
234 code = ENETDOWN50;
235 goto done;
236 }
237
238 tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1); /* test for error below */
239 ObtainWriteLock(&adp->lock, 142)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 = 142
; } while (0)
;
240 if (tdc)
9
Taking false branch
241 ObtainSharedLock(&tdc->lock, 638)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
= 638; } while (0)
;
242
243 /*
244 * Make sure that the data in the cache is current. We may have
245 * received a callback while we were waiting for the write lock.
246 */
247 if (!(adp->f.states & CStatd0x00000001)
10
Taking false branch
248 || (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
)
)) {
249 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)
;
250 if (tdc) {
251 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)
;
252 afs_PutDCache(tdc);
253 }
254 goto tagain;
255 }
256
257 unlinkFid.Fid.Vnode = 0;
258 if (!tvc) {
11
Taking true branch
259 tvc = osi_dnlc_lookup(adp, aname, WRITE_LOCK2);
260 }
261 /* This should not be necessary since afs_lookup() has already
262 * done the work.
263 */
264 if (!tvc)
12
Taking true branch
265 if (tdc) {
13
Taking false branch
266 code = afs_dir_Lookup(tdc, aname, &unlinkFid.Fid);
267 if (code == 0) {
268 afs_int32 cached = 0;
269
270 unlinkFid.Cell = adp->f.fidusr_fid.Cell;
271 unlinkFid.Fid.Volume = adp->f.fidusr_fid.Fid.Volume;
272 if (unlinkFid.Fid.Unique == 0) {
273 tvc =
274 afs_LookupVCache(&unlinkFid, &treq, &cached, adp,
275 aname);
276 } else {
277 ObtainReadLock(&afs_xvcache)do { ; if (!((&afs_xvcache)->excl_locked & 2)) ((&
afs_xvcache)->readers_reading)++; else Afs_Lock_Obtain(&
afs_xvcache, 1); (&afs_xvcache)->pid_last_reader = (get_user_struct
()->u_procp->p_pid ); } while (0)
;
278 tvc = afs_FindVCache(&unlinkFid, 0, DO_STATS1);
279 ReleaseReadLock(&afs_xvcache)do { ; if (!(--((&afs_xvcache)->readers_reading)) &&
(&afs_xvcache)->wait_states) Afs_Lock_ReleaseW(&afs_xvcache
) ; if ( (&afs_xvcache)->pid_last_reader == (get_user_struct
()->u_procp->p_pid ) ) (&afs_xvcache)->pid_last_reader
=0; } while (0)
;
280 }
281 }
282 }
283
284 if (AFS_IS_DISCON_RW(afs_is_discon_rw)) {
14
Taking true branch
285 if (!adp->f.shadow.vnodeusr_vnode && !(adp->f.ddirty_flags & VDisconCreate0x00004000)) {
15
Taking false branch
286 /* Make shadow copy of parent dir. */
287 afs_MakeShadowDir(adp, tdc);
288 }
289
290 /* Can't hold a dcache lock whilst we're getting a vcache one */
291 if (tdc)
16
Taking false branch
292 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)
;
293
294 /* XXX - We're holding adp->lock still, and we've got no
295 * guarantee about whether the ordering matches the lock hierarchy */
296 ObtainWriteLock(&tvc->lock, 713)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 = 713
; } while (0)
;
17
Within the expansion of the macro 'ObtainWriteLock':
a
Access to field 'excl_locked' results in a dereference of a null pointer
297
298 /* If we were locally created, then we don't need to do very
299 * much beyond ensuring that we don't exist anymore */
300 if (tvc->f.ddirty_flags & VDisconCreate0x00004000) {
301 afs_DisconRemoveDirty(tvc);
302 } else {
303 /* Add removed file vcache to dirty list. */
304 afs_DisconAddDirty(tvc, VDisconRemove0x00002000, 1);
305 }
306 adp->f.m.LinkCount--;
307 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)
;
308 if (tdc)
309 ObtainSharedLock(&tdc->lock, 714)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
= 714; } while (0)
;
310 }
311
312 if (tvc && osi_Active(tvc)) {
313 /* about to delete whole file, prefetch it first */
314 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)
;
315 if (tdc)
316 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)
;
317 ObtainWriteLock(&tvc->lock, 143)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 = 143
; } while (0)
;
318 FetchWholeEnchilada(tvc, &treq);
319 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)
;
320 ObtainWriteLock(&adp->lock, 144)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 = 144
; } while (0)
;
321 /* Technically I don't think we need this back, but let's hold it
322 anyway; The "got" reference should actually be sufficient. */
323 if (tdc)
324 ObtainSharedLock(&tdc->lock, 640)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
= 640; } while (0)
;
325 }
326
327 osi_dnlc_remove(adp, aname, tvc);
328
329 Tadp1 = adp;
330#ifndef AFS_DARWIN80_ENV
331 Tadpr = VREFCOUNT(adp)((adp)->v.v_count);
332#endif
333 Ttvc = tvc;
334 Tnam = aname;
335 Tnam1 = 0;
336#ifndef AFS_DARWIN80_ENV
337 if (tvc)
338 Ttvcr = VREFCOUNT(tvc)((tvc)->v.v_count);
339#endif
340#ifdef AFS_AIX_ENV
341 if (tvc && VREFCOUNT_GT(tvc, 2)((tvc)->v.v_count > (2)) && tvc->opens > 0
342 && !(tvc->f.states & CUnlinked0x00010000)) {
343#else
344 if (tvc && VREFCOUNT_GT(tvc, 1)((tvc)->v.v_count > (1)) && tvc->opens > 0
345 && !(tvc->f.states & CUnlinked0x00010000)) {
346#endif
347 char *unlname = afs_newname();
348
349 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)
;
350 if (tdc)
351 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)
;
352 code = afsrename(adp, aname, adp, unlname, acred, &treq);
353 Tnam1 = unlname;
354 if (!code) {
355 struct VenusFid *oldmvid = NULL((void *)0);
356 if (tvc->mvid)
357 oldmvid = tvc->mvid;
358 tvc->mvid = (struct VenusFid *)unlname;
359 if (oldmvid)
360 osi_FreeSmallSpace(oldmvid);
361 crholdusr_crhold(acred);
362 if (tvc->uncred) {
363 crfreeusr_crfree(tvc->uncred);
364 }
365 tvc->uncred = acred;
366 tvc->f.states |= CUnlinked0x00010000;
367 /* if rename succeeded, remove should not */
368 ObtainWriteLock(&tvc->lock, 715)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 = 715
; } while (0)
;
369 if (tvc->f.ddirty_flags & VDisconRemove0x00002000) {
370 tvc->f.ddirty_flags &= ~VDisconRemove0x00002000;
371 }
372 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)
;
373 } else {
374 osi_FreeSmallSpace(unlname);
375 }
376 if (tdc)
377 afs_PutDCache(tdc);
378 afs_PutVCache(tvc);
379 } else {
380 code = afsremove(adp, tdc, tvc, aname, acred, &treq);
381 }
382 done:
383 afs_PutFakeStat(&fakestate);
384#ifndef AFS_DARWIN80_ENV
385 /* we can't track by thread, it's not exported in the KPI; only do
386 this on !macos */
387 osi_Assert(!WriteLocked(&adp->lock) || (adp->lock.pid_writer != MyPidxx))(void)((!((&adp->lock)->excl_locked & 2) || (adp
->lock.pid_writer != (get_user_struct()->u_procp->p_pid
))) || (osi_AssertFailK( "!WriteLocked(&adp->lock) || (adp->lock.pid_writer != MyPidxx)"
, "/home/wollman/openafs/src/afs/VNOPS/afs_vnop_remove.c", 387
), 0))
;
388#endif
389 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)
;
390 return code;
391}
392
393
394/* afs_remunlink -- This tries to delete the file at the server after it has
395 * been renamed when unlinked locally but now has been finally released.
396 *
397 * CAUTION -- may be called with avc unheld. */
398
399int
400afs_remunlink(struct vcache *avc, int doit)
401{
402 afs_ucred_tstruct usr_ucred *cred;
403 char *unlname;
404 struct vcache *adp;
405 struct vrequest treq;
406 struct VenusFid dirFid;
407 struct dcache *tdc;
408 afs_int32 code = 0;
409
410 if (NBObtainWriteLock(&avc->lock, 423)(((&avc->lock)->excl_locked || (&avc->lock)->
readers_reading) ? 35 : (((&avc->lock) -> excl_locked
= 2), ((&avc->lock)->pid_writer = (get_user_struct
()->u_procp->p_pid )), ((&avc->lock)->src_indicator
= 423), 0))
)
411 return 0;
412#if defined(AFS_DARWIN80_ENV)
413 if (vnode_get(AFSTOV(avc)(&(avc)->v))) {
414 ReleaseWriteLock(&avc->lock)do { ; (&avc->lock)->excl_locked &= ~2; if ((&
avc->lock)->wait_states) Afs_Lock_ReleaseR(&avc->
lock); (&avc->lock)->pid_writer=0; } while (0)
;
415 return 0;
416 }
417#endif
418
419 if (avc->mvid && (doit || (avc->f.states & CUnlinkedDel0x00040000))) {
420 if ((code = afs_InitReq(&treq, avc->uncred))) {
421 ReleaseWriteLock(&avc->lock)do { ; (&avc->lock)->excl_locked &= ~2; if ((&
avc->lock)->wait_states) Afs_Lock_ReleaseR(&avc->
lock); (&avc->lock)->pid_writer=0; } while (0)
;
422 } else {
423 /* Must bump the refCount because GetVCache may block.
424 * Also clear mvid so no other thread comes here if we block.
425 */
426 unlname = (char *)avc->mvid;
427 avc->mvid = NULL((void *)0);
428 cred = avc->uncred;
429 avc->uncred = NULL((void *)0);
430
431#if defined(AFS_DARWIN_ENV) && !defined(AFS_DARWIN80_ENV)
432 VREF(AFSTOV(avc)(&(avc)->v));
433#else
434 AFS_FAST_HOLD(avc)do { { ((&((avc))->v))->v_count++; }; } while(0);
435#endif
436
437 /* We'll only try this once. If it fails, just release the vnode.
438 * Clear after doing hold so that NewVCache doesn't find us yet.
439 */
440 avc->f.states &= ~(CUnlinked0x00010000 | CUnlinkedDel0x00040000);
441
442 ReleaseWriteLock(&avc->lock)do { ; (&avc->lock)->excl_locked &= ~2; if ((&
avc->lock)->wait_states) Afs_Lock_ReleaseR(&avc->
lock); (&avc->lock)->pid_writer=0; } while (0)
;
443
444 dirFid.Cell = avc->f.fidusr_fid.Cell;
445 dirFid.Fid.Volume = avc->f.fidusr_fid.Fid.Volume;
446 dirFid.Fid.Vnode = avc->f.parent.vnodeusr_vnode;
447 dirFid.Fid.Unique = avc->f.parent.unique;
448 adp = afs_GetVCache(&dirFid, &treq, NULL((void *)0), NULL((void *)0));
449
450 if (adp) {
451 tdc = afs_FindDCache(adp, (afs_size_t) 0);
452 ObtainWriteLock(&adp->lock, 159)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 = 159
; } while (0)
;
453 if (tdc)
454 ObtainSharedLock(&tdc->lock, 639)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
= 639; } while (0)
;
455
456 /* afsremove releases the adp & tdc locks, and does vn_rele(avc) */
457 code = afsremove(adp, tdc, avc, unlname, cred, &treq);
458 afs_PutVCache(adp);
459 } else {
460 /* we failed - and won't be back to try again. */
461 afs_PutVCache(avc);
462 }
463 osi_FreeSmallSpace(unlname);
464 crfreeusr_crfree(cred);
465 }
466 } else {
467#if defined(AFS_DARWIN80_ENV)
468 vnode_put(AFSTOV(avc)(&(avc)->v));
469#endif
470 ReleaseWriteLock(&avc->lock)do { ; (&avc->lock)->excl_locked &= ~2; if ((&
avc->lock)->wait_states) Afs_Lock_ReleaseR(&avc->
lock); (&avc->lock)->pid_writer=0; } while (0)
;
471 }
472
473 return code;
474}