Bug Summary

File:afs/afs_disconnected.c
Location:line 706, column 2
Description:Value stored to 'code' is never read

Annotated Source Code

1/*
2 * This software has been released under the terms of the IBM Public
3 * License. For details, see the LICENSE file in the top-level source
4 * directory or online at http://www.openafs.org/dl/license10.html
5 */
6
7#include <afsconfig.h>
8#include "afs/param.h"
9
10
11#include "afs/sysincludes.h"
12#include "afsincludes.h"
13#include "afs/afs_stats.h" /* statistics */
14#include "afs/lock.h"
15#include "afs/afs_cbqueue.h"
16
17#define dv_match(vc, fstat)((vc->f.m.DataVersion.low == fstat.DataVersion) &&
(vc->f.m.DataVersion.high == fstat.dataVersionHigh))
\
18 ((vc->f.m.DataVersion.low == fstat.DataVersion) && \
19 (vc->f.m.DataVersion.high == fstat.dataVersionHigh))
20
21/*! Circular queue of dirty vcaches */
22struct afs_q afs_disconDirty;
23
24/*! Circular queue of vcaches with shadow directories */
25struct afs_q afs_disconShadow;
26
27/*! Locks both of these lists. Must be write locked for anything other than
28 * list traversal */
29afs_rwlock_t afs_disconDirtyLock;
30
31extern afs_int32 *afs_dvhashTbl; /*Data cache hash table */
32extern afs_int32 *afs_dchashTbl; /*Data cache hash table */
33extern afs_int32 *afs_dvnextTbl; /*Dcache hash table links */
34extern afs_int32 *afs_dcnextTbl; /*Dcache hash table links */
35extern struct dcache **afs_indexTable; /*Pointers to dcache entries */
36
37/*! Vnode number. On file creation, use the current value and increment it.
38 */
39afs_uint32 afs_DisconVnode = 2;
40
41/*! Conflict policy. */
42enum {
43 CLIENT_WINS = 0,
44 SERVER_WINS,
45 LAST_CLOSER_WINS,
46 ASK
47};
48
49afs_int32 afs_ConflictPolicy = SERVER_WINS;
50
51static void afs_DisconDiscardAllShadows(int, afs_ucred_tstruct usr_ucred *);
52void afs_DbgListDirEntries(struct VenusFid *afid);
53
54
55/*!
56 * Find the first dcache of a file that has the specified fid.
57 * Similar to afs_FindDCache, only that it takes a fid instead
58 * of a vcache and it can get the first dcache.
59 *
60 * \param afid
61 *
62 * \return The found dcache or NULL.
63 */
64struct dcache *
65afs_FindDCacheByFid(struct VenusFid *afid)
66{
67 afs_int32 i, index;
68 struct dcache *tdc = NULL((void *)0);
69
70 i = DVHash(afid)((((afid)->Fid.Vnode + (afid)->Fid.Volume )) & (afs_dhashsize
-1))
;
71 ObtainWriteLock(&afs_xdcache, 758)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 = 758; } while (0)
;
72 for (index = afs_dvhashTbl[i]; index != NULLIDX(-1);) {
73 if (afs_indexUnique[index] == afid->Fid.Unique) {
74 tdc = afs_GetDSlot(index, NULL)(*(afs_cacheType->GetDSlot))(index, ((void *)0));
75 ReleaseReadLock(&tdc->tlock)do { ; if (!(--((&tdc->tlock)->readers_reading)) &&
(&tdc->tlock)->wait_states) Afs_Lock_ReleaseW(&
tdc->tlock) ; if ( (&tdc->tlock)->pid_last_reader
== (get_user_struct()->u_procp->p_pid ) ) (&tdc->
tlock)->pid_last_reader =0; } while (0)
;
76 if (!FidCmp(&tdc->f.fid, afid)((&tdc->f.usr_fid)->Fid.Unique != (afid)->Fid.Unique
|| (&tdc->f.usr_fid)->Fid.Vnode != (afid)->Fid.
Vnode || (&tdc->f.usr_fid)->Fid.Volume != (afid)->
Fid.Volume || (&tdc->f.usr_fid)->Cell != (afid)->
Cell)
) {
77 break; /* leaving refCount high for caller */
78 }
79 afs_PutDCache(tdc);
80 }
81 index = afs_dvnextTbl[index];
82 }
83 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)
;
84
85 if (index == NULLIDX(-1))
86 tdc = NULL((void *)0);
87 return tdc;
88}
89
90/*!
91 * Generate a store status from a dirty vcache entry.
92 *
93 * \param avc Dirty vcache entry.
94 * \param astat
95 *
96 * \note The vnode must be share locked. It is called only on resync,
97 * where the vnode is write locked locally and and the server.
98 *
99 * \return Mask of operations.
100 */
101int
102afs_GenStoreStatus(struct vcache *avc, struct AFSStoreStatus *astat)
103{
104 if (!avc || !astat || !avc->f.ddirty_flags)
105 return 0;
106
107 /* Clean up store stat. */
108 memset(astat, 0, sizeof(struct AFSStoreStatus));
109
110 if (avc->f.ddirty_flags & VDisconSetTime0x00000001) {
111 /* Update timestamp. */
112 astat->ClientModTime = avc->f.m.Date;
113 astat->Mask |= AFS_SETMODTIME1;
114 }
115
116 if (avc->f.ddirty_flags & VDisconSetMode0x00000002) {
117 /* Copy the mode bits. */
118 astat->UnixModeBits = avc->f.m.Mode;
119 astat->Mask |= AFS_SETMODE8;
120 }
121
122 /* XXX: more to come... ?*/
123
124 return astat->Mask;
125}
126
127/*!
128 * Hook for filtering the local dir fid by searching the "." entry.
129 *
130 * \param hdata The fid to be filled.
131 */
132static int
133get_parent_dir_fid_hook(void *hdata, char *aname, afs_int32 vnodeusr_vnode,
134 afs_int32 unique)
135{
136 struct VenusFid *tfid = (struct VenusFid *) hdata;
137
138 if ((aname[0] == '.') && (aname[1] == '.') && !aname[2]) {
139 tfid->Fid.Vnode = vnodeusr_vnode;
140 tfid->Fid.Unique = unique;
141 return 1;
142 }
143
144 return 0;
145}
146
147/*!
148 * Get a the dir's fid by looking in the vcache for simple files and
149 * in the ".." entry for directories.
150 *
151 * \param avc The file's vhash entry.
152 * \param afid Put the fid here.
153 *
154 * \return 0 on success, -1 on failure
155 */
156int
157afs_GetParentDirFid(struct vcache *avc, struct VenusFid *afid)
158{
159 struct dcache *tdc;
160
161 afid->Cell = avc->f.fidusr_fid.Cell;
162 afid->Fid.Volume = avc->f.fidusr_fid.Fid.Volume;
163
164 switch (vType(avc)(avc)->v.v_type) {
165 case VREG0100000:
166 case VLNK0120000:
167 /* Normal files have the dir fid embedded in the vcache. */
168 afid->Fid.Vnode = avc->f.parent.vnodeusr_vnode;
169 afid->Fid.Unique = avc->f.parent.unique;
170 break;
171 case VDIR0040000:
172 /* If dir or parent dir created locally*/
173 tdc = afs_FindDCacheByFid(&avc->f.fidusr_fid);
174 if (tdc) {
175 afid->Fid.Unique = 0;
176 /* Lookup each entry for the fid. It should be the first. */
177 afs_dir_EnumerateDir(tdc, &get_parent_dir_fid_hook, afid);
178 afs_PutDCache(tdc);
179 if (afid->Fid.Unique == 0) {
180 return -1;
181 }
182 } else {
183 return -1;
184 }
185 break;
186 default:
187 return -1;
188 }
189
190 return 0;
191}
192
193struct NameAndFid {
194 struct VenusFid *fidusr_fid;
195 char *name;
196 int name_len;
197};
198
199/*!
200 * Hook that searches a certain fid's name.
201 *
202 * \param hdata NameAndFid structure containin a pointer to a fid
203 * and an allocate name. The name will be filled when hit.
204 */
205static int
206get_vnode_name_hook(void *hdata, char *aname, afs_int32 vnodeusr_vnode,
207 afs_int32 unique)
208{
209 struct NameAndFid *nf = (struct NameAndFid *) hdata;
210
211 if ((nf->fidusr_fid->Fid.Vnode == vnodeusr_vnode) &&
212 (nf->fidusr_fid->Fid.Unique == unique)) {
213 nf->name_len = strlen(aname);
214 memcpy(nf->name, aname, nf->name_len);
215 nf->name[nf->name_len] = 0;
216
217 return 1;
218 }
219
220 return 0;
221}
222
223/*!
224 * Try to get a vnode's name by comparing all parent dir's entries
225 * to the given fid. It can also return the dir's dcache.
226 *
227 * \param avc The file's vcache.
228 * \param afid The parent dir's fid.
229 * \param aname A preallocated string for the name.
230 * \param deleted Has this file been deleted? If yes, use the shadow
231 * dir for looking up the name.
232 */
233int
234afs_GetVnodeName(struct vcache *avc, struct VenusFid *afid, char *aname,
235 int deleted)
236{
237 int code = 0;
238 struct dcache *tdc;
239 struct vcache *parent_vc;
240 struct NameAndFid tnf;
241 struct VenusFid parent_fid;
242 struct VenusFid shadow_fid;
243
244 /* List dir contents and get it's tdc. */
245 if (deleted) {
246 /* For deleted files, get the shadow dir's tdc: */
247
248 /* Get the parent dir's vcache that contains the shadow fid. */
249 parent_fid.Cell = avc->f.fidusr_fid.Cell;
250 parent_fid.Fid.Volume = avc->f.fidusr_fid.Fid.Volume;
251 if (avc->f.ddirty_flags & VDisconRename0x00010000) {
252 /* For renames the old dir fid is needed. */
253 parent_fid.Fid.Vnode = avc->f.oldParent.vnodeusr_vnode;
254 parent_fid.Fid.Unique = avc->f.oldParent.unique;
255 } else {
256 parent_fid.Fid.Vnode = afid->Fid.Vnode;
257 parent_fid.Fid.Unique = afid->Fid.Unique;
258 }
259
260 /* Get the parent dir's vcache that contains the shadow fid. */
261 ObtainSharedLock(&afs_xvcache, 755)do { ; if (!(&afs_xvcache)->excl_locked) (&afs_xvcache
) -> excl_locked = 4; else Afs_Lock_Obtain(&afs_xvcache
, 4); (&afs_xvcache)->pid_writer = (get_user_struct()->
u_procp->p_pid ); (&afs_xvcache)->src_indicator = 755
; } while (0)
;
262 parent_vc = afs_FindVCache(&parent_fid, 0, 1);
263 ReleaseSharedLock(&afs_xvcache)do { ; (&afs_xvcache)->excl_locked &= ~(4 | 2); if
((&afs_xvcache)->wait_states) Afs_Lock_ReleaseR(&
afs_xvcache); (&afs_xvcache)->pid_writer=0; } while (0
)
;
264 if (!parent_vc) {
265 return ENOENT2;
266 }
267
268 shadow_fid.Cell = parent_vc->f.fidusr_fid.Cell;
269 shadow_fid.Fid.Volume = parent_vc->f.fidusr_fid.Fid.Volume;
270 shadow_fid.Fid.Vnode = parent_vc->f.shadow.vnodeusr_vnode;
271 shadow_fid.Fid.Unique = parent_vc->f.shadow.unique;
272
273 afs_PutVCache(parent_vc);
274
275 /* Get shadow dir's dcache. */
276 tdc = afs_FindDCacheByFid(&shadow_fid);
277
278 } else {
279
280 /* For normal files, look into the current dir's entry. */
281 tdc = afs_FindDCacheByFid(afid);
282 } /* if (deleted) */
283
284 if (tdc) {
285 tnf.fidusr_fid = &avc->f.fidusr_fid;
286 tnf.name_len = -1;
287 tnf.name = aname;
288 afs_dir_EnumerateDir(tdc, &get_vnode_name_hook, &tnf);
289 afs_PutDCache(tdc);
290 if (tnf.name_len == -1)
291 code = ENOENT2;
292 } else {
293 /* printf("Directory dcache not found!\n"); */
294 code = ENOENT2;
295 }
296
297 return code;
298}
299
300struct DirtyChildrenCount {
301 struct vcache *vc;
302 afs_uint32 count;
303};
304
305/*!
306 * Lookup dirty deleted vnodes in this dir.
307 */
308static int
309chk_del_children_hook(void *hdata, char *aname, afs_int32 vnodeusr_vnode,
310 afs_int32 unique)
311{
312 struct VenusFid tfid;
313 struct DirtyChildrenCount *v = (struct DirtyChildrenCount *) hdata;
314 struct vcache *tvc;
315
316 if ((aname[0] == '.') && !aname[1])
317 /* Skip processing this dir again.
318 * It would result in an endless loop.
319 */
320 return 0;
321
322 if ((aname[0] == '.') && (aname[1] == '.') && !aname[2])
323 /* Don't process parent dir. */
324 return 0;
325
326 /* Get this file's vcache. */
327 tfid.Cell = v->vc->f.fidusr_fid.Cell;
328 tfid.Fid.Volume = v->vc->f.fidusr_fid.Fid.Volume;
329 tfid.Fid.Vnode = vnodeusr_vnode;
330 tfid.Fid.Unique = unique;
331
332 ObtainSharedLock(&afs_xvcache, 757)do { ; if (!(&afs_xvcache)->excl_locked) (&afs_xvcache
) -> excl_locked = 4; else Afs_Lock_Obtain(&afs_xvcache
, 4); (&afs_xvcache)->pid_writer = (get_user_struct()->
u_procp->p_pid ); (&afs_xvcache)->src_indicator = 757
; } while (0)
;
333 tvc = afs_FindVCache(&tfid, 0, 1);
334 ReleaseSharedLock(&afs_xvcache)do { ; (&afs_xvcache)->excl_locked &= ~(4 | 2); if
((&afs_xvcache)->wait_states) Afs_Lock_ReleaseR(&
afs_xvcache); (&afs_xvcache)->pid_writer=0; } while (0
)
;
335
336 /* Count unfinished dirty children. */
337 if (tvc) {
338 ObtainReadLock(&tvc->lock)do { ; if (!((&tvc->lock)->excl_locked & 2)) ((
&tvc->lock)->readers_reading)++; else Afs_Lock_Obtain
(&tvc->lock, 1); (&tvc->lock)->pid_last_reader
= (get_user_struct()->u_procp->p_pid ); } while (0)
;
339 if (tvc->f.ddirty_flags)
340 v->count++;
341 ReleaseReadLock(&tvc->lock)do { ; if (!(--((&tvc->lock)->readers_reading)) &&
(&tvc->lock)->wait_states) Afs_Lock_ReleaseW(&
tvc->lock) ; if ( (&tvc->lock)->pid_last_reader ==
(get_user_struct()->u_procp->p_pid ) ) (&tvc->lock
)->pid_last_reader =0; } while (0)
;
342
343 afs_PutVCache(tvc);
344 }
345
346 return 0;
347}
348
349/*!
350 * Check if entries have been deleted in a vnode's shadow
351 * dir.
352 *
353 * \return Returns the number of dirty children.
354 *
355 * \note afs_DDirtyVCListLock must be write locked.
356 */
357int
358afs_CheckDeletedChildren(struct vcache *avc)
359{
360 struct dcache *tdc;
361 struct DirtyChildrenCount dcc;
362 struct VenusFid shadow_fid;
363
364 if (!avc->f.shadow.vnodeusr_vnode)
365 /* Empty dir. */
366 return 0;
367
368 shadow_fid.Cell = avc->f.fidusr_fid.Cell;
369 shadow_fid.Fid.Volume = avc->f.fidusr_fid.Fid.Volume;
370 shadow_fid.Fid.Vnode = avc->f.shadow.vnodeusr_vnode;
371 shadow_fid.Fid.Unique = avc->f.shadow.unique;
372
373 dcc.count = 0;
374
375 /* Get shadow dir's dcache. */
376 tdc = afs_FindDCacheByFid(&shadow_fid);
377 if (tdc) {
378 dcc.vc = avc;
379 afs_dir_EnumerateDir(tdc, &chk_del_children_hook, &dcc);
380 afs_PutDCache(tdc);
381 }
382
383 return dcc.count;
384}
385
386/*!
387 * Changes a file's parent fid references.
388 */
389static int
390fix_children_fids_hook(void *hdata, char *aname, afs_int32 vnodeusr_vnode,
391 afs_int32 unique)
392{
393 struct VenusFid tfid;
394 struct VenusFid *afid = (struct VenusFid *) hdata;
395 struct vcache *tvc;
396 struct dcache *tdc = NULL((void *)0);
397
398 if ((aname[0] == '.') && !aname[1])
399 return 0;
400
401 if ((aname[0] == '.') && (aname[1] == '.') && !aname[2])
402 return 0;
403
404 tfid.Cell = afid->Cell;
405 tfid.Fid.Volume = afid->Fid.Volume;
406 tfid.Fid.Vnode = vnodeusr_vnode;
407 tfid.Fid.Unique = unique;
408
409 if (!(vnodeusr_vnode % 2)) {
410 /* vnode's parity indicates that it's a file. */
411
412 /* Get the vcache. */
413 ObtainSharedLock(&afs_xvcache, 759)do { ; if (!(&afs_xvcache)->excl_locked) (&afs_xvcache
) -> excl_locked = 4; else Afs_Lock_Obtain(&afs_xvcache
, 4); (&afs_xvcache)->pid_writer = (get_user_struct()->
u_procp->p_pid ); (&afs_xvcache)->src_indicator = 759
; } while (0)
;
414 tvc = afs_FindVCache(&tfid, 0, 1);
415 ReleaseSharedLock(&afs_xvcache)do { ; (&afs_xvcache)->excl_locked &= ~(4 | 2); if
((&afs_xvcache)->wait_states) Afs_Lock_ReleaseR(&
afs_xvcache); (&afs_xvcache)->pid_writer=0; } while (0
)
;
416
417 /* Change the fields. */
418 if (tvc) {
419 tvc->f.parent.vnodeusr_vnode = afid->Fid.Vnode;
420 tvc->f.parent.unique = afid->Fid.Unique;
421
422 afs_PutVCache(tvc);
423 }
424 } else {
425 /* It's a dir. Fix this dir's .. entry to contain the new fid. */
426 /* Seek the dir's dcache. */
427 tdc = afs_FindDCacheByFid(&tfid);
428 if (tdc) {
429 /* Change the .. entry fid. */
430 afs_dir_ChangeFid(tdc, "..", NULL((void *)0), &afid->Fid.Vnode);
431 afs_PutDCache(tdc);
432 }
433 } /* if (!(vnode % 2))*/
434
435 return 0;
436}
437
438/*!
439 * Fixes the parentVnode and parentUnique fields of all
440 * files (not dirs) contained in the directory pointed by
441 * old_fid. This is useful on resync, when a locally created dir
442 * get's a new fid and all the children references must be updated
443 * to reflect the new fid.
444 *
445 * \note The dir's fid hasn't been changed yet, it is still referenced
446 * with the old fid.
447 *
448 * \param old_fid The current dir's fid.
449 * \param new_fid The new dir's fid.
450 */
451void
452afs_FixChildrenFids(struct VenusFid *old_fid, struct VenusFid *new_fid)
453{
454 struct dcache *tdc;
455
456 /* Get shadow dir's dcache. */
457 tdc = afs_FindDCacheByFid(old_fid);
458 /* Change the fids. */
459 if (tdc) {
460 afs_dir_EnumerateDir(tdc, &fix_children_fids_hook, new_fid);
461 afs_PutDCache(tdc);
462 }
463}
464
465static int
466list_dir_hook(void *hdata, char *aname, afs_int32 vnodeusr_vnode, afs_int32 unique)
467{
468 /* printf("list_dir_hook: %s v:%u u:%u\n", aname, vnode, unique); */
469 return 0;
470}
471
472void
473afs_DbgListDirEntries(struct VenusFid *afid)
474{
475 struct dcache *tdc;
476
477 /* Get shadow dir's dcache. */
478 tdc = afs_FindDCacheByFid(afid);
479 if (tdc) {
480 afs_dir_EnumerateDir(tdc, &list_dir_hook, NULL((void *)0));
481 afs_PutDCache(tdc);
482 }
483}
484
485/*!
486 * Find the parent vcache for a given child
487 *
488 * \param avc The vcache whose parent is required
489 * \param afid Fid structure in which parent's fid should be stored
490 * \param aname An AFSNAMEMAX sized buffer to hold the parents name
491 * \param adp A pointer to a struct vcache* which will be set to the
492 * parent vcache
493 *
494 * \return An error code. 0 indicates success, EAGAIN that the vnode should
495 * be deferred to later in the resync process
496 */
497
498int
499afs_GetParentVCache(struct vcache *avc, int deleted, struct VenusFid *afid,
500 char *aname, struct vcache **adp)
501{
502 int code;
503
504 *adp = NULL((void *)0);
505
506 if (afs_GetParentDirFid(avc, afid)) {
507 /* printf("afs_GetParentVCache: Couldn't find parent dir's FID.\n"); */
508 return ENOENT2;
509 }
510
511 code = afs_GetVnodeName(avc, afid, aname, deleted);
512 if (code) {
513 /* printf("afs_GetParentVCache: Couldn't find file name\n"); */
514 goto end;
515 }
516
517 ObtainSharedLock(&afs_xvcache, 766)do { ; if (!(&afs_xvcache)->excl_locked) (&afs_xvcache
) -> excl_locked = 4; else Afs_Lock_Obtain(&afs_xvcache
, 4); (&afs_xvcache)->pid_writer = (get_user_struct()->
u_procp->p_pid ); (&afs_xvcache)->src_indicator = 766
; } while (0)
;
518 *adp = afs_FindVCache(afid, 0, 1);
519 ReleaseSharedLock(&afs_xvcache)do { ; (&afs_xvcache)->excl_locked &= ~(4 | 2); if
((&afs_xvcache)->wait_states) Afs_Lock_ReleaseR(&
afs_xvcache); (&afs_xvcache)->pid_writer=0; } while (0
)
;
520 if (!*adp) {
521 /* printf("afs_GetParentVCache: Couldn't find parent dir's vcache\n"); */
522 code = ENOENT2;
523 goto end;
524 }
525
526 if ((*adp)->f.ddirty_flags & VDisconCreate0x00004000) {
527 /* printf("afs_GetParentVCache: deferring until parent exists\n"); */
528 code = EAGAIN35;
529 goto end;
530 }
531
532end:
533 if (code && *adp) {
534 afs_PutVCache(*adp);
535 *adp = NULL((void *)0);
536 }
537 return code;
538}
539
540
541/*!
542 * Handles file renaming on reconnection:
543 * - Get the old name from the old dir's shadow dir.
544 * - Get the new name from the current dir.
545 * - Old dir fid and new dir fid are collected along the way.
546 * */
547int
548afs_ProcessOpRename(struct vcache *avc, struct vrequest *areq)
549{
550 struct VenusFid old_pdir_fid, new_pdir_fid;
551 char *old_name = NULL((void *)0), *new_name = NULL((void *)0);
552 struct AFSFetchStatus OutOldDirStatus, OutNewDirStatus;
553 struct AFSVolSync tsync;
554 struct afs_conn *tc;
555 struct rx_connection *rxconn;
556 afs_uint32 code = 0;
557 XSTATS_DECLSstruct afs_stats_opTimingData *opP = ((void *)0); osi_timeval_t
opStartTime = { 0, 0}, opStopTime, elapsedTime
;
558
559 /* Get old dir vcache. */
560 old_pdir_fid.Cell = avc->f.fidusr_fid.Cell;
561 old_pdir_fid.Fid.Volume = avc->f.fidusr_fid.Fid.Volume;
562 old_pdir_fid.Fid.Vnode = avc->f.oldParent.vnodeusr_vnode;
563 old_pdir_fid.Fid.Unique = avc->f.oldParent.unique;
564
565 /* Get old name. */
566 old_name = afs_osi_Alloc(AFSNAMEMAX256);
567 if (!old_name) {
568 /* printf("afs_ProcessOpRename: Couldn't alloc space for old name.\n"); */
569 return ENOMEM12;
570 }
571 code = afs_GetVnodeName(avc, &old_pdir_fid, old_name, 1);
572 if (code) {
573 /* printf("afs_ProcessOpRename: Couldn't find old name.\n"); */
574 goto done;
575 }
576
577 /* Alloc data first. */
578 new_name = afs_osi_Alloc(AFSNAMEMAX256);
579 if (!new_name) {
580 /* printf("afs_ProcessOpRename: Couldn't alloc space for new name.\n"); */
581 code = ENOMEM12;
582 goto done;
583 }
584
585 if (avc->f.ddirty_flags & VDisconRenameSameDir0x00020000) {
586 /* If we're in the same dir, don't do the lookups all over again,
587 * just copy fid and vcache from the old dir.
588 */
589 memcpy(&new_pdir_fid, &old_pdir_fid, sizeof(struct VenusFid));
590 } else {
591 /* Get parent dir's FID.*/
592 if (afs_GetParentDirFid(avc, &new_pdir_fid)) {
593 /* printf("afs_ProcessOpRename: Couldn't find new parent dir FID.\n"); */
594 code = ENOENT2;
595 goto done;
596 }
597 }
598
599 /* And finally get the new name. */
600 code = afs_GetVnodeName(avc, &new_pdir_fid, new_name, 0);
601 if (code) {
602 /* printf("afs_ProcessOpRename: Couldn't find new name.\n"); */
603 goto done;
604 }
605
606 /* Send to data to server. */
607 do {
608 tc = afs_Conn(&old_pdir_fid, areq, SHARED_LOCK4, &rxconn);
609 if (tc) {
610 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RENAME)opP = &(afs_stats_cmfullperf.rpc.fsRPCTimes[8]); osi_GetTime
(&opStartTime);
;
611 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/afs_disconnected.c"
, 611);}while(0); } while(0)
;
612 code = RXAFS_Rename(rxconn,
613 (struct AFSFid *)&old_pdir_fid.Fid,
614 old_name,
615 (struct AFSFid *)&new_pdir_fid.Fid,
616 new_name,
617 &OutOldDirStatus,
618 &OutNewDirStatus,
619 &tsync);
620 RX_AFS_GLOCK()do { do{if (!(pthread_mutex_lock(&afs_global_lock) == 0))
AssertionFailed("/home/wollman/openafs/src/afs/afs_disconnected.c"
, 620);}while(0); afs_global_owner = pthread_self(); } while(
0)
;
621 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; }; } }
;
622 } else
623 code = -1;
624
625 } while (afs_Analyze(tc,
626 rxconn,
627 code,
628 &new_pdir_fid,
629 areq,
630 AFS_STATS_FS_RPCIDX_RENAME8,
631 SHARED_LOCK4,
632 NULL((void *)0)));
633
634 /* if (code) printf("afs_ProcessOpRename: server code=%u\n", code); */
635done:
636 if (new_name)
637 afs_osi_Free(new_name, AFSNAMEMAX256);
638 if (old_name)
639 afs_osi_Free(old_name, AFSNAMEMAX256);
640 return code;
641}
642
643/*!
644 * Handles all the reconnection details:
645 * - Get all the details about the vnode: name, fid, and parent dir fid.
646 * - Send data to server.
647 * - Handle errors.
648 * - Reorder vhash and dcaches in their hashes, using the newly acquired fid.
649 */
650int
651afs_ProcessOpCreate(struct vcache *avc, struct vrequest *areq,
652 afs_ucred_tstruct usr_ucred *acred)
653{
654 char *tname = NULL((void *)0), *ttargetName = NULL((void *)0);
655 struct AFSStoreStatus InStatus;
656 struct AFSFetchStatus OutFidStatus, OutDirStatus;
657 struct VenusFid pdir_fid, newFid;
658 struct AFSCallBack CallBack;
659 struct AFSVolSync tsync;
660 struct vcache *tdp = NULL((void *)0), *tvc = NULL((void *)0);
661 struct dcache *tdc = NULL((void *)0);
662 struct afs_conn *tc;
663 struct rx_connection *rxconn;
664 afs_int32 hash, new_hash, index;
665 afs_size_t tlen;
666 int code, op = 0;
667 XSTATS_DECLSstruct afs_stats_opTimingData *opP = ((void *)0); osi_timeval_t
opStartTime = { 0, 0}, opStopTime, elapsedTime
;
668
669 tname = afs_osi_Alloc(AFSNAMEMAX256);
670 if (!tname)
671 return ENOMEM12;
672
673 code = afs_GetParentVCache(avc, 0, &pdir_fid, tname, &tdp);
674 if (code)
675 goto end;
676
677 /* This data may also be in linkData, but then we have to deal with
678 * the joy of terminating NULLs and . and file modes. So just get
679 * it from the dcache where it won't have been fiddled with.
680 */
681 if (vType(avc)(avc)->v.v_type == VLNK0120000) {
682 afs_size_t offset;
683 struct dcache *tdc;
684 struct osi_file *tfile;
685
686 tdc = afs_GetDCache(avc, 0, areq, &offset, &tlen, 0);
687 if (!tdc) {
688 code = ENOENT2;
689 goto end;
690 }
691
692 if (tlen > 1024) {
693 afs_PutDCache(tdc);
694 code = EFAULT14;
695 goto end;
696 }
697
698 tlen++; /* space for NULL */
699 ttargetName = afs_osi_Alloc(tlen);
700 if (!ttargetName) {
701 afs_PutDCache(tdc);
702 return ENOMEM12;
703 }
704 ObtainReadLock(&tdc->lock)do { ; if (!((&tdc->lock)->excl_locked & 2)) ((
&tdc->lock)->readers_reading)++; else Afs_Lock_Obtain
(&tdc->lock, 1); (&tdc->lock)->pid_last_reader
= (get_user_struct()->u_procp->p_pid ); } while (0)
;
705 tfile = afs_CFileOpen(&tdc->f.inode)(void *)(*(afs_cacheType->open))(&tdc->f.usr_inode);
706 code = afs_CFileRead(tfile, 0, ttargetName, tlen)(*(afs_cacheType->fread))(tfile, 0, ttargetName, tlen);
Value stored to 'code' is never read
707 ttargetName[tlen-1] = '\0';
708 afs_CFileClose(tfile)(*(afs_cacheType->close))(tfile);
709 ReleaseReadLock(&tdc->lock)do { ; if (!(--((&tdc->lock)->readers_reading)) &&
(&tdc->lock)->wait_states) Afs_Lock_ReleaseW(&
tdc->lock) ; if ( (&tdc->lock)->pid_last_reader ==
(get_user_struct()->u_procp->p_pid ) ) (&tdc->lock
)->pid_last_reader =0; } while (0)
;
710 afs_PutDCache(tdc);
711 }
712
713 /* Set status. */
714 InStatus.Mask = AFS_SETMODTIME1 | AFS_SETMODE8 | AFS_SETGROUP4;
715 InStatus.ClientModTime = avc->f.m.Date;
716 InStatus.Owner = avc->f.m.Owner;
717 InStatus.Group = (afs_int32) afs_cr_gid(acred)((acred)->cr_gid);
718 /* Only care about protection bits. */
719 InStatus.UnixModeBits = avc->f.m.Mode & 0xffff;
720
721 do {
722 tc = afs_Conn(&tdp->f.fidusr_fid, areq, SHARED_LOCK4, &rxconn);
723 if (tc) {
724 switch (vType(avc)(avc)->v.v_type) {
725 case VREG0100000:
726 /* Make file on server. */
727 op = AFS_STATS_FS_RPCIDX_CREATEFILE7;
728 XSTATS_START_TIME(op)opP = &(afs_stats_cmfullperf.rpc.fsRPCTimes[op]); osi_GetTime
(&opStartTime);
;
729 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/afs_disconnected.c"
, 729);}while(0); } while(0)
;
730 code = RXAFS_CreateFile(rxconn,
731 (struct AFSFid *)&tdp->f.fidusr_fid.Fid,
732 tname, &InStatus,
733 (struct AFSFid *) &newFid.Fid,
734 &OutFidStatus, &OutDirStatus,
735 &CallBack, &tsync);
736 RX_AFS_GLOCK()do { do{if (!(pthread_mutex_lock(&afs_global_lock) == 0))
AssertionFailed("/home/wollman/openafs/src/afs/afs_disconnected.c"
, 736);}while(0); afs_global_owner = pthread_self(); } while(
0)
;
737 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; }; } }
;
738 break;
739 case VDIR0040000:
740 /* Make dir on server. */
741 op = AFS_STATS_FS_RPCIDX_MAKEDIR11;
742 XSTATS_START_TIME(op)opP = &(afs_stats_cmfullperf.rpc.fsRPCTimes[op]); osi_GetTime
(&opStartTime);
;
743 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/afs_disconnected.c"
, 743);}while(0); } while(0)
;
744 code = RXAFS_MakeDir(rxconn, (struct AFSFid *) &tdp->f.fidusr_fid.Fid,
745 tname, &InStatus,
746 (struct AFSFid *) &newFid.Fid,
747 &OutFidStatus, &OutDirStatus,
748 &CallBack, &tsync);
749 RX_AFS_GLOCK()do { do{if (!(pthread_mutex_lock(&afs_global_lock) == 0))
AssertionFailed("/home/wollman/openafs/src/afs/afs_disconnected.c"
, 749);}while(0); afs_global_owner = pthread_self(); } while(
0)
;
750 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; }; } }
;
751 break;
752 case VLNK0120000:
753 /* Make symlink on server. */
754 op = AFS_STATS_FS_RPCIDX_SYMLINK9;
755 XSTATS_START_TIME(op)opP = &(afs_stats_cmfullperf.rpc.fsRPCTimes[op]); osi_GetTime
(&opStartTime);
;
756 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/afs_disconnected.c"
, 756);}while(0); } while(0)
;
757 code = RXAFS_Symlink(rxconn,
758 (struct AFSFid *) &tdp->f.fidusr_fid.Fid,
759 tname, ttargetName, &InStatus,
760 (struct AFSFid *) &newFid.Fid,
761 &OutFidStatus, &OutDirStatus, &tsync);
762 RX_AFS_GLOCK()do { do{if (!(pthread_mutex_lock(&afs_global_lock) == 0))
AssertionFailed("/home/wollman/openafs/src/afs/afs_disconnected.c"
, 762);}while(0); afs_global_owner = pthread_self(); } while(
0)
;
763 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; }; } }
;
764 break;
765 default:
766 op = AFS_STATS_FS_RPCIDX_CREATEFILE7;
767 code = 1;
768 break;
769 }
770 } else
771 code = -1;
772 } while (afs_Analyze(tc, rxconn, code, &tdp->f.fidusr_fid, areq, op, SHARED_LOCK4, NULL((void *)0)));
773
774 /* TODO: Handle errors. */
775 if (code) {
776 /* printf("afs_ProcessOpCreate: error while creating vnode on server, code=%d .\n", code); */
777 goto end;
778 }
779
780 /* The rpc doesn't set the cell number. */
781 newFid.Cell = avc->f.fidusr_fid.Cell;
782
783 /*
784 * Change the fid in the dir entry.
785 */
786
787 /* Seek the dir's dcache. */
788 tdc = afs_FindDCacheByFid(&tdp->f.fidusr_fid);
789 if (tdc) {
790 /* And now change the fid in the parent dir entry. */
791 afs_dir_ChangeFid(tdc, tname, &avc->f.fidusr_fid.Fid.Vnode, &newFid.Fid.Vnode);
792 afs_PutDCache(tdc);
793 }
794
795 if (vType(avc)(avc)->v.v_type == VDIR0040000) {
796 /* Change fid in the dir for the "." entry. ".." has alredy been
797 * handled by afs_FixChildrenFids when processing the parent dir.
798 */
799 tdc = afs_FindDCacheByFid(&avc->f.fidusr_fid);
800 if (tdc) {
801 afs_dir_ChangeFid(tdc, ".", &avc->f.fidusr_fid.Fid.Vnode,
802 &newFid.Fid.Vnode);
803
804 if (avc->f.m.LinkCount >= 2)
805 /* For non empty dirs, fix children's parentVnode and
806 * parentUnique reference.
807 */
808 afs_FixChildrenFids(&avc->f.fidusr_fid, &newFid);
809
810 afs_PutDCache(tdc);
811 }
812 }
813
814 /* Recompute hash chain positions for vnode and dcaches.
815 * Then change to the new FID.
816 */
817
818 /* The vcache goes first. */
819 ObtainWriteLock(&afs_xvcache, 735)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 = 735; } while (0)
;
820
821 /* Old fid hash. */
822 hash = VCHash(&avc->f.fid)(((&avc->f.usr_fid)->Fid.Volume + (&avc->f.usr_fid
)->Fid.Vnode) & (1024 -1))
;
823 /* New fid hash. */
824 new_hash = VCHash(&newFid)(((&newFid)->Fid.Volume + (&newFid)->Fid.Vnode)
& (1024 -1))
;
825
826 /* Remove hash from old position. */
827 /* XXX: not checking array element contents. It shouldn't be empty.
828 * If it oopses, then something else might be wrong.
829 */
830 if (afs_vhashT[hash] == avc) {
831 /* First in hash chain (might be the only one). */
832 afs_vhashT[hash] = avc->hnext;
833 } else {
834 /* More elements in hash chain. */
835 for (tvc = afs_vhashT[hash]; tvc; tvc = tvc->hnext) {
836 if (tvc->hnext == avc) {
837 tvc->hnext = avc->hnext;
838 break;
839 }
840 }
841 } /* if (!afs_vhashT[i]->hnext) */
842 QRemove(&avc->vhashq)((&avc->vhashq)->next->prev = (&avc->vhashq
)->prev, (&avc->vhashq)->prev->next = (&avc
->vhashq)->next, (&avc->vhashq)->prev = ((void
*)0), (&avc->vhashq)->next = ((void *)0))
;
843
844 /* Insert hash in new position. */
845 avc->hnext = afs_vhashT[new_hash];
846 afs_vhashT[new_hash] = avc;
847 QAdd(&afs_vhashTV[VCHashV(&newFid)], &avc->vhashq)((&avc->vhashq)->next = (&afs_vhashTV[((&newFid
)->Fid.Volume & (1024 -1))])->next, (&avc->vhashq
)->prev = (&afs_vhashTV[((&newFid)->Fid.Volume &
(1024 -1))]), (&afs_vhashTV[((&newFid)->Fid.Volume
& (1024 -1))])->next->prev = (&avc->vhashq)
, (&afs_vhashTV[((&newFid)->Fid.Volume & (1024
-1))])->next = (&avc->vhashq))
;
848
849 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)
;
850
851 /* Do the same thing for all dcaches. */
852 hash = DVHash(&avc->f.fid)((((&avc->f.usr_fid)->Fid.Vnode + (&avc->f.usr_fid
)->Fid.Volume )) & (afs_dhashsize-1))
;
853 ObtainWriteLock(&afs_xdcache, 743)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 = 743; } while (0)
;
854 for (index = afs_dvhashTbl[hash]; index != NULLIDX(-1); index = hash) {
855 hash = afs_dvnextTbl[index];
856 tdc = afs_GetDSlot(index, NULL)(*(afs_cacheType->GetDSlot))(index, ((void *)0));
857 ReleaseReadLock(&tdc->tlock)do { ; if (!(--((&tdc->tlock)->readers_reading)) &&
(&tdc->tlock)->wait_states) Afs_Lock_ReleaseW(&
tdc->tlock) ; if ( (&tdc->tlock)->pid_last_reader
== (get_user_struct()->u_procp->p_pid ) ) (&tdc->
tlock)->pid_last_reader =0; } while (0)
;
858 if (afs_indexUnique[index] == avc->f.fidusr_fid.Fid.Unique) {
859 if (!FidCmp(&tdc->f.fid, &avc->f.fid)((&tdc->f.usr_fid)->Fid.Unique != (&avc->f.usr_fid
)->Fid.Unique || (&tdc->f.usr_fid)->Fid.Vnode !=
(&avc->f.usr_fid)->Fid.Vnode || (&tdc->f.usr_fid
)->Fid.Volume != (&avc->f.usr_fid)->Fid.Volume ||
(&tdc->f.usr_fid)->Cell != (&avc->f.usr_fid
)->Cell)
) {
860
861 /* Safer but slower. */
862 afs_HashOutDCache(tdc, 0);
863
864 /* Put dcache in new positions in the dchash and dvhash. */
865 new_hash = DCHash(&newFid, tdc->f.chunk)((((&newFid)->Fid.Vnode + (&newFid)->Fid.Volume
+ (tdc->f.chunk))) & (afs_dhashsize-1))
;
866 afs_dcnextTbl[tdc->index] = afs_dchashTbl[new_hash];
867 afs_dchashTbl[new_hash] = tdc->index;
868
869 new_hash = DVHash(&newFid)((((&newFid)->Fid.Vnode + (&newFid)->Fid.Volume
)) & (afs_dhashsize-1))
;
870 afs_dvnextTbl[tdc->index] = afs_dvhashTbl[new_hash];
871 afs_dvhashTbl[new_hash] = tdc->index;
872
873 afs_indexUnique[tdc->index] = newFid.Fid.Unique;
874 memcpy(&tdc->f.fidusr_fid, &newFid, sizeof(struct VenusFid));
875 } /* if fid match */
876 } /* if uniquifier match */
877 if (tdc)
878 afs_PutDCache(tdc);
879 } /* for all dcaches in this hash bucket */
880 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)
;
881
882 /* Now we can set the new fid. */
883 memcpy(&avc->f.fidusr_fid, &newFid, sizeof(struct VenusFid));
884
885end:
886 if (tdp)
887 afs_PutVCache(tdp);
888 afs_osi_Free(tname, AFSNAMEMAX256);
889 if (ttargetName)
890 afs_osi_Free(ttargetName, tlen);
891 return code;
892}
893
894/*!
895 * Remove a vnode on the server, be it file or directory.
896 * Not much to do here only get the parent dir's fid and call the
897 * removal rpc.
898 *
899 * \param avc The deleted vcache
900 * \param areq
901 *
902 * \note The vcache refcount should be dropped because it points to
903 * a deleted vnode and has served it's purpouse, but we drop refcount
904 * on shadow dir deletio (we still need it for that).
905 *
906 * \note avc must be write locked.
907 */
908int
909afs_ProcessOpRemove(struct vcache *avc, struct vrequest *areq)
910{
911 char *tname = NULL((void *)0);
912 struct AFSFetchStatus OutDirStatus;
913 struct VenusFid pdir_fid;
914 struct AFSVolSync tsync;
915 struct afs_conn *tc;
916 struct rx_connection *rxconn;
917 struct vcache *tdp = NULL((void *)0);
918 int code = 0;
919 XSTATS_DECLSstruct afs_stats_opTimingData *opP = ((void *)0); osi_timeval_t
opStartTime = { 0, 0}, opStopTime, elapsedTime
;
920
921 tname = afs_osi_Alloc(AFSNAMEMAX256);
922 if (!tname) {
923 /* printf("afs_ProcessOpRemove: Couldn't alloc space for file name\n"); */
924 return ENOMEM12;
925 }
926
927 code = afs_GetParentVCache(avc, 1, &pdir_fid, tname, &tdp);
928 if (code)
929 goto end;
930
931 if ((vType(avc)(avc)->v.v_type == VDIR0040000) && (afs_CheckDeletedChildren(avc))) {
932 /* Deleted children of this dir remain unsynchronized.
933 * Defer this vcache.
934 */
935 code = EAGAIN35;
936 goto end;
937 }
938
939 if (vType(avc)(avc)->v.v_type == VREG0100000 || vType(avc)(avc)->v.v_type == VLNK0120000) {
940 /* Remove file on server. */
941 do {
942 tc = afs_Conn(&pdir_fid, areq, SHARED_LOCK4, &rxconn);
943 if (tc) {
944 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE)opP = &(afs_stats_cmfullperf.rpc.fsRPCTimes[6]); osi_GetTime
(&opStartTime);
;
945 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/afs_disconnected.c"
, 945);}while(0); } while(0)
;
946 code = RXAFS_RemoveFile(rxconn,
947 &pdir_fid.Fid,
948 tname,
949 &OutDirStatus,
950 &tsync);
951
952 RX_AFS_GLOCK()do { do{if (!(pthread_mutex_lock(&afs_global_lock) == 0))
AssertionFailed("/home/wollman/openafs/src/afs/afs_disconnected.c"
, 952);}while(0); afs_global_owner = pthread_self(); } while(
0)
;
953 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; }; } }
;
954 } else
955 code = -1;
956 } while (afs_Analyze(tc,
957 rxconn,
958 code,
959 &pdir_fid,
960 areq,
961 AFS_STATS_FS_RPCIDX_REMOVEFILE6,
962 SHARED_LOCK4,
963 NULL((void *)0)));
964
965 } else if (vType(avc)(avc)->v.v_type == VDIR0040000) {
966 /* Remove dir on server. */
967 do {
968 tc = afs_Conn(&pdir_fid, areq, SHARED_LOCK4, &rxconn);
969 if (tc) {
970 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEDIR)opP = &(afs_stats_cmfullperf.rpc.fsRPCTimes[12]); osi_GetTime
(&opStartTime);
;
971 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/afs_disconnected.c"
, 971);}while(0); } while(0)
;
972 code = RXAFS_RemoveDir(rxconn,
973 &pdir_fid.Fid,
974 tname,
975 &OutDirStatus,
976 &tsync);
977 RX_AFS_GLOCK()do { do{if (!(pthread_mutex_lock(&afs_global_lock) == 0))
AssertionFailed("/home/wollman/openafs/src/afs/afs_disconnected.c"
, 977);}while(0); afs_global_owner = pthread_self(); } while(
0)
;
978 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; }; } }
;
979 } else
980 code = -1;
981 } while (afs_Analyze(tc,
982 rxconn,
983 code,
984 &pdir_fid,
985 areq,
986 AFS_STATS_FS_RPCIDX_REMOVEDIR12,
987 SHARED_LOCK4,
988 NULL((void *)0)));
989
990 } /* if (vType(avc) == VREG) */
991
992 /* if (code) printf("afs_ProcessOpRemove: server returned code=%u\n", code); */
993
994end:
995 afs_osi_Free(tname, AFSNAMEMAX256);
996 return code;
997}
998
999/*!
1000 * Send disconnected file changes to the server.
1001 *
1002 * \note Call with vnode locked both locally and on the server.
1003 *
1004 * \param avc Vnode that gets synchronized to the server.
1005 * \param areq Used for obtaining a conn struct.
1006 *
1007 * \return 0 for success. On failure, other error codes.
1008 */
1009int
1010afs_SendChanges(struct vcache *avc, struct vrequest *areq)
1011{
1012 struct afs_conn *tc;
1013 struct rx_connection *rxconn;
1014 struct AFSStoreStatus sstat;
1015 struct AFSFetchStatus fstat;
1016 struct AFSVolSync tsync;
1017 int code = 0;
1018 int flags = 0;
1019 XSTATS_DECLSstruct afs_stats_opTimingData *opP = ((void *)0); osi_timeval_t
opStartTime = { 0, 0}, opStopTime, elapsedTime
;
1020
1021 /* Start multiplexing dirty operations from ddirty_flags field: */
1022 if (avc->f.ddirty_flags & VDisconSetAttrMask0x0000003F) {
1023 /* Setattr OPS: */
1024 /* Turn dirty vc data into a new store status... */
1025 if (afs_GenStoreStatus(avc, &sstat) > 0) {
1026 do {
1027 tc = afs_Conn(&avc->f.fidusr_fid, areq, SHARED_LOCK4, &rxconn);
1028 if (tc) {
1029 /* ... and send it. */
1030 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STORESTATUS)opP = &(afs_stats_cmfullperf.rpc.fsRPCTimes[5]); osi_GetTime
(&opStartTime);
;
1031 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/afs_disconnected.c"
, 1031);}while(0); } while(0)
;
1032 code = RXAFS_StoreStatus(rxconn,
1033 (struct AFSFid *) &avc->f.fidusr_fid.Fid,
1034 &sstat,
1035 &fstat,
1036 &tsync);
1037
1038 RX_AFS_GLOCK()do { do{if (!(pthread_mutex_lock(&afs_global_lock) == 0))
AssertionFailed("/home/wollman/openafs/src/afs/afs_disconnected.c"
, 1038);}while(0); afs_global_owner = pthread_self(); } while
(0)
;
1039 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; }; } }
;
1040 } else
1041 code = -1;
1042
1043 } while (afs_Analyze(tc,
1044 rxconn,
1045 code,
1046 &avc->f.fidusr_fid,
1047 areq,
1048 AFS_STATS_FS_RPCIDX_STORESTATUS5,
1049 SHARED_LOCK4,
1050 NULL((void *)0)));
1051
1052 } /* if (afs_GenStoreStatus() > 0)*/
1053 } /* disconnected SETATTR */
1054
1055 if (code)
1056 return code;
1057
1058 if (avc->f.ddirty_flags &
1059 (VDisconTrunc0x00000020
1060 | VDisconWriteClose0x00000400
1061 | VDisconWriteFlush0x00000800
1062 | VDisconWriteOsiFlush0x00001000)) {
1063
1064 /* Truncate OP: */
1065 do {
1066 tc = afs_Conn(&avc->f.fidusr_fid, areq, SHARED_LOCK4, &rxconn);
1067 if (tc) {
1068 /* Set storing flags. XXX: A tad inefficient ... */
1069 if (avc->f.ddirty_flags & VDisconWriteClose0x00000400)
1070 flags |= AFS_LASTSTORE4;
1071 if (avc->f.ddirty_flags & VDisconWriteOsiFlush0x00001000)
1072 flags |= (AFS_SYNC1 | AFS_LASTSTORE4);
1073 if (avc->f.ddirty_flags & VDisconWriteFlush0x00000800)
1074 flags |= AFS_SYNC1;
1075
1076 /* Try to send store to server. */
1077 /* XXX: AFS_LASTSTORE for writes? Or just AFS_SYNC for all? */
1078 code = afs_StoreAllSegments(avc, areq, flags);
1079 } else
1080 code = -1;
1081
1082 } while (afs_Analyze(tc,
1083 rxconn,
1084 code,
1085 &avc->f.fidusr_fid,
1086 areq,
1087 AFS_STATS_FS_RPCIDX_STOREDATA3,
1088 SHARED_LOCK4,
1089 NULL((void *)0)));
1090
1091 } /* disconnected TRUNC | WRITE */
1092
1093 return code;
1094}
1095
1096/*!
1097 * All files that have been dirty before disconnection are going to
1098 * be replayed back to the server.
1099 *
1100 * \param areq Request from the user.
1101 * \param acred User credentials.
1102 *
1103 * \return If all files synchronized succesfully, return 0, otherwise
1104 * return error code
1105 *
1106 * \note For now, it's the request from the PDiscon pioctl.
1107 *
1108 */
1109int
1110afs_ResyncDisconFiles(struct vrequest *areq, afs_ucred_tstruct usr_ucred *acred)
1111{
1112 struct afs_conn *tc;
1113 struct rx_connection *rxconn;
1114 struct vcache *tvc;
1115 struct AFSFetchStatus fstat;
1116 struct AFSCallBack callback;
1117 struct AFSVolSync tsync;
1118 int code = 0;
1119 afs_int32 start = 0;
1120 XSTATS_DECLSstruct afs_stats_opTimingData *opP = ((void *)0); osi_timeval_t
opStartTime = { 0, 0}, opStopTime, elapsedTime
;
1121 /*AFS_STATCNT(afs_ResyncDisconFiles);*/
1122
1123 ObtainWriteLock(&afs_disconDirtyLock, 707)do { ; if (!(&afs_disconDirtyLock)->excl_locked &&
!(&afs_disconDirtyLock)->readers_reading) (&afs_disconDirtyLock
) -> excl_locked = 2; else Afs_Lock_Obtain(&afs_disconDirtyLock
, 2); (&afs_disconDirtyLock)->pid_writer = (get_user_struct
()->u_procp->p_pid ); (&afs_disconDirtyLock)->src_indicator
= 707; } while (0)
;
1124
1125 while (!QEmpty(&afs_disconDirty)((&afs_disconDirty)->prev == (&afs_disconDirty))) {
1126 tvc = QEntry(QPrev(&afs_disconDirty), struct vcache, dirtyq)((struct vcache *)((char *)(((&afs_disconDirty)->prev)
)-(char *)(&((struct vcache *)((void *)0))->dirtyq)))
;
1127
1128 /* Can't lock tvc whilst holding the discon dirty lock */
1129 ReleaseWriteLock(&afs_disconDirtyLock)do { ; (&afs_disconDirtyLock)->excl_locked &= ~2; if
((&afs_disconDirtyLock)->wait_states) Afs_Lock_ReleaseR
(&afs_disconDirtyLock); (&afs_disconDirtyLock)->pid_writer
=0; } while (0)
;
1130
1131 /* Get local write lock. */
1132 ObtainWriteLock(&tvc->lock, 705)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 = 705
; } while (0)
;
1133
1134 if (tvc->f.ddirty_flags & VDisconRemove0x00002000) {
1135 /* Delete the file on the server and just move on
1136 * to the next file. After all, it has been deleted
1137 * we can't replay any other operation it.
1138 */
1139 code = afs_ProcessOpRemove(tvc, areq);
1140 goto next_file;
1141
1142 } else if (tvc->f.ddirty_flags & VDisconCreate0x00004000) {
1143 /* For newly created files, we don't need a server lock. */
1144 code = afs_ProcessOpCreate(tvc, areq, acred);
1145 if (code)
1146 goto next_file;
1147
1148 tvc->f.ddirty_flags &= ~VDisconCreate0x00004000;
1149 tvc->f.ddirty_flags |= VDisconCreated0x00008000;
1150 }
1151#if 0
1152 /* Get server write lock. */
1153 do {
1154 tc = afs_Conn(&tvc->f.fidusr_fid, areq, SHARED_LOCK4, &rxconn);
1155 if (tc) {
1156 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK)opP = &(afs_stats_cmfullperf.rpc.fsRPCTimes[13]); osi_GetTime
(&opStartTime);
;
1157 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/afs_disconnected.c"
, 1157);}while(0); } while(0)
;
1158 code = RXAFS_SetLock(rxconn,
1159 (struct AFSFid *)&tvc->f.fidusr_fid.Fid,
1160 LockWrite1,
1161 &tsync);
1162 RX_AFS_GLOCK()do { do{if (!(pthread_mutex_lock(&afs_global_lock) == 0))
AssertionFailed("/home/wollman/openafs/src/afs/afs_disconnected.c"
, 1162);}while(0); afs_global_owner = pthread_self(); } while
(0)
;
1163 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; }; } }
;
1164 } else
1165 code = -1;
1166
1167 } while (afs_Analyze(tc,
1168 rxconn,
1169 code,
1170 &tvc->f.fidusr_fid,
1171 areq,
1172 AFS_STATS_FS_RPCIDX_SETLOCK13,
1173 SHARED_LOCK4,
1174 NULL((void *)0)));
1175
1176 if (code)
1177 goto next_file;
1178#endif
1179 if (tvc->f.ddirty_flags & VDisconRename0x00010000) {
1180 /* If we're renaming the file, do so now */
1181 code = afs_ProcessOpRename(tvc, areq);
1182 if (code)
1183 goto unlock_srv_file;
1184 }
1185
1186 /* Issue a FetchStatus to get info about DV and callbacks. */
1187 do {
1188 tc = afs_Conn(&tvc->f.fidusr_fid, areq, SHARED_LOCK4, &rxconn);
1189 if (tc) {
1190 tvc->callback = tc->parent->srvr->server;
1191 start = osi_Time()(time(((void *)0)));
1192 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS)opP = &(afs_stats_cmfullperf.rpc.fsRPCTimes[2]); osi_GetTime
(&opStartTime);
;
1193 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/afs_disconnected.c"
, 1193);}while(0); } while(0)
;
1194 code = RXAFS_FetchStatus(rxconn,
1195 (struct AFSFid *)&tvc->f.fidusr_fid.Fid,
1196 &fstat,
1197 &callback,
1198 &tsync);
1199 RX_AFS_GLOCK()do { do{if (!(pthread_mutex_lock(&afs_global_lock) == 0))
AssertionFailed("/home/wollman/openafs/src/afs/afs_disconnected.c"
, 1199);}while(0); afs_global_owner = pthread_self(); } while
(0)
;
1200 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; }; } }
;
1201 } else
1202 code = -1;
1203
1204 } while (afs_Analyze(tc,
1205 rxconn,
1206 code,
1207 &tvc->f.fidusr_fid,
1208 areq,
1209 AFS_STATS_FS_RPCIDX_FETCHSTATUS2,
1210 SHARED_LOCK4,
1211 NULL((void *)0)));
1212
1213 if (code) {
1214 goto unlock_srv_file;
1215 }
1216
1217 if ((dv_match(tvc, fstat)((tvc->f.m.DataVersion.low == fstat.DataVersion) &&
(tvc->f.m.DataVersion.high == fstat.dataVersionHigh))
&& (tvc->f.m.Date == fstat.ServerModTime)) ||
1218 (afs_ConflictPolicy == CLIENT_WINS) ||
1219 (tvc->f.ddirty_flags & VDisconCreated0x00008000)) {
1220 /*
1221 * Send changes to the server if there's data version match, or
1222 * client wins policy has been selected or file has been created
1223 * but doesn't have it's the contents on to the server yet.
1224 */
1225 /*
1226 * XXX: Checking server attr changes by timestamp might not the
1227 * most elegant solution, but it's the most viable one that we could find.
1228 */
1229 afs_UpdateStatus(tvc, &tvc->f.fidusr_fid, areq, &fstat, &callback, start);
1230 code = afs_SendChanges(tvc, areq);
1231
1232 } else if (afs_ConflictPolicy == SERVER_WINS) {
1233 /* DV mismatch, apply collision resolution policy. */
1234 /* Discard this files chunks and remove from current dir. */
1235 afs_ResetVCache(tvc, acred);
1236 tvc->f.truncPos = AFS_NOTRUNC0x7fffffff;
1237 } else {
1238 /* printf("afs_ResyncDisconFiles: no resolution policy selected.\n"); */
1239 } /* if DV match or client wins policy */
1240
1241unlock_srv_file:
1242 /* Release server write lock. */
1243#if 0
1244 do {
1245 tc = afs_Conn(&tvc->f.fidusr_fid, areq, SHARED_LOCK4, &rxconn);
1246 if (tc) {
1247 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK)opP = &(afs_stats_cmfullperf.rpc.fsRPCTimes[15]); osi_GetTime
(&opStartTime);
;
1248 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/afs_disconnected.c"
, 1248);}while(0); } while(0)
;
1249 ucode = RXAFS_ReleaseLock(rxconn,
1250 (struct AFSFid *) &tvc->f.fidusr_fid.Fid,
1251 &tsync);
1252 RX_AFS_GLOCK()do { do{if (!(pthread_mutex_lock(&afs_global_lock) == 0))
AssertionFailed("/home/wollman/openafs/src/afs/afs_disconnected.c"
, 1252);}while(0); afs_global_owner = pthread_self(); } while
(0)
;
1253 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; }; } }
;
1254 } else
1255 ucode = -1;
1256 } while (afs_Analyze(tc,
1257 rxconn,
1258 ucode,
1259 &tvc->f.fidusr_fid,
1260 areq,
1261 AFS_STATS_FS_RPCIDX_RELEASELOCK15,
1262 SHARED_LOCK4,
1263 NULL((void *)0)));
1264#endif
1265next_file:
1266 ObtainWriteLock(&afs_disconDirtyLock, 710)do { ; if (!(&afs_disconDirtyLock)->excl_locked &&
!(&afs_disconDirtyLock)->readers_reading) (&afs_disconDirtyLock
) -> excl_locked = 2; else Afs_Lock_Obtain(&afs_disconDirtyLock
, 2); (&afs_disconDirtyLock)->pid_writer = (get_user_struct
()->u_procp->p_pid ); (&afs_disconDirtyLock)->src_indicator
= 710; } while (0)
;
1267 if (code == 0) {
1268 /* Replayed successfully - pull the vcache from the
1269 * disconnected list */
1270 tvc->f.ddirty_flags = 0;
1271 QRemove(&tvc->dirtyq)((&tvc->dirtyq)->next->prev = (&tvc->dirtyq
)->prev, (&tvc->dirtyq)->prev->next = (&tvc
->dirtyq)->next, (&tvc->dirtyq)->prev = ((void
*)0), (&tvc->dirtyq)->next = ((void *)0))
;
1272 afs_PutVCache(tvc);
1273 } else {
1274 if (code == EAGAIN35) {
1275 /* Operation was deferred. Pull it from the current place in
1276 * the list, and stick it at the end again */
1277 QRemove(&tvc->dirtyq)((&tvc->dirtyq)->next->prev = (&tvc->dirtyq
)->prev, (&tvc->dirtyq)->prev->next = (&tvc
->dirtyq)->next, (&tvc->dirtyq)->prev = ((void
*)0), (&tvc->dirtyq)->next = ((void *)0))
;
1278 QAdd(&afs_disconDirty, &tvc->dirtyq)((&tvc->dirtyq)->next = (&afs_disconDirty)->
next, (&tvc->dirtyq)->prev = (&afs_disconDirty)
, (&afs_disconDirty)->next->prev = (&tvc->dirtyq
), (&afs_disconDirty)->next = (&tvc->dirtyq))
;
1279 } else {
1280 /* Failed - keep state as is, and let the user know we died */
1281
1282 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)
;
1283 break;
1284 }
1285 }
1286
1287 /* Release local write lock. */
1288 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)
;
1289 } /* while (tvc) */
1290
1291 if (code) {
1292 ReleaseWriteLock(&afs_disconDirtyLock)do { ; (&afs_disconDirtyLock)->excl_locked &= ~2; if
((&afs_disconDirtyLock)->wait_states) Afs_Lock_ReleaseR
(&afs_disconDirtyLock); (&afs_disconDirtyLock)->pid_writer
=0; } while (0)
;
1293 return code;
1294 }
1295
1296 /* Dispose of all of the shadow directories */
1297 afs_DisconDiscardAllShadows(0, acred);
1298
1299 ReleaseWriteLock(&afs_disconDirtyLock)do { ; (&afs_disconDirtyLock)->excl_locked &= ~2; if
((&afs_disconDirtyLock)->wait_states) Afs_Lock_ReleaseR
(&afs_disconDirtyLock); (&afs_disconDirtyLock)->pid_writer
=0; } while (0)
;
1300 return code;
1301}
1302
1303/*!
1304 * Discard all of our shadow directory copies. If squash is true, then
1305 * we also invalidate the vcache holding the shadow directory, to ensure
1306 * that any disconnected changes are deleted
1307 *
1308 * \param squash
1309 * \param acred
1310 *
1311 * \note afs_disconDirtyLock must be held on entry. It will be released
1312 * and reobtained
1313 */
1314
1315static void
1316afs_DisconDiscardAllShadows(int squash, afs_ucred_tstruct usr_ucred *acred)
1317{
1318 struct vcache *tvc;
1319
1320 while (!QEmpty(&afs_disconShadow)((&afs_disconShadow)->prev == (&afs_disconShadow))) {
1321 tvc = QEntry(QNext(&afs_disconShadow), struct vcache, shadowq)((struct vcache *)((char *)(((&afs_disconShadow)->next
))-(char *)(&((struct vcache *)((void *)0))->shadowq))
)
;
1322
1323 /* Must release the dirty lock to be able to get a vcache lock */
1324 ReleaseWriteLock(&afs_disconDirtyLock)do { ; (&afs_disconDirtyLock)->excl_locked &= ~2; if
((&afs_disconDirtyLock)->wait_states) Afs_Lock_ReleaseR
(&afs_disconDirtyLock); (&afs_disconDirtyLock)->pid_writer
=0; } while (0)
;
1325 ObtainWriteLock(&tvc->lock, 706)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 = 706
; } while (0)
;
1326
1327 if (squash)
1328 afs_ResetVCache(tvc, acred);
1329
1330 afs_DeleteShadowDir(tvc);
1331
1332 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)
;
1333 ObtainWriteLock(&afs_disconDirtyLock, 709)do { ; if (!(&afs_disconDirtyLock)->excl_locked &&
!(&afs_disconDirtyLock)->readers_reading) (&afs_disconDirtyLock
) -> excl_locked = 2; else Afs_Lock_Obtain(&afs_disconDirtyLock
, 2); (&afs_disconDirtyLock)->pid_writer = (get_user_struct
()->u_procp->p_pid ); (&afs_disconDirtyLock)->src_indicator
= 709; } while (0)
;
1334 } /* while (tvc) */
1335}
1336
1337/*!
1338 * This function throws away the whole disconnected state, allowing
1339 * the cache manager to reconnect to a server if we get into a state
1340 * where reconiliation is impossible.
1341 *
1342 * \param acred
1343 *
1344 */
1345void
1346afs_DisconDiscardAll(afs_ucred_tstruct usr_ucred *acred)
1347{
1348 struct vcache *tvc;
1349
1350 ObtainWriteLock(&afs_disconDirtyLock, 717)do { ; if (!(&afs_disconDirtyLock)->excl_locked &&
!(&afs_disconDirtyLock)->readers_reading) (&afs_disconDirtyLock
) -> excl_locked = 2; else Afs_Lock_Obtain(&afs_disconDirtyLock
, 2); (&afs_disconDirtyLock)->pid_writer = (get_user_struct
()->u_procp->p_pid ); (&afs_disconDirtyLock)->src_indicator
= 717; } while (0)
;
1351 while (!QEmpty(&afs_disconDirty)((&afs_disconDirty)->prev == (&afs_disconDirty))) {
1352 tvc = QEntry(QPrev(&afs_disconDirty), struct vcache, dirtyq)((struct vcache *)((char *)(((&afs_disconDirty)->prev)
)-(char *)(&((struct vcache *)((void *)0))->dirtyq)))
;
1353 QRemove(&tvc->dirtyq)((&tvc->dirtyq)->next->prev = (&tvc->dirtyq
)->prev, (&tvc->dirtyq)->prev->next = (&tvc
->dirtyq)->next, (&tvc->dirtyq)->prev = ((void
*)0), (&tvc->dirtyq)->next = ((void *)0))
;
1354 ReleaseWriteLock(&afs_disconDirtyLock)do { ; (&afs_disconDirtyLock)->excl_locked &= ~2; if
((&afs_disconDirtyLock)->wait_states) Afs_Lock_ReleaseR
(&afs_disconDirtyLock); (&afs_disconDirtyLock)->pid_writer
=0; } while (0)
;
1355
1356 ObtainWriteLock(&tvc->lock, 718)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 = 718
; } while (0)
;
1357 afs_ResetVCache(tvc, acred);
1358 tvc->f.truncPos = AFS_NOTRUNC0x7fffffff;
1359 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)
;
1360 ObtainWriteLock(&afs_disconDirtyLock, 719)do { ; if (!(&afs_disconDirtyLock)->excl_locked &&
!(&afs_disconDirtyLock)->readers_reading) (&afs_disconDirtyLock
) -> excl_locked = 2; else Afs_Lock_Obtain(&afs_disconDirtyLock
, 2); (&afs_disconDirtyLock)->pid_writer = (get_user_struct
()->u_procp->p_pid ); (&afs_disconDirtyLock)->src_indicator
= 719; } while (0)
;
1361 afs_PutVCache(tvc);
1362 }
1363
1364 afs_DisconDiscardAllShadows(1, acred);
1365
1366 ReleaseWriteLock(&afs_disconDirtyLock)do { ; (&afs_disconDirtyLock)->excl_locked &= ~2; if
((&afs_disconDirtyLock)->wait_states) Afs_Lock_ReleaseR
(&afs_disconDirtyLock); (&afs_disconDirtyLock)->pid_writer
=0; } while (0)
;
1367}
1368
1369/*!
1370 * Print list of disconnected files.
1371 *
1372 * \note Call with afs_DDirtyVCListLock read locked.
1373 */
1374void
1375afs_DbgDisconFiles(void)
1376{
1377 struct vcache *tvc;
1378 struct afs_q *q;
1379 int i = 0;
1380
1381 afs_warn("List of dirty files: \n");
1382
1383 ObtainReadLock(&afs_disconDirtyLock)do { ; if (!((&afs_disconDirtyLock)->excl_locked &
2)) ((&afs_disconDirtyLock)->readers_reading)++; else
Afs_Lock_Obtain(&afs_disconDirtyLock, 1); (&afs_disconDirtyLock
)->pid_last_reader = (get_user_struct()->u_procp->p_pid
); } while (0)
;
1384 for (q = QPrev(&afs_disconDirty)((&afs_disconDirty)->prev); q != &afs_disconDirty; q = QPrev(q)((q)->prev)) {
1385 tvc = QEntry(q, struct vcache, dirtyq)((struct vcache *)((char *)(q)-(char *)(&((struct vcache *
)((void *)0))->dirtyq)))
;
1386
1387 afs_warn("Cell=%u Volume=%u VNode=%u Unique=%u\n",
1388 tvc->f.fidusr_fid.Cell,
1389 tvc->f.fidusr_fid.Fid.Volume,
1390 tvc->f.fidusr_fid.Fid.Vnode,
1391 tvc->f.fidusr_fid.Fid.Unique);
1392
1393 i++;
1394 if (i >= 30)
1395 osi_Panic("afs_DbgDisconFiles: loop in dirty list\n");
1396 }
1397 ReleaseReadLock(&afs_disconDirtyLock)do { ; if (!(--((&afs_disconDirtyLock)->readers_reading
)) && (&afs_disconDirtyLock)->wait_states) Afs_Lock_ReleaseW
(&afs_disconDirtyLock) ; if ( (&afs_disconDirtyLock)->
pid_last_reader == (get_user_struct()->u_procp->p_pid )
) (&afs_disconDirtyLock)->pid_last_reader =0; } while
(0)
;
1398}
1399
1400/*!
1401 * Generate a fake fid for a disconnected shadow dir.
1402 * Similar to afs_GenFakeFid, only that it uses the dhash
1403 * to search for a uniquifier because a shadow dir lives only
1404 * in the dcache.
1405 *
1406 * \param afid
1407 *
1408 * \note Don't forget to fill in afid with Cell and Volume.
1409 */
1410void
1411afs_GenShadowFid(struct VenusFid *afid)
1412{
1413 afs_uint32 i, index, max_unique = 1;
1414 struct vcache *tvc = NULL((void *)0);
1415
1416 /* Try generating a fid that isn't used in the vhash. */
1417 do {
1418 /* Shadow Fids are always directories */
1419 afid->Fid.Vnode = afs_DisconVnode + 1;
1420
1421 i = DVHash(afid)((((afid)->Fid.Vnode + (afid)->Fid.Volume )) & (afs_dhashsize
-1))
;
1422 ObtainWriteLock(&afs_xdcache, 737)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 = 737; } while (0)
;
1423 for (index = afs_dvhashTbl[i]; index != NULLIDX(-1); index = i) {
1424 i = afs_dvnextTbl[index];
1425 if (afs_indexUnique[index] > max_unique)
1426 max_unique = afs_indexUnique[index];
1427 }
1428
1429 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)
;
1430 afid->Fid.Unique = max_unique + 1;
1431 afs_DisconVnode += 2;
1432 if (!afs_DisconVnode)
1433 afs_DisconVnode = 2;
1434
1435 /* Is this a used vnode? */
1436 ObtainSharedLock(&afs_xvcache, 762)do { ; if (!(&afs_xvcache)->excl_locked) (&afs_xvcache
) -> excl_locked = 4; else Afs_Lock_Obtain(&afs_xvcache
, 4); (&afs_xvcache)->pid_writer = (get_user_struct()->
u_procp->p_pid ); (&afs_xvcache)->src_indicator = 762
; } while (0)
;
1437 tvc = afs_FindVCache(afid, 0, 1);
1438 ReleaseSharedLock(&afs_xvcache)do { ; (&afs_xvcache)->excl_locked &= ~(4 | 2); if
((&afs_xvcache)->wait_states) Afs_Lock_ReleaseR(&
afs_xvcache); (&afs_xvcache)->pid_writer=0; } while (0
)
;
1439 if (tvc)
1440 afs_PutVCache(tvc);
1441 } while (tvc);
1442}
1443
1444/*!
1445 * Generate a fake fid (vnode and uniquifier) for a vcache
1446 * (either dir or normal file). The vnode is generated via
1447 * afs_DisconVNode and the uniquifier by getting the highest
1448 * uniquifier on a hash chain and incrementing it by one.
1449 *
1450 * \param afid The fid structre that will be filled.
1451 * \param avtype Vnode type: VDIR/VREG.
1452 * \param lock True indicates that xvcache may be obtained,
1453 * False that it is already held
1454 *
1455 * \note The cell number must be completed somewhere else.
1456 */
1457void
1458afs_GenFakeFid(struct VenusFid *afid, afs_uint32 avtype, int lock)
1459{
1460 struct vcache *tvc;
1461 afs_uint32 max_unique = 0, i;
1462
1463 switch (avtype) {
1464 case VDIR0040000:
1465 afid->Fid.Vnode = afs_DisconVnode + 1;
1466 break;
1467 case VREG0100000:
1468 case VLNK0120000:
1469 afid->Fid.Vnode = afs_DisconVnode;
1470 break;
1471 }
1472
1473 if (lock)
1474 ObtainWriteLock(&afs_xvcache, 736)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 = 736; } while (0)
;
1475 i = VCHash(afid)(((afid)->Fid.Volume + (afid)->Fid.Vnode) & (1024 -
1))
;
1476 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
1477 if (tvc->f.fidusr_fid.Fid.Unique > max_unique)
1478 max_unique = tvc->f.fidusr_fid.Fid.Unique;
1479 }
1480 if (lock)
1481 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)
;
1482
1483 afid->Fid.Unique = max_unique + 1;
1484 afs_DisconVnode += 2;
1485 if (!afs_DisconVnode)
1486 afs_DisconVnode = 2;
1487}
1488
1489/*!
1490 * Fill in stats for a newly created file/directory.
1491 *
1492 * \param adp The parent dir's vcache.
1493 * \param avc The created vnode.
1494 * \param afid The new fid.
1495 * \param attrs
1496 * \param areq
1497 * \param file_type Specify if file or directory.
1498 *
1499 * \note Call with avc write locked.
1500 */
1501void
1502afs_GenDisconStatus(struct vcache *adp, struct vcache *avc,
1503 struct VenusFid *afid, struct vattrusr_vattr *attrs,
1504 struct vrequest *areq, int file_type)
1505{
1506 memcpy(&avc->f.fidusr_fid, afid, sizeof(struct VenusFid));
1507 avc->f.m.Mode = attrs->va_mode;
1508 /* Used to do this:
1509 * avc->f.m.Owner = attrs->va_uid;
1510 * But now we use the parent dir's ownership,
1511 * there's no other way to get a server owner id.
1512 * XXX: Does it really matter?
1513 */
1514 avc->f.m.Group = adp->f.m.Group;
1515 avc->f.m.Owner = adp->f.m.Owner;
1516 hset64(avc->f.m.DataVersion, 0, 0)((avc->f.m.DataVersion).high = (0), (avc->f.m.DataVersion
).low = (0))
;
1517 avc->f.m.Length = attrs->va_size;
1518 avc->f.m.Date = osi_Time()(time(((void *)0)));
1519 switch(file_type) {
1520 case VREG0100000:
1521 vSetType(avc, VREG)(avc)->v.v_type = (0100000);
1522 avc->f.m.Mode |= S_IFREG0100000;
1523 avc->f.m.LinkCount = 1;
1524 avc->f.parent.vnodeusr_vnode = adp->f.fidusr_fid.Fid.Vnode;
1525 avc->f.parent.unique = adp->f.fidusr_fid.Fid.Unique;
1526 break;
1527 case VDIR0040000:
1528 vSetType(avc, VDIR)(avc)->v.v_type = (0040000);
1529 avc->f.m.Mode |= S_IFDIR0040000;
1530 avc->f.m.LinkCount = 2;
1531 break;
1532 case VLNK0120000:
1533 vSetType(avc, VLNK)(avc)->v.v_type = (0120000);
1534 avc->f.m.Mode |= S_IFLNK0120000;
1535 if ((avc->f.m.Mode & 0111) == 0)
1536 avc->mvstat = 1;
1537 avc->f.parent.vnodeusr_vnode = adp->f.fidusr_fid.Fid.Vnode;
1538 avc->f.parent.unique = adp->f.fidusr_fid.Fid.Unique;
1539 break;
1540 default:
1541 break;
1542 }
1543 avc->f.anyAccess = adp->f.anyAccess;
1544 afs_AddAxs(avc->Access, areq->uid, adp->Access->axess){ struct axscache *ac; if ((ac = axs_Alloc())) { ac->uid =
(areq->uid); ac->axess = (afs_int32)(adp->Access->
axess); ac->next = (avc->Access); avc->Access = ac; }
}
;
1545
1546 avc->callback = NULL((void *)0);
1547 avc->f.states |= CStatd0x00000001;
1548 avc->f.states &= ~CBulkFetching0x04000000;
1549}