Bug Summary

File:volser/volprocs.c
Location:line 693, column 5
Description:Value stored to 'originalvp' is never read

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 * Portions Copyright (c) 2007-2008 Sine Nomine Associates
10 */
11
12#include <afsconfig.h>
13#include <afs/param.h>
14
15#include <roken.h>
16
17#include <rx/xdr.h>
18#include <rx/rx.h>
19#include <rx/rxkad.h>
20#include <afs/afsint.h>
21#include <afs/afs_assert.h>
22#include <afs/prs_fs.h>
23#include <afs/nfs.h>
24#include <lwp.h>
25#include <lock.h>
26#include <afs/cellconfig.h>
27#include <afs/keys.h>
28#include <ubik.h>
29#include <afs/ihandle.h>
30#ifdef AFS_NT40_ENV
31#include <afs/ntops.h>
32#endif
33#include <afs/vnode.h>
34#include <afs/volume.h>
35#include <afs/volume_inline.h>
36#include <afs/partition.h>
37#include "vol.h"
38#include <afs/daemon_com.h>
39#include <afs/fssync.h>
40#include <afs/acl.h>
41#include "afs/audit.h"
42#include <afs/dir.h>
43#include <afs/afsutil.h>
44#include <afs/com_err.h>
45#include <afs/vol_prototypes.h>
46#include <afs/errors.h>
47
48#include "volser.h"
49#include "voltrans_inline.h"
50#include "volint.h"
51
52#include "volser_internal.h"
53#include "physio.h"
54#include "dumpstuff.h"
55
56extern int DoLogging;
57extern struct afsconf_dir *tdir;
58
59extern void LogError(afs_int32 errcode);
60
61/* Forward declarations */
62static int GetPartName(afs_int32 partid, char *pname);
63
64#define OneDay(24*60*60) (24*60*60)
65
66#ifdef AFS_NT40_ENV
67#define ENOTCONN57 134
68#endif
69
70afs_int32 localTid = 1;
71
72static afs_int32 VolPartitionInfo(struct rx_call *, char *pname,
73 struct diskPartition64 *);
74static afs_int32 VolNukeVolume(struct rx_call *, afs_int32, afs_uint32);
75static afs_int32 VolCreateVolume(struct rx_call *, afs_int32, char *,
76 afs_int32, afs_uint32, afs_uint32 *,
77 afs_int32 *);
78static afs_int32 VolDeleteVolume(struct rx_call *, afs_int32);
79static afs_int32 VolClone(struct rx_call *, afs_int32, afs_uint32,
80 afs_int32, char *, afs_uint32 *);
81static afs_int32 VolReClone(struct rx_call *, afs_int32, afs_int32);
82static afs_int32 VolTransCreate(struct rx_call *, afs_uint32, afs_int32,
83 afs_int32, afs_int32 *);
84static afs_int32 VolGetNthVolume(struct rx_call *, afs_int32, afs_uint32 *,
85 afs_int32 *);
86static afs_int32 VolGetFlags(struct rx_call *, afs_int32, afs_int32 *);
87static afs_int32 VolSetFlags(struct rx_call *, afs_int32, afs_int32 );
88static afs_int32 VolForward(struct rx_call *, afs_int32, afs_int32,
89 struct destServer *destination, afs_int32,
90 struct restoreCookie *cookie);
91static afs_int32 VolDump(struct rx_call *, afs_int32, afs_int32, afs_int32);
92static afs_int32 VolRestore(struct rx_call *, afs_int32, afs_int32,
93 struct restoreCookie *);
94static afs_int32 VolEndTrans(struct rx_call *, afs_int32, afs_int32 *);
95static afs_int32 VolSetForwarding(struct rx_call *, afs_int32, afs_int32);
96static afs_int32 VolGetStatus(struct rx_call *, afs_int32,
97 struct volser_status *);
98static afs_int32 VolSetInfo(struct rx_call *, afs_int32, struct volintInfo *);
99static afs_int32 VolGetName(struct rx_call *, afs_int32, char **);
100static afs_int32 VolListPartitions(struct rx_call *, struct pIDs *);
101static afs_int32 XVolListPartitions(struct rx_call *, struct partEntries *);
102static afs_int32 VolListOneVolume(struct rx_call *, afs_int32, afs_uint32,
103 volEntries *);
104static afs_int32 VolXListOneVolume(struct rx_call *, afs_int32, afs_uint32,
105 volXEntries *);
106static afs_int32 VolListVolumes(struct rx_call *, afs_int32, afs_int32,
107 volEntries *);
108static afs_int32 VolXListVolumes(struct rx_call *, afs_int32, afs_int32,
109 volXEntries *);
110static afs_int32 VolMonitor(struct rx_call *, transDebugEntries *);
111static afs_int32 VolSetIdsTypes(struct rx_call *, afs_int32, char [],
112 afs_int32, afs_uint32, afs_uint32,
113 afs_uint32);
114static afs_int32 VolSetDate(struct rx_call *, afs_int32, afs_int32);
115
116/* this call unlocks all of the partition locks we've set */
117int
118VPFullUnlock_r(void)
119{
120 struct DiskPartition64 *tp;
121 for (tp = DiskPartitionList; tp; tp = tp->next) {
122 if (tp->lock_fd != INVALID_FD((FD_t)-1)) {
123 OS_CLOSE(tp->lock_fd)close(tp->lock_fd);
124 tp->lock_fd = INVALID_FD((FD_t)-1);
125 }
126 }
127 return 0;
128}
129
130int
131VPFullUnlock(void)
132{
133 int code;
134 VOL_LOCK;
135 code = VPFullUnlock_r();
136 VOL_UNLOCK;
137 return code;
138}
139
140/* get partition id from a name */
141afs_int32
142PartitionID(char *aname)
143{
144 char tc;
145 int code = 0;
146 char ascii[3];
147
148 tc = *aname;
149 if (tc == 0)
150 return -1; /* unknown */
151
152 /* otherwise check for vicepa or /vicepa, or just plain "a" */
153 ascii[2] = 0;
154 if (!strncmp(aname, "/vicep", 6)) {
155 strncpy(ascii, aname + 6, 2);
156 } else
157 return -1; /* bad partition name */
158 /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, and are numbered
159 * from 0. Do the appropriate conversion */
160 if (ascii[1] == 0) {
161 /* one char name, 0..25 */
162 if (ascii[0] < 'a' || ascii[0] > 'z')
163 return -1; /* wrongo */
164 return ascii[0] - 'a';
165 } else {
166 /* two char name, 26 .. <whatever> */
167 if (ascii[0] < 'a' || ascii[0] > 'z')
168 return -1; /* wrongo */
169 if (ascii[1] < 'a' || ascii[1] > 'z')
170 return -1; /* just as bad */
171 code = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
172 if (code > VOLMAXPARTS255)
173 return -1;
174 return code;
175 }
176}
177
178static int
179ConvertVolume(afs_uint32 avol, char *aname, afs_int32 asize)
180{
181 if (asize < 18)
182 return -1;
183 /* It's better using the Generic VFORMAT since otherwise we have to make changes to too many places... The 14 char limitation in names hits us again in AIX; print in field of 9 digits (still 10 for the rest), right justified with 0 padding */
184 snprintf(aname, asize, VFORMAT"V%010lu.vol", (unsigned long)avol);
185 return 0;
186}
187
188static int
189ConvertPartition(int apartno, char *aname, int asize)
190{
191 if (asize < 10)
192 return E2BIG7;
193 if (apartno < 0)
194 return EINVAL22;
195 strcpy(aname, "/vicep");
196 if (apartno < 26) {
197 aname[6] = 'a' + apartno;
198 aname[7] = 0;
199 } else {
200 apartno -= 26;
201 aname[6] = 'a' + (apartno / 26);
202 aname[7] = 'a' + (apartno % 26);
203 aname[8] = 0;
204 }
205 return 0;
206}
207
208#ifdef AFS_DEMAND_ATTACH_FS
209/* normally we should use the regular salvaging functions from the volume
210 * package, but this is a special case where we have a volume ID, but no
211 * volume structure to give the volume package */
212static void
213SalvageUnknownVolume(VolumeId volid, char *part)
214{
215 afs_int32 code;
216
217 Log("Scheduling salvage for allegedly nonexistent volume %lu part %s\n",
218 afs_printable_uint32_lu(volid), part);
219
220 code = FSYNC_VolOp(volid, part, FSYNC_VOL_FORCE_ERROR,
221 FSYNC_SALVAGE, NULL((void *)0));
222 if (code) {
223 Log("SalvageUnknownVolume: error %ld trying to salvage vol %lu part %s\n",
224 afs_printable_int32_ld(code), afs_printable_uint32_lu(volid),
225 part);
226 }
227}
228#endif /* AFS_DEMAND_ATTACH_FS */
229
230static struct Volume *
231VAttachVolumeByName_retry(Errorbit32 *ec, char *partition, char *name, int mode)
232{
233 struct Volume *vp;
234
235 *ec = 0;
236 vp = VAttachVolumeByName(ec, partition, name, mode);
237
238#ifdef AFS_DEMAND_ATTACH_FS
239 {
240 int i;
241 /*
242 * The fileserver will take care of keeping track of how many
243 * demand-salvages have been performed, and will force the volume to
244 * ERROR if we've done too many. The limit on This loop is just a
245 * failsafe to prevent trying to salvage forever. We want to attempt
246 * attachment at least SALVAGE_COUNT_MAX times, since we want to
247 * avoid prematurely exiting this loop, if we can.
248 */
249 for (i = 0; i < SALVAGE_COUNT_MAX*2 && *ec == VSALVAGING113; i++) {
250 sleep(SALVAGE_PRIO_UPDATE_INTERVAL);
251 vp = VAttachVolumeByName(ec, partition, name, mode);
252 }
253
254 if (*ec == VSALVAGING113) {
255 *ec = VSALVAGE101;
256 }
257 }
258#endif /* AFS_DEMAND_ATTACH_FS */
259
260 return vp;
261}
262
263static struct Volume *
264VAttachVolume_retry(Errorbit32 *ec, afs_uint32 avolid, int amode)
265{
266 struct Volume *vp;
267
268 *ec = 0;
269 vp = VAttachVolume(ec, avolid, amode);
270
271#ifdef AFS_DEMAND_ATTACH_FS
272 {
273 int i;
274 /* see comment above in VAttachVolumeByName_retry */
275 for (i = 0; i < SALVAGE_COUNT_MAX*2 && *ec == VSALVAGING113; i++) {
276 sleep(SALVAGE_PRIO_UPDATE_INTERVAL);
277 vp = VAttachVolume(ec, avolid, amode);
278 }
279
280 if (*ec == VSALVAGING113) {
281 *ec = VSALVAGE101;
282 }
283 }
284#endif /* AFS_DEMAND_ATTACH_FS */
285
286 return vp;
287}
288
289/* the only attach function that takes a partition is "...ByName", so we use it */
290static struct Volume *
291XAttachVolume(afs_int32 *error, afs_uint32 avolid, afs_int32 apartid, int amode)
292{
293 char pbuf[30], vbuf[20];
294
295 if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
296 *error = EINVAL22;
297 return NULL((void *)0);
298 }
299 if (ConvertVolume(avolid, vbuf, sizeof(vbuf))) {
300 *error = EINVAL22;
301 return NULL((void *)0);
302 }
303
304 return VAttachVolumeByName_retry((Errorbit32 *)error, pbuf, vbuf, amode);
305}
306
307/* Adapted from the file server; create a root directory for this volume */
308static Errorbit32
309ViceCreateRoot(Volume *vp)
310{
311 DirHandle dir;
312 struct acl_accessList *ACL;
313 AFSFid did;
314 Inode inodeNumber, nearInode;
315 struct VnodeDiskObject *vnode;
316 struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge0];
317 IHandle_t *h;
318 FdHandle_t *fdP;
319 afs_fsize_t length;
320 ssize_t nBytes;
321
322 vnode = (struct VnodeDiskObject *)malloc(SIZEOF_LARGEDISKVNODE256);
323 if (!vnode)
324 return ENOMEM12;
325 memset(vnode, 0, SIZEOF_LARGEDISKVNODE256);
326
327 V_pref(vp, nearInode)nearInode = 0;
328 inodeNumber =
329 IH_CREATE(V_linkHandle(vp), V_device(vp),namei_icreate(((vp)->linkHandle), VPartitionPath(((vp)->
partition)), ((vp)->header->diskstuff.parentId), 1, 1, 0
)
330 VPartitionPath(V_partition(vp)), nearInode, V_parentId(vp),namei_icreate(((vp)->linkHandle), VPartitionPath(((vp)->
partition)), ((vp)->header->diskstuff.parentId), 1, 1, 0
)
331 1, 1, 0)namei_icreate(((vp)->linkHandle), VPartitionPath(((vp)->
partition)), ((vp)->header->diskstuff.parentId), 1, 1, 0
)
;
332 if (!VALID_INO(inodeNumber)((inodeNumber) != (Inode)-1 && (inodeNumber) != (Inode
)0)
) {
333 Log("ViceCreateRoot: IH_CREATE: %s\n", afs_error_message(errno(* __error())));
334 free(vnode);
335 return EIO5;
336 }
337
338 SetSalvageDirHandle(&dir, V_parentId(vp)((vp)->header->diskstuff.parentId), vp->device, inodeNumber);
339 did.Volume = V_id(vp)((vp)->header->diskstuff.id);
340 did.Vnode = (VnodeId) 1;
341 did.Unique = 1;
342
343 osi_Assert(!(afs_dir_MakeDir(&dir, (afs_int32 *)&did, (afs_int32 *)&did)))(void)((!(afs_dir_MakeDir(&dir, (afs_int32 *)&did, (afs_int32
*)&did))) || (osi_AssertFailU("!(afs_dir_MakeDir(&dir, (afs_int32 *)&did, (afs_int32 *)&did))"
, "volprocs.c", 343), 0))
;
344 DFlush(); /* flush all modified dir buffers out */
345 DZap(&dir); /* Remove all buffers for this dir */
346 length = afs_dir_Length(&dir); /* Remember size of this directory */
347
348 FidZap(&dir); /* Done with the dir handle obtained via SetSalvageDirHandle() */
349
350 /* build a single entry ACL that gives all rights to system:administrators */
351 /* this section of code assumes that access list format is not going to
352 * change
353 */
354 ACL = VVnodeDiskACL(vnode)((AL_AccessList *) (((byte *)(vnode))+64));
355 ACL->size = sizeof(struct acl_accessList);
356 ACL->version = ACL_ACLVERSION1;
357 ACL->total = 1;
358 ACL->positive = 1;
359 ACL->negative = 0;
360 ACL->entries[0].id = -204; /* this assumes System:administrators is group -204 */
361 ACL->entries[0].rights =
362 PRSFS_READ1 | PRSFS_WRITE2 | PRSFS_INSERT4 | PRSFS_LOOKUP8 | PRSFS_DELETE16
363 | PRSFS_LOCK32 | PRSFS_ADMINISTER64;
364
365 vnode->type = vDirectory2;
366 vnode->cloned = 0;
367 vnode->modeBits = 0777;
368 vnode->linkCount = 2;
369 VNDISK_SET_LEN(vnode, length)((vnode)->vn_length_hi) = ((afs_int64)length) >> 32;
((vnode)->length) = (length) & 0xFFFFFFFF;
;
370 vnode->uniquifier = 1;
371 V_uniquifier(vp)((vp)->header->diskstuff.uniquifier) = vnode->uniquifier + 1;
372 vnode->dataVersion = 1;
373 VNDISK_SET_INO(vnode, inodeNumber)((vnode)->vn_ino_lo = (int)(inodeNumber&0xffffffff), (
(vnode)->vn_ino_hi = (inodeNumber) ? (int)(((inodeNumber)>>
32)&0xffffffff) : 0))
;
374 vnode->unixModifyTime = vnode->serverModifyTime = V_creationDate(vp)((vp)->header->diskstuff.creationDate);
375 vnode->author = 0;
376 vnode->owner = 0;
377 vnode->parent = 0;
378 vnode->vnodeMagic = vcp->magic;
379
380 IH_INIT(h, vp->device, V_parentId(vp),((h) = ih_init((vp->device), (((vp)->header->diskstuff
.parentId)), (vp->vnodeIndex[0].handle->ih_ino)))
381 vp->vnodeIndex[vLarge].handle->ih_ino)((h) = ih_init((vp->device), (((vp)->header->diskstuff
.parentId)), (vp->vnodeIndex[0].handle->ih_ino)))
;
382 fdP = IH_OPEN(h)ih_open(h);
383 osi_Assert(fdP != NULL)(void)((fdP != ((void *)0)) || (osi_AssertFailU("fdP != NULL"
, "volprocs.c", 383), 0))
;
384 nBytes = FDH_PWRITE(fdP, vnode, SIZEOF_LARGEDISKVNODE, vnodeIndexOffset(vcp, 1))pwrite((fdP)->fd_fd, vnode, 256, (((((1)-1)>>1)+1)<<
(vcp)->logSize))
;
385 osi_Assert(nBytes == SIZEOF_LARGEDISKVNODE)(void)((nBytes == 256) || (osi_AssertFailU("nBytes == SIZEOF_LARGEDISKVNODE"
, "volprocs.c", 385), 0))
;
386 FDH_REALLYCLOSE(fdP)(fd_reallyclose(fdP), (fdP)=((void *)0), 0);
387 IH_RELEASE(h)(ih_release(h), (h)=((void *)0), 0);
388 VNDISK_GET_LEN(length, vnode)(length) = ((afs_int64)((vnode)->vn_length_hi) << 32
) | ((vnode)->length);
;
389 V_diskused(vp)((vp)->header->diskstuff.diskused) = nBlocks(length)((afs_sfsize_t)((length) == 0? 1: (((afs_sfsize_t)(length))+1023
)/1024))
;
390
391 free(vnode);
392 return 0;
393}
394
395afs_int32
396SAFSVolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition
397 *partition)
398{
399 afs_int32 code;
400 struct diskPartition64 *dp = (struct diskPartition64 *)
401 malloc(sizeof(struct diskPartition64));
402
403 code = VolPartitionInfo(acid, pname, dp);
404 if (!code) {
405 strncpy(partition->name, dp->name, 32);
406 strncpy(partition->devName, dp->devName, 32);
407 partition->lock_fd = dp->lock_fd;
408 partition->free=RoundInt64ToInt32(dp->free)(dp->free > 0xFFFFFFFF) ? 0xFFFFFFFF : dp->free;;
409 partition->minFree=RoundInt64ToInt32(dp->minFree)(dp->minFree > 0xFFFFFFFF) ? 0xFFFFFFFF : dp->minFree
;
;
410 }
411 free(dp);
412 osi_auditU(acid, VS_ParInfEvent"AFS_VS_ParInf", code, AUD_STR1, pname, AUD_END0);
413 return code;
414}
415
416afs_int32
417SAFSVolPartitionInfo64(struct rx_call *acid, char *pname, struct diskPartition64
418 *partition)
419{
420 afs_int32 code;
421
422 code = VolPartitionInfo(acid, pname, partition);
423 osi_auditU(acid, VS_ParInfEvent"AFS_VS_ParInf", code, AUD_STR1, pname, AUD_END0);
424 return code;
425}
426
427afs_int32
428VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition64
429 *partition)
430{
431 struct DiskPartition64 *dp;
432
433/*
434 if (!afsconf_SuperUser(tdir, acid, caller)) return VOLSERBAD_ACCESS;
435*/
436 VResetDiskUsage();
437 dp = VGetPartition(pname, 0);
438 if (dp) {
439 strncpy(partition->name, dp->name, 32);
440 strncpy(partition->devName, dp->devName, 32);
441 partition->lock_fd = (int)dp->lock_fd;
442 partition->free = dp->free;
443 partition->minFree = dp->totalUsable;
444 return 0;
445 } else
446 return VOLSERILLEGAL_PARTITION(1492325125L);
447}
448
449/* obliterate a volume completely, and slowly. */
450afs_int32
451SAFSVolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_uint32 avolID)
452{
453 afs_int32 code;
454
455 code = VolNukeVolume(acid, apartID, avolID);
456 osi_auditU(acid, VS_NukVolEvent"AFS_VS_NukVol", code, AUD_LONG5, avolID, AUD_END0);
457 return code;
458}
459
460static afs_int32
461VolNukeVolume(struct rx_call *acid, afs_int32 apartID, afs_uint32 avolID)
462{
463 char partName[50];
464 afs_int32 error;
465 Errorbit32 verror;
466 afs_int32 code;
467 struct Volume *tvp;
468 char caller[MAXKTCNAMELEN64];
469
470 /* check for access */
471 if (!afsconf_SuperUser(tdir, acid, caller))
472 return VOLSERBAD_ACCESS(1492325127L);
473 if (DoLogging)
474 Log("%s is executing VolNukeVolume %u\n", caller, avolID);
475
476 if (volutil_PartitionName2_r(apartID, partName, sizeof(partName)) != 0)
477 return VOLSERNOVOL(1492325135L);
478 /* we first try to attach the volume in update mode, so that the file
479 * server doesn't try to use it (and abort) while (or after) we delete it.
480 * If we don't get the volume, that's fine, too. We just won't put it back.
481 */
482 tvp = XAttachVolume(&error, avolID, apartID, V_VOLUPD3);
483 code = nuke(partName, avolID);
484 if (tvp)
485 VDetachVolume(&verror, tvp);
486 return code;
487}
488
489/* create a new volume, with name aname, on the specified partition (1..n)
490 * and of type atype (readwriteVolume, readonlyVolume, backupVolume).
491 * As input, if *avolid is 0, we allocate a new volume id, otherwise we use *avolid
492 * for the volume id (useful for things like volume restore).
493 * Return the new volume id in *avolid.
494 */
495afs_int32
496SAFSVolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
497 afs_int32 atype, afs_uint32 aparent, afs_uint32 *avolid,
498 afs_int32 *atrans)
499{
500 afs_int32 code;
501
502 code =
503 VolCreateVolume(acid, apart, aname, atype, aparent, avolid, atrans);
504 osi_auditU(acid, VS_CrVolEvent"AFS_VS_CrVol", code, AUD_LONG5, *atrans, AUD_LONG5,
505 *avolid, AUD_STR1, aname, AUD_LONG5, atype, AUD_LONG5, aparent,
506 AUD_END0);
507 return code;
508}
509
510static afs_int32
511VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
512 afs_int32 atype, afs_uint32 aparent, afs_uint32 *avolid,
513 afs_int32 *atrans)
514{
515 Errorbit32 error;
516 Volume *vp;
517 Errorbit32 junk; /* discardable error code */
518 afs_uint32 volumeID;
519 afs_int32 doCreateRoot = 1;
520 struct volser_trans *tt;
521 char ppath[30];
522 char caller[MAXKTCNAMELEN64];
523
524 if (strlen(aname) > 31)
525 return VOLSERBADNAME(1492325129L);
526 if (!afsconf_SuperUser(tdir, acid, caller))
527 return VOLSERBAD_ACCESS(1492325127L);
528 if (DoLogging)
529 Log("%s is executing CreateVolume '%s'\n", caller, aname);
530 if ((error = ConvertPartition(apart, ppath, sizeof(ppath))))
531 return error; /*a standard unix error */
532 if (atype != readwriteVolume0 && atype != readonlyVolume1
533 && atype != backupVolume2)
534 return EINVAL22;
535 if ((volumeID = *avolid) == 0) {
536
537 Log("1 Volser: CreateVolume: missing volume number; %s volume not created\n", aname);
538 return E2BIG7;
539
540 }
541 if ((aparent == volumeID) && (atype == readwriteVolume0)) {
542 doCreateRoot = 0;
543 }
544 if (aparent == 0)
545 aparent = volumeID;
546 tt = NewTrans(volumeID, apart);
547 if (!tt) {
548 Log("1 createvolume: failed to create trans\n");
549 return VOLSERVOLBUSY(1492325133L); /* volume already busy! */
550 }
551 vp = VCreateVolume(&error, ppath, volumeID, aparent);
552 if (error) {
553#ifdef AFS_DEMAND_ATTACH_FS
554 if (error != VVOLEXISTS104 && error != EXDEV18) {
555 SalvageUnknownVolume(volumeID, ppath);
556 }
557#endif
558 Log("1 Volser: CreateVolume: Unable to create the volume; aborted, error code %u\n", error);
559 LogError(error);
560 DeleteTrans(tt, 1);
561 return EIO5;
562 }
563 V_uniquifier(vp)((vp)->header->diskstuff.uniquifier) = 1;
564 V_updateDate(vp)((vp)->header->diskstuff.updateDate) = V_creationDate(vp)((vp)->header->diskstuff.creationDate) = V_copyDate(vp)((vp)->header->diskstuff.copyDate);
565 V_inService(vp)((vp)->header->diskstuff.inService) = V_blessed(vp)((vp)->header->diskstuff.blessed) = 1;
566 V_type(vp)((vp)->header->diskstuff.type) = atype;
567 AssignVolumeName(&V_disk(vp)((vp)->header->diskstuff), aname, 0);
568 if (doCreateRoot) {
569 error = ViceCreateRoot(vp);
570 if (error) {
571 Log("1 Volser: CreateVolume: Unable to create volume root dir; "
572 "error code %u\n", (unsigned)error);
573 DeleteTrans(tt, 1);
574 V_needsSalvaged(vp)((vp)->header->diskstuff.needsSalvaged) = 1;
575 VDetachVolume(&junk, vp);
576 return EIO5;
577 }
578 }
579 V_destroyMe(vp)((vp)->header->diskstuff.destroyMe) = DESTROY_ME0xD3;
580 V_inService(vp)((vp)->header->diskstuff.inService) = 0;
581 V_maxquota(vp)((vp)->header->diskstuff.maxquota) = 5000; /* set a quota of 5000 at init time */
582 VUpdateVolume(&error, vp);
583 if (error) {
584 Log("1 Volser: create UpdateVolume failed, code %d\n", error);
585 LogError(error);
586 DeleteTrans(tt, 1);
587 VDetachVolume(&junk, vp); /* rather return the real error code */
588 return error;
589 }
590 VTRANS_OBJ_LOCK(tt);
591 tt->volume = vp;
592 *atrans = tt->tid;
593 TSetRxCall_r(tt, acid, "CreateVolume");
594 VTRANS_OBJ_UNLOCK(tt);
595 Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
596 TClearRxCall(tt);
597 if (TRELE(tt))
598 return VOLSERTRELE_ERROR(1492325120L);
599 return 0;
600}
601
602/* delete the volume associated with this transaction */
603afs_int32
604SAFSVolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
605{
606 afs_int32 code;
607
608 code = VolDeleteVolume(acid, atrans);
609 osi_auditU(acid, VS_DelVolEvent"AFS_VS_DelVol", code, AUD_LONG5, atrans, AUD_END0);
610 return code;
611}
612
613static afs_int32
614VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
615{
616 struct volser_trans *tt;
617 Errorbit32 error;
618 char caller[MAXKTCNAMELEN64];
619
620 if (!afsconf_SuperUser(tdir, acid, caller))
621 return VOLSERBAD_ACCESS(1492325127L);
622 tt = FindTrans(atrans);
623 if (!tt)
624 return ENOENT2;
625 if (tt->vflags & VTDeleted4) {
626 Log("1 Volser: Delete: volume %u already deleted \n", tt->volid);
627 TRELE(tt);
628 return ENOENT2;
629 }
630 if (DoLogging)
631 Log("%s is executing Delete Volume %u\n", caller, tt->volid);
632 TSetRxCall(tt, acid, "DeleteVolume");
633 VPurgeVolume(&error, tt->volume); /* don't check error code, it is not set! */
634 V_destroyMe(tt->volume)((tt->volume)->header->diskstuff.destroyMe) = DESTROY_ME0xD3;
635 if (tt->volume->needsPutBack) {
636 tt->volume->needsPutBack = VOL_PUTBACK_DELETE2; /* so endtrans does the right fssync opcode */
637 }
638 VTRANS_OBJ_LOCK(tt);
639 tt->vflags |= VTDeleted4; /* so we know not to do anything else to it */
640 TClearRxCall_r(tt);
641 VTRANS_OBJ_UNLOCK(tt);
642 if (TRELE(tt))
643 return VOLSERTRELE_ERROR(1492325120L);
644
645 Log("1 Volser: Delete: volume %u deleted \n", tt->volid);
646 return 0; /* vpurgevolume doesn't set an error code */
647}
648
649/* make a clone of the volume associated with atrans, possibly giving it a new
650 * number (allocate a new number if *newNumber==0, otherwise use *newNumber
651 * for the clone's id). The new clone is given the name newName. Finally,
652 * due to efficiency considerations, if purgeId is non-zero, we purge that
653 * volume when doing the clone operation. This may be useful when making
654 * new backup volumes, for instance since the net result of a clone and a
655 * purge generally leaves many inode ref counts the same, while doing them
656 * separately would result in far more iincs and idecs being peformed
657 * (and they are slow operations).
658 */
659/* for efficiency reasons, sometimes faster to piggyback a purge here */
660afs_int32
661SAFSVolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
662 afs_int32 newType, char *newName, afs_uint32 *newNumber)
663{
664 afs_int32 code;
665
666 code = VolClone(acid, atrans, purgeId, newType, newName, newNumber);
667 osi_auditU(acid, VS_CloneEvent"AFS_VS_Clone", code, AUD_LONG5, atrans, AUD_LONG5, purgeId,
668 AUD_STR1, newName, AUD_LONG5, newType, AUD_LONG5, *newNumber,
669 AUD_END0);
670 return code;
671}
672
673static afs_int32
674VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
675 afs_int32 newType, char *newName, afs_uint32 *newNumber)
676{
677 afs_uint32 newId;
678 struct Volume *originalvp, *purgevp, *newvp;
679 Errorbit32 error, code;
680 struct volser_trans *tt, *ttc;
681 char caller[MAXKTCNAMELEN64];
682#ifdef AFS_DEMAND_ATTACH_FS
683 struct Volume *salv_vp = NULL((void *)0);
684#endif
685
686 if (strlen(newName) > 31)
687 return VOLSERBADNAME(1492325129L);
688 if (!afsconf_SuperUser(tdir, acid, caller))
689 return VOLSERBAD_ACCESS(1492325127L); /*not a super user */
690 if (DoLogging)
691 Log("%s is executing Clone Volume new name=%s\n", caller, newName);
692 error = 0;
693 originalvp = (Volume *) 0;
Value stored to 'originalvp' is never read
694 purgevp = (Volume *) 0;
695 newvp = (Volume *) 0;
696 tt = ttc = (struct volser_trans *)0;
697
698 if (!newNumber || !*newNumber) {
699 Log("1 Volser: Clone: missing volume number for the clone; aborted\n");
700 goto fail;
701 }
702 newId = *newNumber;
703
704 if (newType != readonlyVolume1 && newType != backupVolume2)
705 return EINVAL22;
706 tt = FindTrans(atrans);
707 if (!tt)
708 return ENOENT2;
709 if (tt->vflags & VTDeleted4) {
710 Log("1 Volser: Clone: volume %u has been deleted \n", tt->volid);
711 TRELE(tt);
712 return ENOENT2;
713 }
714 ttc = NewTrans(newId, tt->partition);
715 if (!ttc) { /* someone is messing with the clone already */
716 TRELE(tt);
717 return VOLSERVOLBUSY(1492325133L);
718 }
719 TSetRxCall(tt, acid, "Clone");
720
721
722 if (purgeId) {
723 purgevp = VAttachVolume_retry(&error, purgeId, V_VOLUPD3);
724 if (error) {
725 Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
726 goto fail;
727 }
728 } else {
729 purgevp = NULL((void *)0);
730 }
731 originalvp = tt->volume;
732 if ((V_type(originalvp)((originalvp)->header->diskstuff.type) == backupVolume2)
733 || (V_type(originalvp)((originalvp)->header->diskstuff.type) == readonlyVolume1)) {
734 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
735 error = EROFS30;
736 goto fail;
737 }
738 if ((V_destroyMe(originalvp)((originalvp)->header->diskstuff.destroyMe) == DESTROY_ME0xD3) || !V_inService(originalvp)((originalvp)->header->diskstuff.inService)) {
739 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
740 V_id(originalvp)((originalvp)->header->diskstuff.id));
741 error = VOFFLINE106;
742 goto fail;
743 }
744 if (purgevp) {
745 if (originalvp->device != purgevp->device) {
746 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n", tt->volid, purgeId);
747 error = EXDEV18;
748 goto fail;
749 }
750 if (V_type(purgevp)((purgevp)->header->diskstuff.type) != readonlyVolume1) {
751 Log("1 Volser: Clone: The \"purge\" volume must be a read only volume; aborted\n");
752 error = EINVAL22;
753 goto fail;
754 }
755 if (V_type(originalvp)((originalvp)->header->diskstuff.type) == readonlyVolume1
756 && V_parentId(originalvp)((originalvp)->header->diskstuff.parentId) != V_parentId(purgevp)((purgevp)->header->diskstuff.parentId)) {
757 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, purgeId);
758 error = EXDEV18;
759 goto fail;
760 }
761 if (V_type(originalvp)((originalvp)->header->diskstuff.type) == readwriteVolume0
762 && tt->volid != V_parentId(purgevp)((purgevp)->header->diskstuff.parentId)) {
763 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", purgeId, tt->volid);
764 error = EXDEV18;
765 goto fail;
766 }
767 }
768
769 error = 0;
770#ifdef AFS_DEMAND_ATTACH_FS
771 salv_vp = originalvp;
772#endif
773
774 newvp =
775 VCreateVolume(&error, originalvp->partition->name, newId,
776 V_parentId(originalvp)((originalvp)->header->diskstuff.parentId));
777 if (error) {
778 Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n");
779 newvp = (Volume *) 0;
780 goto fail;
781 }
782 if (newType == readonlyVolume1)
783 V_cloneId(originalvp)((originalvp)->header->diskstuff.cloneId) = newId;
784 Log("1 Volser: Clone: Cloning volume %u to new volume %u\n", tt->volid,
785 newId);
786 if (purgevp)
787 Log("1 Volser: Clone: Purging old read only volume %u\n", purgeId);
788 CloneVolume(&error, originalvp, newvp, purgevp);
789 purgevp = NULL((void *)0); /* clone releases it, maybe even if error */
790 if (error) {
791 Log("1 Volser: Clone: clone operation failed with code %u\n", error);
792 LogError(error);
793 goto fail;
794 }
795 if (newType == readonlyVolume1) {
796 AssignVolumeName(&V_disk(newvp)((newvp)->header->diskstuff), V_name(originalvp)((originalvp)->header->diskstuff.name), ".readonly");
797 V_type(newvp)((newvp)->header->diskstuff.type) = readonlyVolume1;
798 } else if (newType == backupVolume2) {
799 AssignVolumeName(&V_disk(newvp)((newvp)->header->diskstuff), V_name(originalvp)((originalvp)->header->diskstuff.name), ".backup");
800 V_type(newvp)((newvp)->header->diskstuff.type) = backupVolume2;
801 V_backupId(originalvp)((originalvp)->header->diskstuff.backupId) = newId;
802 }
803 strcpy(newvp->header->diskstuff.name, newName);
804 V_creationDate(newvp)((newvp)->header->diskstuff.creationDate) = V_copyDate(newvp)((newvp)->header->diskstuff.copyDate);
805 ClearVolumeStats(&V_disk(newvp)((newvp)->header->diskstuff));
806 V_destroyMe(newvp)((newvp)->header->diskstuff.destroyMe) = DESTROY_ME0xD3;
807 V_inService(newvp)((newvp)->header->diskstuff.inService) = 0;
808 if (newType == backupVolume2) {
809 V_backupDate(originalvp)((originalvp)->header->diskstuff.backupDate) = V_copyDate(newvp)((newvp)->header->diskstuff.copyDate);
810 V_backupDate(newvp)((newvp)->header->diskstuff.backupDate) = V_copyDate(newvp)((newvp)->header->diskstuff.copyDate);
811 }
812 V_inUse(newvp)((newvp)->header->diskstuff.inUse) = 0;
813 VUpdateVolume(&error, newvp);
814 if (error) {
815 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
816 LogError(error);
817 goto fail;
818 }
819 VDetachVolume(&error, newvp); /* allow file server to get it's hands on it */
820 newvp = NULL((void *)0);
821 VUpdateVolume(&error, originalvp);
822 if (error) {
823 Log("1 Volser: Clone: original update %u\n", error);
824 LogError(error);
825 goto fail;
826 }
827 TClearRxCall(tt);
828#ifdef AFS_DEMAND_ATTACH_FS
829 salv_vp = NULL((void *)0);
830#endif
831 if (TRELE(tt)) {
832 tt = (struct volser_trans *)0;
833 error = VOLSERTRELE_ERROR(1492325120L);
834 goto fail;
835 }
836 DeleteTrans(ttc, 1);
837 return 0;
838
839 fail:
840 if (purgevp)
841 VDetachVolume(&code, purgevp);
842 if (newvp)
843 VDetachVolume(&code, newvp);
844 if (tt) {
845 TClearRxCall(tt);
846 TRELE(tt);
847 }
848 if (ttc)
849 DeleteTrans(ttc, 1);
850#ifdef AFS_DEMAND_ATTACH_FS
851 if (salv_vp && error != VVOLEXISTS104 && error != EXDEV18) {
852 V_needsSalvaged(salv_vp)((salv_vp)->header->diskstuff.needsSalvaged) = 1;
853 }
854#endif /* AFS_DEMAND_ATTACH_FS */
855 return error;
856}
857
858/* reclone this volume into the specified id */
859afs_int32
860SAFSVolReClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 cloneId)
861{
862 afs_int32 code;
863
864 code = VolReClone(acid, atrans, cloneId);
865 osi_auditU(acid, VS_ReCloneEvent"AFS_VS_ReClone", code, AUD_LONG5, atrans, AUD_LONG5,
866 cloneId, AUD_END0);
867 return code;
868}
869
870static afs_int32
871VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
872{
873 struct Volume *originalvp, *clonevp;
874 Errorbit32 error, code;
875 afs_int32 newType;
876 struct volser_trans *tt, *ttc;
877 char caller[MAXKTCNAMELEN64];
878
879 /*not a super user */
880 if (!afsconf_SuperUser(tdir, acid, caller))
881 return VOLSERBAD_ACCESS(1492325127L);
882 if (DoLogging)
883 Log("%s is executing Reclone Volume %u\n", caller, cloneId);
884 error = 0;
885 clonevp = originalvp = (Volume *) 0;
886 tt = (struct volser_trans *)0;
887
888 tt = FindTrans(atrans);
889 if (!tt)
890 return ENOENT2;
891 if (tt->vflags & VTDeleted4) {
892 Log("1 Volser: VolReClone: volume %u has been deleted \n", tt->volid);
893 TRELE(tt);
894 return ENOENT2;
895 }
896 ttc = NewTrans(cloneId, tt->partition);
897 if (!ttc) { /* someone is messing with the clone already */
898 TRELE(tt);
899 return VOLSERVOLBUSY(1492325133L);
900 }
901 TSetRxCall(tt, acid, "ReClone");
902
903 originalvp = tt->volume;
904 if ((V_type(originalvp)((originalvp)->header->diskstuff.type) == backupVolume2)
905 || (V_type(originalvp)((originalvp)->header->diskstuff.type) == readonlyVolume1)) {
906 Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n");
907 error = EROFS30;
908 goto fail;
909 }
910 if ((V_destroyMe(originalvp)((originalvp)->header->diskstuff.destroyMe) == DESTROY_ME0xD3) || !V_inService(originalvp)((originalvp)->header->diskstuff.inService)) {
911 Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n",
912 V_id(originalvp)((originalvp)->header->diskstuff.id));
913 error = VOFFLINE106;
914 goto fail;
915 }
916
917 clonevp = VAttachVolume_retry(&error, cloneId, V_VOLUPD3);
918 if (error) {
919 Log("1 Volser: can't attach clone %d\n", cloneId);
920 goto fail;
921 }
922
923 newType = V_type(clonevp)((clonevp)->header->diskstuff.type); /* type of the new volume */
924
925 if (originalvp->device != clonevp->device) {
926 Log("1 Volser: Clone: Volumes %u and %u are on different devices\n",
927 tt->volid, cloneId);
928 error = EXDEV18;
929 goto fail;
930 }
931 if (V_type(clonevp)((clonevp)->header->diskstuff.type) != readonlyVolume1 && V_type(clonevp)((clonevp)->header->diskstuff.type) != backupVolume2) {
932 Log("1 Volser: Clone: The \"recloned\" volume must be a read only volume; aborted\n");
933 error = EINVAL22;
934 goto fail;
935 }
936 if (V_type(originalvp)((originalvp)->header->diskstuff.type) == readonlyVolume1
937 && V_parentId(originalvp)((originalvp)->header->diskstuff.parentId) != V_parentId(clonevp)((clonevp)->header->diskstuff.parentId)) {
938 Log("1 Volser: Clone: Volume %u and volume %u were not cloned from the same parent volume; aborted\n", tt->volid, cloneId);
939 error = EXDEV18;
940 goto fail;
941 }
942 if (V_type(originalvp)((originalvp)->header->diskstuff.type) == readwriteVolume0
943 && tt->volid != V_parentId(clonevp)((clonevp)->header->diskstuff.parentId)) {
944 Log("1 Volser: Clone: Volume %u was not originally cloned from volume %u; aborted\n", cloneId, tt->volid);
945 error = EXDEV18;
946 goto fail;
947 }
948
949 error = 0;
950 Log("1 Volser: Clone: Recloning volume %u to volume %u\n", tt->volid,
951 cloneId);
952 CloneVolume(&error, originalvp, clonevp, clonevp);
953 if (error) {
954 Log("1 Volser: Clone: reclone operation failed with code %d\n",
955 error);
956 LogError(error);
957 goto fail;
958 }
959
960 /* fix up volume name and type, CloneVolume just propagated RW's */
961 if (newType == readonlyVolume1) {
962 AssignVolumeName(&V_disk(clonevp)((clonevp)->header->diskstuff), V_name(originalvp)((originalvp)->header->diskstuff.name), ".readonly");
963 V_type(clonevp)((clonevp)->header->diskstuff.type) = readonlyVolume1;
964 } else if (newType == backupVolume2) {
965 AssignVolumeName(&V_disk(clonevp)((clonevp)->header->diskstuff), V_name(originalvp)((originalvp)->header->diskstuff.name), ".backup");
966 V_type(clonevp)((clonevp)->header->diskstuff.type) = backupVolume2;
967 V_backupId(originalvp)((originalvp)->header->diskstuff.backupId) = cloneId;
968 }
969 /* don't do strcpy onto diskstuff.name, it's still OK from 1st clone */
970
971 /* pretend recloned volume is a totally new instance */
972 V_copyDate(clonevp)((clonevp)->header->diskstuff.copyDate) = time(0);
973 V_creationDate(clonevp)((clonevp)->header->diskstuff.creationDate) = V_copyDate(clonevp)((clonevp)->header->diskstuff.copyDate);
974 ClearVolumeStats(&V_disk(clonevp)((clonevp)->header->diskstuff));
975 V_destroyMe(clonevp)((clonevp)->header->diskstuff.destroyMe) = 0;
976 V_inService(clonevp)((clonevp)->header->diskstuff.inService) = 0;
977 if (newType == backupVolume2) {
978 V_backupDate(originalvp)((originalvp)->header->diskstuff.backupDate) = V_copyDate(clonevp)((clonevp)->header->diskstuff.copyDate);
979 V_backupDate(clonevp)((clonevp)->header->diskstuff.backupDate) = V_copyDate(clonevp)((clonevp)->header->diskstuff.copyDate);
980 }
981 V_inUse(clonevp)((clonevp)->header->diskstuff.inUse) = 0;
982 VUpdateVolume(&error, clonevp);
983 if (error) {
984 Log("1 Volser: Clone: VUpdate failed code %u\n", error);
985 LogError(error);
986 goto fail;
987 }
988 /* VUpdateVolume succeeded. Mark it in service so there's no window
989 * between FSYNC_VOL_ON and VolSetFlags where it's offline with no
990 * specialStatus; this is a reclone and this volume started online
991 */
992 V_inService(clonevp)((clonevp)->header->diskstuff.inService) = 1;
993 VDetachVolume(&error, clonevp); /* allow file server to get it's hands on it */
994 clonevp = NULL((void *)0);
995 VUpdateVolume(&error, originalvp);
996 if (error) {
997 Log("1 Volser: Clone: original update %u\n", error);
998 LogError(error);
999 goto fail;
1000 }
1001 TClearRxCall(tt);
1002 if (TRELE(tt)) {
1003 tt = (struct volser_trans *)0;
1004 error = VOLSERTRELE_ERROR(1492325120L);
1005 goto fail;
1006 }
1007
1008 DeleteTrans(ttc, 1);
1009
1010 {
1011 struct DiskPartition64 *tpartp = originalvp->partition;
1012 FSYNC_VolOp(cloneId, tpartp->name, FSYNC_VOL_BREAKCBKS, 0, NULL((void *)0));
1013 }
1014 return 0;
1015
1016 fail:
1017 if (clonevp)
1018 VDetachVolume(&code, clonevp);
1019 if (tt) {
1020 TClearRxCall(tt);
1021 TRELE(tt);
1022 }
1023 if (ttc)
1024 DeleteTrans(ttc, 1);
1025 return error;
1026}
1027
1028/* create a new transaction, associated with volume and partition. Type of
1029 * volume transaction is spec'd by iflags. New trans id is returned in ttid.
1030 * See volser.h for definition of iflags (the constants are named IT*).
1031 */
1032afs_int32
1033SAFSVolTransCreate(struct rx_call *acid, afs_uint32 volume, afs_int32 partition,
1034 afs_int32 iflags, afs_int32 *ttid)
1035{
1036 afs_int32 code;
1037
1038 code = VolTransCreate(acid, volume, partition, iflags, ttid);
1039 osi_auditU(acid, VS_TransCrEvent"AFS_VS_TransCr", code, AUD_LONG5, *ttid, AUD_LONG5, volume,
1040 AUD_END0);
1041 return code;
1042}
1043
1044static afs_int32
1045VolTransCreate(struct rx_call *acid, afs_uint32 volume, afs_int32 partition,
1046 afs_int32 iflags, afs_int32 *ttid)
1047{
1048 struct volser_trans *tt;
1049 Volume *tv;
1050 afs_int32 error;
1051 Errorbit32 code;
1052 afs_int32 mode;
1053 char caller[MAXKTCNAMELEN64];
1054
1055 if (!afsconf_SuperUser(tdir, acid, caller))
1056 return VOLSERBAD_ACCESS(1492325127L); /*not a super user */
1057 if (iflags & ITCreate0x10)
1058 mode = V_SECRETLY5;
1059 else if (iflags & ITBusy2)
1060 mode = V_CLONE2;
1061 else if (iflags & ITReadOnly8)
1062 mode = V_READONLY1;
1063 else if (iflags & ITOffline1)
1064 mode = V_VOLUPD3;
1065 else {
1066 Log("1 Volser: TransCreate: Could not create trans, error %u\n",
1067 EINVAL22);
1068 LogError(EINVAL22);
1069 return EINVAL22;
1070 }
1071 tt = NewTrans(volume, partition);
1072 if (!tt) {
1073 /* can't create a transaction? put the volume back */
1074 Log("1 transcreate: can't create transaction\n");
1075 return VOLSERVOLBUSY(1492325133L);
1076 }
1077 tv = XAttachVolume(&error, volume, partition, mode);
1078 if (error) {
1079 /* give up */
1080 if (tv)
1081 VDetachVolume(&code, tv);
1082 DeleteTrans(tt, 1);
1083 return error;
1084 }
1085 VTRANS_OBJ_LOCK(tt);
1086 tt->volume = tv;
1087 *ttid = tt->tid;
1088 tt->iflags = iflags;
1089 tt->vflags = 0;
1090 TSetRxCall_r(tt, NULL((void *)0), "TransCreate");
1091 VTRANS_OBJ_UNLOCK(tt);
1092 if (TRELE(tt))
1093 return VOLSERTRELE_ERROR(1492325120L);
1094
1095 return 0;
1096}
1097
1098/* using aindex as a 0-based index, return the aindex'th volume on this server
1099 * Both the volume number and partition number (one-based) are returned.
1100 */
1101afs_int32
1102SAFSVolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_uint32 *avolume,
1103 afs_int32 *apart)
1104{
1105 afs_int32 code;
1106
1107 code = VolGetNthVolume(acid, aindex, avolume, apart);
1108 osi_auditU(acid, VS_GetNVolEvent"AFS_VS_GetNVol", code, AUD_LONG5, *avolume, AUD_END0);
1109 return code;
1110}
1111
1112static afs_int32
1113VolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_uint32 *avolume,
1114 afs_int32 *apart)
1115{
1116 Log("1 Volser: GetNthVolume: Not yet implemented\n");
1117 return VOLSERNO_OP(1492325121L);
1118}
1119
1120/* return the volume flags (VT* constants in volser.h) associated with this
1121 * transaction.
1122 */
1123afs_int32
1124SAFSVolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
1125{
1126 afs_int32 code;
1127
1128 code = VolGetFlags(acid, atid, aflags);
1129 osi_auditU(acid, VS_GetFlgsEvent"AFS_VS_GetFlgs", code, AUD_LONG5, atid, AUD_END0);
1130 return code;
1131}
1132
1133static afs_int32
1134VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
1135{
1136 struct volser_trans *tt;
1137
1138 tt = FindTrans(atid);
1139 if (!tt)
1140 return ENOENT2;
1141 if (tt->vflags & VTDeleted4) {
1142 Log("1 Volser: VolGetFlags: volume %u has been deleted \n",
1143 tt->volid);
1144 TRELE(tt);
1145 return ENOENT2;
1146 }
1147 TSetRxCall(tt, acid, "GetFlags");
1148 *aflags = tt->vflags;
1149 TClearRxCall(tt);
1150 if (TRELE(tt))
1151 return VOLSERTRELE_ERROR(1492325120L);
1152
1153 return 0;
1154}
1155
1156/* Change the volume flags (VT* constants in volser.h) associated with this
1157 * transaction. Effects take place immediately on volume, although volume
1158 * remains attached as usual by the transaction.
1159 */
1160afs_int32
1161SAFSVolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
1162{
1163 afs_int32 code;
1164
1165 code = VolSetFlags(acid, atid, aflags);
1166 osi_auditU(acid, VS_SetFlgsEvent"AFS_VS_SetFlgs", code, AUD_LONG5, atid, AUD_LONG5, aflags,
1167 AUD_END0);
1168 return code;
1169}
1170
1171static afs_int32
1172VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
1173{
1174 struct volser_trans *tt;
1175 struct Volume *vp;
1176 Errorbit32 error;
1177 char caller[MAXKTCNAMELEN64];
1178
1179 if (!afsconf_SuperUser(tdir, acid, caller))
1180 return VOLSERBAD_ACCESS(1492325127L); /*not a super user */
1181 /* find the trans */
1182 tt = FindTrans(atid);
1183 if (!tt)
1184 return ENOENT2;
1185 if (tt->vflags & VTDeleted4) {
1186 Log("1 Volser: VolSetFlags: volume %u has been deleted \n",
1187 tt->volid);
1188 TRELE(tt);
1189 return ENOENT2;
1190 }
1191 TSetRxCall(tt, acid, "SetFlags");
1192 vp = tt->volume; /* pull volume out of transaction */
1193
1194 /* check if we're allowed to make any updates */
1195 if (tt->iflags & ITReadOnly8) {
1196 TRELE(tt);
1197 return EROFS30;
1198 }
1199
1200 /* handle delete-on-salvage flag */
1201 if (aflags & VTDeleteOnSalvage1) {
1202 V_destroyMe(tt->volume)((tt->volume)->header->diskstuff.destroyMe) = DESTROY_ME0xD3;
1203 } else {
1204 V_destroyMe(tt->volume)((tt->volume)->header->diskstuff.destroyMe) = 0;
1205 }
1206
1207 if (aflags & VTOutOfService2) {
1208 V_inService(vp)((vp)->header->diskstuff.inService) = 0;
1209 } else {
1210 V_inService(vp)((vp)->header->diskstuff.inService) = 1;
1211 }
1212 VUpdateVolume(&error, vp);
1213 VTRANS_OBJ_LOCK(tt);
1214 tt->vflags = aflags;
1215 TClearRxCall_r(tt);
1216 VTRANS_OBJ_UNLOCK(tt);
1217 if (TRELE(tt) && !error)
1218 return VOLSERTRELE_ERROR(1492325120L);
1219
1220 return error;
1221}
1222
1223/* dumpS the volume associated with a particular transaction from a particular
1224 * date. Send the dump to a different transaction (destTrans) on the server
1225 * specified by the destServer structure.
1226 */
1227afs_int32
1228SAFSVolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1229 struct destServer *destination, afs_int32 destTrans,
1230 struct restoreCookie *cookie)
1231{
1232 afs_int32 code;
1233
1234 code =
1235 VolForward(acid, fromTrans, fromDate, destination, destTrans, cookie);
1236 osi_auditU(acid, VS_ForwardEvent"AFS_VS_Forward", code, AUD_LONG5, fromTrans, AUD_HOST4,
1237 htonl(destination->destHost)(__builtin_constant_p(destination->destHost) ? ((((__uint32_t
)(destination->destHost)) >> 24) | ((((__uint32_t)(destination
->destHost)) & (0xff << 16)) >> 8) | ((((__uint32_t
)(destination->destHost)) & (0xff << 8)) <<
8) | (((__uint32_t)(destination->destHost)) << 24))
: __bswap32_var(destination->destHost))
, AUD_LONG5, destTrans, AUD_END0);
1238 return code;
1239}
1240
1241static afs_int32
1242VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1243 struct destServer *destination, afs_int32 destTrans,
1244 struct restoreCookie *cookie)
1245{
1246 struct volser_trans *tt;
1247 afs_int32 code;
1248 struct rx_connection *tcon;
1249 struct rx_call *tcall;
1250 struct Volume *vp;
1251 struct rx_securityClass *securityObject;
1252 afs_int32 securityIndex;
1253 char caller[MAXKTCNAMELEN64];
1254
1255 if (!afsconf_SuperUser(tdir, acid, caller))
1256 return VOLSERBAD_ACCESS(1492325127L); /*not a super user */
1257 /* initialize things */
1258 tcon = (struct rx_connection *)0;
1259 tt = (struct volser_trans *)0;
1260
1261 /* find the local transaction */
1262 tt = FindTrans(fromTrans);
1263 if (!tt)
1264 return ENOENT2;
1265 if (tt->vflags & VTDeleted4) {
1266 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1267 TRELE(tt);
1268 return ENOENT2;
1269 }
1270 vp = tt->volume;
1271 TSetRxCall(tt, NULL((void *)0), "Forward");
1272
1273 /* get auth info for the this connection (uses afs from ticket file) */
1274 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1275 if (code) {
1276 TRELE(tt);
1277 return code;
1278 }
1279
1280 /* make an rpc connection to the other server */
1281 tcon =
1282 rx_NewConnection(htonl(destination->destHost)(__builtin_constant_p(destination->destHost) ? ((((__uint32_t
)(destination->destHost)) >> 24) | ((((__uint32_t)(destination
->destHost)) & (0xff << 16)) >> 8) | ((((__uint32_t
)(destination->destHost)) & (0xff << 8)) <<
8) | (((__uint32_t)(destination->destHost)) << 24))
: __bswap32_var(destination->destHost))
,
1283 htons(destination->destPort)(__builtin_constant_p(destination->destPort) ? (__uint16_t
)(((__uint16_t)(destination->destPort)) << 8 | ((__uint16_t
)(destination->destPort)) >> 8) : __bswap16_var(destination
->destPort))
, VOLSERVICE_ID4,
1284 securityObject, securityIndex);
1285 if (!tcon) {
1286 TClearRxCall(tt);
1287 TRELE(tt);
1288 return ENOTCONN57;
1289 }
1290 tcall = rx_NewCall(tcon);
1291 TSetRxCall(tt, tcall, "Forward");
1292 /* start restore going. fromdate == 0 --> doing an incremental dump/restore */
1293 code = StartAFSVolRestore(tcall, destTrans, (fromDate ? 1 : 0), cookie);
1294 if (code) {
1295 goto fail;
1296 }
1297
1298 /* these next calls implictly call rx_Write when writing out data */
1299 code = DumpVolume(tcall, vp, fromDate, 0); /* last field = don't dump all dirs */
1300 if (code)
1301 goto fail;
1302 EndAFSVolRestore(tcall); /* probably doesn't do much */
1303 TClearRxCall(tt);
1304 code = rx_EndCall(tcall, 0);
1305 rx_DestroyConnection(tcon); /* done with the connection */
1306 tcon = NULL((void *)0);
1307 if (code)
1308 goto fail;
1309 if (TRELE(tt))
1310 return VOLSERTRELE_ERROR(1492325120L);
1311
1312 return 0;
1313
1314 fail:
1315 if (tcon) {
1316 (void)rx_EndCall(tcall, 0);
1317 rx_DestroyConnection(tcon);
1318 }
1319 if (tt) {
1320 TClearRxCall(tt);
1321 TRELE(tt);
1322 }
1323 return code;
1324}
1325
1326/* Start a dump and send it to multiple places simultaneously.
1327 * If this returns an error (eg, return ENOENT), it means that
1328 * none of the releases worked. If this returns 0, that means
1329 * that one or more of the releases worked, and the caller has
1330 * to examine the results array to see which one(s).
1331 * This will only do EITHER incremental or full, not both, so it's
1332 * the caller's responsibility to be sure that all the destinations
1333 * need just an incremental (and from the same time), if that's
1334 * what we're doing.
1335 */
1336afs_int32
1337SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
1338 fromDate, manyDests *destinations, afs_int32 spare,
1339 struct restoreCookie *cookie, manyResults *results)
1340{
1341 afs_int32 securityIndex;
1342 struct rx_securityClass *securityObject;
1343 char caller[MAXKTCNAMELEN64];
1344 struct volser_trans *tt;
1345 afs_int32 ec, code, *codes;
1346 struct rx_connection **tcons;
1347 struct rx_call **tcalls;
1348 struct Volume *vp;
1349 int i, is_incremental;
1350
1351 if (results) {
1352 memset(results, 0, sizeof(manyResults));
1353 i = results->manyResults_len = destinations->manyDests_len;
1354 results->manyResults_val = codes =
1355 (afs_int32 *) malloc(i * sizeof(afs_int32));
1356 }
1357 if (!results || !results->manyResults_val)
1358 return ENOMEM12;
1359
1360 if (!afsconf_SuperUser(tdir, acid, caller))
1361 return VOLSERBAD_ACCESS(1492325127L); /*not a super user */
1362 tt = FindTrans(fromTrans);
1363 if (!tt)
1364 return ENOENT2;
1365 if (tt->vflags & VTDeleted4) {
1366 Log("1 Volser: VolForward: volume %u has been deleted \n", tt->volid);
1367 TRELE(tt);
1368 return ENOENT2;
1369 }
1370 vp = tt->volume;
1371 TSetRxCall(tt, NULL((void *)0), "ForwardMulti");
1372
1373 /* (fromDate == 0) ==> full dump */
1374 is_incremental = (fromDate ? 1 : 0);
1375
1376 tcons =
1377 (struct rx_connection **)malloc(i * sizeof(struct rx_connection *));
1378 if (!tcons) {
1379 return ENOMEM12;
1380 }
1381 tcalls = (struct rx_call **)malloc(i * sizeof(struct rx_call *));
1382 if (!tcalls) {
1383 free(tcons);
1384 return ENOMEM12;
1385 }
1386
1387 /* get auth info for this connection (uses afs from ticket file) */
1388 code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
1389 if (code) {
1390 goto fail; /* in order to audit each failure */
1391 }
1392
1393 /* make connections to all the other servers */
1394 for (i = 0; i < destinations->manyDests_len; i++) {
1395 struct replica *dest = &(destinations->manyDests_val[i]);
1396 tcons[i] =
1397 rx_NewConnection(htonl(dest->server.destHost)(__builtin_constant_p(dest->server.destHost) ? ((((__uint32_t
)(dest->server.destHost)) >> 24) | ((((__uint32_t)(dest
->server.destHost)) & (0xff << 16)) >> 8) |
((((__uint32_t)(dest->server.destHost)) & (0xff <<
8)) << 8) | (((__uint32_t)(dest->server.destHost)) <<
24)) : __bswap32_var(dest->server.destHost))
,
1398 htons(dest->server.destPort)(__builtin_constant_p(dest->server.destPort) ? (__uint16_t
)(((__uint16_t)(dest->server.destPort)) << 8 | ((__uint16_t
)(dest->server.destPort)) >> 8) : __bswap16_var(dest
->server.destPort))
, VOLSERVICE_ID4,
1399 securityObject, securityIndex);
1400 if (!tcons[i]) {
1401 codes[i] = ENOTCONN57;
1402 } else {
1403 if (!(tcalls[i] = rx_NewCall(tcons[i])))
1404 codes[i] = ENOTCONN57;
1405 else {
1406 codes[i] =
1407 StartAFSVolRestore(tcalls[i], dest->trans, is_incremental,
1408 cookie);
1409 if (codes[i]) {
1410 (void)rx_EndCall(tcalls[i], 0);
1411 tcalls[i] = 0;
1412 rx_DestroyConnection(tcons[i]);
1413 tcons[i] = 0;
1414 }
1415 }
1416 }
1417 }
1418
1419 /* these next calls implictly call rx_Write when writing out data */
1420 code = DumpVolMulti(tcalls, i, vp, fromDate, 0, codes);
1421
1422
1423 fail:
1424 for (i--; i >= 0; i--) {
1425 struct replica *dest = &(destinations->manyDests_val[i]);
1426
1427 if (!code && tcalls[i] && !codes[i]) {
1428 EndAFSVolRestore(tcalls[i]);
1429 }
1430 if (tcalls[i]) {
1431 ec = rx_EndCall(tcalls[i], 0);
1432 if (!codes[i])
1433 codes[i] = ec;
1434 }
1435 if (tcons[i]) {
1436 rx_DestroyConnection(tcons[i]); /* done with the connection */
1437 }
1438
1439 osi_auditU(acid, VS_ForwardEvent"AFS_VS_Forward", (code ? code : codes[i]), AUD_LONG5,
1440 fromTrans, AUD_HOST4, htonl(dest->server.destHost)(__builtin_constant_p(dest->server.destHost) ? ((((__uint32_t
)(dest->server.destHost)) >> 24) | ((((__uint32_t)(dest
->server.destHost)) & (0xff << 16)) >> 8) |
((((__uint32_t)(dest->server.destHost)) & (0xff <<
8)) << 8) | (((__uint32_t)(dest->server.destHost)) <<
24)) : __bswap32_var(dest->server.destHost))
, AUD_LONG5,
1441 dest->trans, AUD_END0);
1442 }
1443 free(tcons);
1444 free(tcalls);
1445
1446 if (tt) {
1447 TClearRxCall(tt);
1448 if (TRELE(tt) && !code) /* return the first code if it's set */
1449 return VOLSERTRELE_ERROR(1492325120L);
1450 }
1451
1452 return code;
1453}
1454
1455afs_int32
1456SAFSVolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate)
1457{
1458 afs_int32 code;
1459
1460 code = VolDump(acid, fromTrans, fromDate, 0);
1461 osi_auditU(acid, VS_DumpEvent"AFS_VS_Dump", code, AUD_LONG5, fromTrans, AUD_END0);
1462 return code;
1463}
1464
1465afs_int32
1466SAFSVolDumpV2(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1467 afs_int32 flags)
1468{
1469 afs_int32 code;
1470
1471 code = VolDump(acid, fromTrans, fromDate, flags);
1472 osi_auditU(acid, VS_DumpEvent"AFS_VS_Dump", code, AUD_LONG5, fromTrans, AUD_END0);
1473 return code;
1474}
1475
1476static afs_int32
1477VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
1478 afs_int32 flags)
1479{
1480 int code = 0;
1481 struct volser_trans *tt;
1482 char caller[MAXKTCNAMELEN64];
1483
1484 if (!afsconf_SuperUser(tdir, acid, caller))
1485 return VOLSERBAD_ACCESS(1492325127L); /*not a super user */
1486 tt = FindTrans(fromTrans);
1487 if (!tt)
1488 return ENOENT2;
1489 if (tt->vflags & VTDeleted4) {
1490 Log("1 Volser: VolDump: volume %u has been deleted \n", tt->volid);
1491 TRELE(tt);
1492 return ENOENT2;
1493 }
1494 TSetRxCall(tt, acid, "Dump");
1495 code = DumpVolume(acid, tt->volume, fromDate, (flags & VOLDUMPV2_OMITDIRS1)
1496 ? 0 : 1); /* squirt out the volume's data, too */
1497 if (code) {
1498 TClearRxCall(tt);
1499 TRELE(tt);
1500 return code;
1501 }
1502 TClearRxCall(tt);
1503
1504 if (TRELE(tt))
1505 return VOLSERTRELE_ERROR(1492325120L);
1506
1507 return 0;
1508}
1509
1510/*
1511 * Ha! No more helper process!
1512 */
1513afs_int32
1514SAFSVolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1515 struct restoreCookie *cookie)
1516{
1517 afs_int32 code;
1518
1519 code = VolRestore(acid, atrans, aflags, cookie);
1520 osi_auditU(acid, VS_RestoreEvent"AFS_VS_Restore", code, AUD_LONG5, atrans, AUD_END0);
1521 return code;
1522}
1523
1524static afs_int32
1525VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
1526 struct restoreCookie *cookie)
1527{
1528 struct volser_trans *tt;
1529 afs_int32 code, tcode;
1530 char caller[MAXKTCNAMELEN64];
1531
1532 if (!afsconf_SuperUser(tdir, acid, caller))
1533 return VOLSERBAD_ACCESS(1492325127L); /*not a super user */
1534 tt = FindTrans(atrans);
1535 if (!tt)
1536 return ENOENT2;
1537 if (tt->vflags & VTDeleted4) {
1538 Log("1 Volser: VolRestore: volume %u has been deleted \n", tt->volid);
1539 TRELE(tt);
1540 return ENOENT2;
1541 }
1542 TSetRxCall(tt, acid, "Restore");
1543
1544 DFlushVolume(V_parentId(tt->volume)((tt->volume)->header->diskstuff.parentId)); /* Ensure dir buffers get dropped */
1545
1546 code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie); /* last is incrementalp */
1547 FSYNC_VolOp(tt->volid, NULL((void *)0), FSYNC_VOL_BREAKCBKS, 0l, NULL((void *)0));
1548 TClearRxCall(tt);
1549 tcode = TRELE(tt);
1550
1551 return (code ? code : tcode);
1552}
1553
1554/* end a transaction, returning the transaction's final error code in rcode */
1555afs_int32
1556SAFSVolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1557{
1558 afs_int32 code;
1559
1560 code = VolEndTrans(acid, destTrans, rcode);
1561 osi_auditU(acid, VS_EndTrnEvent"AFS_VS_EndTrn", code, AUD_LONG5, destTrans, AUD_END0);
1562 return code;
1563}
1564
1565static afs_int32
1566VolEndTrans(struct rx_call *acid, afs_int32 destTrans, afs_int32 *rcode)
1567{
1568 struct volser_trans *tt;
1569 char caller[MAXKTCNAMELEN64];
1570
1571 if (!afsconf_SuperUser(tdir, acid, caller))
1572 return VOLSERBAD_ACCESS(1492325127L); /*not a super user */
1573 tt = FindTrans(destTrans);
1574 if (!tt) {
1575 return ENOENT2;
1576 }
1577 *rcode = tt->returnCode;
1578 DeleteTrans(tt, 1); /* this does an implicit TRELE */
1579
1580 return 0;
1581}
1582
1583afs_int32
1584SAFSVolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1585{
1586 afs_int32 code;
1587
1588 code = VolSetForwarding(acid, atid, anewsite);
1589 osi_auditU(acid, VS_SetForwEvent"AFS_VS_SetForw", code, AUD_LONG5, atid, AUD_HOST4,
1590 htonl(anewsite)(__builtin_constant_p(anewsite) ? ((((__uint32_t)(anewsite)) >>
24) | ((((__uint32_t)(anewsite)) & (0xff << 16)) >>
8) | ((((__uint32_t)(anewsite)) & (0xff << 8)) <<
8) | (((__uint32_t)(anewsite)) << 24)) : __bswap32_var
(anewsite))
, AUD_END0);
1591 return code;
1592}
1593
1594static afs_int32
1595VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
1596{
1597 struct volser_trans *tt;
1598 char caller[MAXKTCNAMELEN64];
1599 char partName[16];
1600
1601 if (!afsconf_SuperUser(tdir, acid, caller))
1602 return VOLSERBAD_ACCESS(1492325127L); /*not a super user */
1603 tt = FindTrans(atid);
1604 if (!tt)
1605 return ENOENT2;
1606 if (tt->vflags & VTDeleted4) {
1607 Log("1 Volser: VolSetForwarding: volume %u has been deleted \n",
1608 tt->volid);
1609 TRELE(tt);
1610 return ENOENT2;
1611 }
1612 TSetRxCall(tt, acid, "SetForwarding");
1613 if (volutil_PartitionName2_r(tt->partition, partName, sizeof(partName)) != 0) {
1614 partName[0] = '\0';
1615 }
1616 FSYNC_VolOp(tt->volid, partName, FSYNC_VOL_MOVE, anewsite, NULL((void *)0));
1617 TClearRxCall(tt);
1618 if (TRELE(tt))
1619 return VOLSERTRELE_ERROR(1492325120L);
1620
1621 return 0;
1622}
1623
1624afs_int32
1625SAFSVolGetStatus(struct rx_call *acid, afs_int32 atrans,
1626 struct volser_status *astatus)
1627{
1628 afs_int32 code;
1629
1630 code = VolGetStatus(acid, atrans, astatus);
1631 osi_auditU(acid, VS_GetStatEvent"AFS_VS_GetStat", code, AUD_LONG5, atrans, AUD_END0);
1632 return code;
1633}
1634
1635static afs_int32
1636VolGetStatus(struct rx_call *acid, afs_int32 atrans,
1637 struct volser_status *astatus)
1638{
1639 struct Volume *tv;
1640 struct VolumeDiskData *td;
1641 struct volser_trans *tt;
1642
1643
1644 tt = FindTrans(atrans);
1645 if (!tt)
1646 return ENOENT2;
1647 if (tt->vflags & VTDeleted4) {
1648 Log("1 Volser: VolGetStatus: volume %u has been deleted \n",
1649 tt->volid);
1650 TRELE(tt);
1651 return ENOENT2;
1652 }
1653 TSetRxCall(tt, acid, "GetStatus");
1654 tv = tt->volume;
1655 if (!tv) {
1656 TClearRxCall(tt);
1657 TRELE(tt);
1658 return ENOENT2;
1659 }
1660
1661 td = &tv->header->diskstuff;
1662 astatus->volID = td->id;
1663 astatus->nextUnique = td->uniquifier;
1664 astatus->type = td->type;
1665 astatus->parentID = td->parentId;
1666 astatus->cloneID = td->cloneId;
1667 astatus->backupID = td->backupId;
1668 astatus->restoredFromID = td->restoredFromId;
1669 astatus->maxQuota = td->maxquota;
1670 astatus->minQuota = td->minquota;
1671 astatus->owner = td->owner;
1672 astatus->creationDate = td->creationDate;
1673 astatus->accessDate = td->accessDate;
1674 astatus->updateDate = td->updateDate;
1675 astatus->expirationDate = td->expirationDate;
1676 astatus->backupDate = td->backupDate;
1677 astatus->copyDate = td->copyDate;
1678 TClearRxCall(tt);
1679 if (TRELE(tt))
1680 return VOLSERTRELE_ERROR(1492325120L);
1681
1682 return 0;
1683}
1684
1685afs_int32
1686SAFSVolSetInfo(struct rx_call *acid, afs_int32 atrans,
1687 struct volintInfo *astatus)
1688{
1689 afs_int32 code;
1690
1691 code = VolSetInfo(acid, atrans, astatus);
1692 osi_auditU(acid, VS_SetInfoEvent"AFS_VS_SetInfo", code, AUD_LONG5, atrans, AUD_END0);
1693 return code;
1694}
1695
1696static afs_int32
1697VolSetInfo(struct rx_call *acid, afs_int32 atrans,
1698 struct volintInfo *astatus)
1699{
1700 struct Volume *tv;
1701 struct VolumeDiskData *td;
1702 struct volser_trans *tt;
1703 char caller[MAXKTCNAMELEN64];
1704 Errorbit32 error;
1705
1706 if (!afsconf_SuperUser(tdir, acid, caller))
1707 return VOLSERBAD_ACCESS(1492325127L); /*not a super user */
1708 tt = FindTrans(atrans);
1709 if (!tt)
1710 return ENOENT2;
1711 if (tt->vflags & VTDeleted4) {
1712 Log("1 Volser: VolSetInfo: volume %u has been deleted \n", tt->volid);
1713 TRELE(tt);
1714 return ENOENT2;
1715 }
1716 TSetRxCall(tt, acid, "SetStatus");
1717 tv = tt->volume;
1718 if (!tv) {
1719 TClearRxCall(tt);
1720 TRELE(tt);
1721 return ENOENT2;
1722 }
1723
1724 td = &tv->header->diskstuff;
1725 /*
1726 * Add more fields as necessary
1727 */
1728 if (astatus->maxquota != -1)
1729 td->maxquota = astatus->maxquota;
1730 if (astatus->dayUse != -1)
1731 td->dayUse = astatus->dayUse;
1732 if (astatus->creationDate != -1)
1733 td->creationDate = astatus->creationDate;
1734 if (astatus->updateDate != -1)
1735 td->updateDate = astatus->updateDate;
1736 if (astatus->spare2 != -1)
1737 td->volUpdateCounter = (unsigned int)astatus->spare2;
1738 VUpdateVolume(&error, tv);
1739 TClearRxCall(tt);
1740 if (TRELE(tt))
1741 return VOLSERTRELE_ERROR(1492325120L);
1742 return 0;
1743}
1744
1745
1746afs_int32
1747SAFSVolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1748{
1749 afs_int32 code;
1750
1751 code = VolGetName(acid, atrans, aname);
1752 osi_auditU(acid, VS_GetNameEvent"AFS_VS_GetName", code, AUD_LONG5, atrans, AUD_END0);
1753 return code;
1754}
1755
1756static afs_int32
1757VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
1758{
1759 struct Volume *tv;
1760 struct VolumeDiskData *td;
1761 struct volser_trans *tt;
1762 int len;
1763
1764 /* We need to at least fill it in */
1765 *aname = (char *)malloc(1);
1766 if (!*aname)
1767 return ENOMEM12;
1768 tt = FindTrans(atrans);
1769 if (!tt)
1770 return ENOENT2;
1771 if (tt->vflags & VTDeleted4) {
1772 Log("1 Volser: VolGetName: volume %u has been deleted \n", tt->volid);
1773 TRELE(tt);
1774 return ENOENT2;
1775 }
1776 TSetRxCall(tt, acid, "GetName");
1777 tv = tt->volume;
1778 if (!tv) {
1779 TClearRxCall(tt);
1780 TRELE(tt);
1781 return ENOENT2;
1782 }
1783
1784 td = &tv->header->diskstuff;
1785 len = strlen(td->name) + 1; /* don't forget the null */
1786 if (len >= SIZE1024) {
1787 TClearRxCall(tt);
1788 TRELE(tt);
1789 return E2BIG7;
1790 }
1791 *aname = (char *)realloc(*aname, len);
1792 strcpy(*aname, td->name);
1793 TClearRxCall(tt);
1794 if (TRELE(tt))
1795 return VOLSERTRELE_ERROR(1492325120L);
1796
1797 return 0;
1798}
1799
1800/*this is a handshake to indicate that the next call will be SAFSVolRestore
1801 * - a noop now !*/
1802afs_int32
1803SAFSVolSignalRestore(struct rx_call *acid, char volname[], int volType,
1804 afs_uint32 parentId, afs_uint32 cloneId)
1805{
1806 return 0;
1807}
1808
1809
1810/*return a list of all partitions on the server. The non mounted
1811 *partitions are returned as -1 in the corresponding slot in partIds*/
1812afs_int32
1813SAFSVolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1814{
1815 afs_int32 code;
1816
1817 code = VolListPartitions(acid, partIds);
1818 osi_auditU(acid, VS_ListParEvent"AFS_VS_ListPar", code, AUD_END0);
1819 return code;
1820}
1821
1822static afs_int32
1823VolListPartitions(struct rx_call *acid, struct pIDs *partIds)
1824{
1825 char namehead[9];
1826 int i;
1827
1828 strcpy(namehead, "/vicep"); /*7 including null terminator */
1829
1830 /* Just return attached partitions. */
1831 namehead[7] = '\0';
1832 for (i = 0; i < 26; i++) {
1833 namehead[6] = i + 'a';
1834 partIds->partIds[i] = VGetPartition(namehead, 0) ? i : -1;
1835 }
1836
1837 return 0;
1838}
1839
1840/*return a list of all partitions on the server. The non mounted
1841 *partitions are returned as -1 in the corresponding slot in partIds*/
1842afs_int32
1843SAFSVolXListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1844{
1845 afs_int32 code;
1846
1847 code = XVolListPartitions(acid, pEntries);
1848 osi_auditU(acid, VS_ListParEvent"AFS_VS_ListPar", code, AUD_END0);
1849 return code;
1850}
1851
1852static afs_int32
1853XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
1854{
1855 char namehead[9];
1856 struct partList partList;
1857 struct DiskPartition64 *dp;
1858 int i, j = 0;
1859
1860 strcpy(namehead, "/vicep"); /*7 including null terminator */
1861
1862 /* Only report attached partitions */
1863 for (i = 0; i < VOLMAXPARTS255; i++) {
1864#ifdef AFS_DEMAND_ATTACH_FS
1865 dp = VGetPartitionById(i, 0);
1866#else
1867 if (i < 26) {
1868 namehead[6] = i + 'a';
1869 namehead[7] = '\0';
1870 } else {
1871 int k;
1872
1873 k = i - 26;
1874 namehead[6] = 'a' + (k / 26);
1875 namehead[7] = 'a' + (k % 26);
1876 namehead[8] = '\0';
1877 }
1878 dp = VGetPartition(namehead, 0);
1879#endif
1880 if (dp)
1881 partList.partId[j++] = i;
1882 }
1883 if (j > 0) {
1884 pEntries->partEntries_val = (afs_int32 *) malloc(j * sizeof(int));
1885 if (!pEntries->partEntries_val)
1886 return ENOMEM12;
1887 memcpy((char *)pEntries->partEntries_val, (char *)&partList,
1888 j * sizeof(int));
1889 pEntries->partEntries_len = j;
1890 } else {
1891 pEntries->partEntries_val = NULL((void *)0);
1892 pEntries->partEntries_len = 0;
1893 }
1894 return 0;
1895
1896}
1897
1898/*extract the volume id from string vname. Its of the form " V0*<id>.vol "*/
1899afs_int32
1900ExtractVolId(char vname[])
1901{
1902 int i;
1903 char name[VOLSER_MAXVOLNAME65 + 1];
1904
1905 strcpy(name, vname);
1906 i = 0;
1907 while (name[i] == 'V' || name[i] == '0')
1908 i++;
1909
1910 name[11] = '\0'; /* smash the "." */
1911 return (atol(&name[i]));
1912}
1913
1914/*return the name of the next volume header in the directory associated with dirp and dp.
1915*the volume id is returned in volid, and volume header name is returned in volname*/
1916int
1917GetNextVol(DIR * dirp, char *volname, afs_uint32 * volid)
1918{
1919 struct dirent *dp;
1920
1921 dp = readdir(dirp); /*read next entry in the directory */
1922 if (dp) {
1923 if ((dp->d_name[0] == 'V') && !strcmp(&(dp->d_name[11]), VHDREXT".vol")) {
1924 *volid = ExtractVolId(dp->d_name);
1925 strcpy(volname, dp->d_name);
1926 return 0; /*return the name of the file representing a volume */
1927 } else {
1928 strcpy(volname, "");
1929 return 0; /*volname doesnot represent a volume */
1930 }
1931 } else {
1932 strcpy(volname, "EOD");
1933 return 0; /*end of directory */
1934 }
1935
1936}
1937
1938/**
1939 * volint vol info structure type.
1940 */
1941typedef enum {
1942 VOLINT_INFO_TYPE_BASE, /**< volintInfo type */
1943 VOLINT_INFO_TYPE_EXT /**< volintXInfo type */
1944} volint_info_type_t;
1945
1946/**
1947 * handle to various on-wire vol info types.
1948 */
1949typedef struct {
1950 volint_info_type_t volinfo_type;
1951 union {
1952 void * opaque;
1953 volintInfo * base;
1954 volintXInfo * ext;
1955 } volinfo_ptr;
1956} volint_info_handle_t;
1957
1958/**
1959 * store value to a field at the appropriate location in on-wire structure.
1960 */
1961#define VOLINT_INFO_STORE(handle, name, val)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->name = (val); } else { (handle
)->volinfo_ptr.ext->name = (val); } } while(0)
\
1962 do { \
1963 if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) { \
1964 (handle)->volinfo_ptr.base->name = (val); \
1965 } else { \
1966 (handle)->volinfo_ptr.ext->name = (val); \
1967 } \
1968 } while(0)
1969
1970/**
1971 * get pointer to appropriate offset of field in on-wire structure.
1972 */
1973#define VOLINT_INFO_PTR(handle, name)(((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) ? &
((handle)->volinfo_ptr.base->name) : &((handle)->
volinfo_ptr.ext->name))
\
1974 (((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) ? \
1975 &((handle)->volinfo_ptr.base->name) : \
1976 &((handle)->volinfo_ptr.ext->name))
1977
1978/**
1979 * fill in appropriate type of on-wire volume metadata structure.
1980 *
1981 * @param vp pointer to volume object
1982 * @param handle pointer to wire format handle object
1983 *
1984 * @pre vp object must contain header & pending_vol_op structurs (populate if from RPC)
1985 * @pre handle object must have a valid pointer and enumeration value
1986 *
1987 * @note passing a NULL value for vp means that the fileserver doesn't
1988 * know about this particular volume, thus implying it is offline.
1989 *
1990 * @return operation status
1991 * @retval 0 success
1992 * @retval 1 failure
1993 */
1994static int
1995FillVolInfo(Volume * vp, volint_info_handle_t * handle)
1996{
1997 unsigned int numStatBytes, now;
1998 struct VolumeDiskData *hdr = &vp->header->diskstuff;
1999
2000 /*read in the relevant info */
2001 strcpy((char *)VOLINT_INFO_PTR(handle, name)(((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) ? &
((handle)->volinfo_ptr.base->name) : &((handle)->
volinfo_ptr.ext->name))
, hdr->name);
2002 VOLINT_INFO_STORE(handle, status, VOK)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->status = (0x02); } else { (
handle)->volinfo_ptr.ext->status = (0x02); } } while(0)
; /*its ok */
2003 VOLINT_INFO_STORE(handle, volid, hdr->id)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->volid = (hdr->id); } else
{ (handle)->volinfo_ptr.ext->volid = (hdr->id); } }
while(0)
;
2004 VOLINT_INFO_STORE(handle, type, hdr->type)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->type = (hdr->type); } else
{ (handle)->volinfo_ptr.ext->type = (hdr->type); } }
while(0)
; /*if ro volume */
2005 VOLINT_INFO_STORE(handle, cloneID, hdr->cloneId)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->cloneID = (hdr->cloneId
); } else { (handle)->volinfo_ptr.ext->cloneID = (hdr->
cloneId); } } while(0)
; /*if rw volume */
2006 VOLINT_INFO_STORE(handle, backupID, hdr->backupId)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->backupID = (hdr->backupId
); } else { (handle)->volinfo_ptr.ext->backupID = (hdr->
backupId); } } while(0)
;
2007 VOLINT_INFO_STORE(handle, parentID, hdr->parentId)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->parentID = (hdr->parentId
); } else { (handle)->volinfo_ptr.ext->parentID = (hdr->
parentId); } } while(0)
;
2008 VOLINT_INFO_STORE(handle, copyDate, hdr->copyDate)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->copyDate = (hdr->copyDate
); } else { (handle)->volinfo_ptr.ext->copyDate = (hdr->
copyDate); } } while(0)
;
2009 VOLINT_INFO_STORE(handle, size, hdr->diskused)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->size = (hdr->diskused);
} else { (handle)->volinfo_ptr.ext->size = (hdr->diskused
); } } while(0)
;
2010 VOLINT_INFO_STORE(handle, maxquota, hdr->maxquota)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->maxquota = (hdr->maxquota
); } else { (handle)->volinfo_ptr.ext->maxquota = (hdr->
maxquota); } } while(0)
;
2011 VOLINT_INFO_STORE(handle, filecount, hdr->filecount)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->filecount = (hdr->filecount
); } else { (handle)->volinfo_ptr.ext->filecount = (hdr
->filecount); } } while(0)
;
2012 now = FT_ApproxTime();
2013 if ((now - hdr->dayUseDate) > OneDay(24*60*60)) {
2014 VOLINT_INFO_STORE(handle, dayUse, 0)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->dayUse = (0); } else { (handle
)->volinfo_ptr.ext->dayUse = (0); } } while(0)
;
2015 } else {
2016 VOLINT_INFO_STORE(handle, dayUse, hdr->dayUse)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->dayUse = (hdr->dayUse);
} else { (handle)->volinfo_ptr.ext->dayUse = (hdr->
dayUse); } } while(0)
;
2017 }
2018 VOLINT_INFO_STORE(handle, creationDate, hdr->creationDate)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->creationDate = (hdr->creationDate
); } else { (handle)->volinfo_ptr.ext->creationDate = (
hdr->creationDate); } } while(0)
;
2019 VOLINT_INFO_STORE(handle, accessDate, hdr->accessDate)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->accessDate = (hdr->accessDate
); } else { (handle)->volinfo_ptr.ext->accessDate = (hdr
->accessDate); } } while(0)
;
2020 VOLINT_INFO_STORE(handle, updateDate, hdr->updateDate)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->updateDate = (hdr->updateDate
); } else { (handle)->volinfo_ptr.ext->updateDate = (hdr
->updateDate); } } while(0)
;
2021 VOLINT_INFO_STORE(handle, backupDate, hdr->backupDate)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->backupDate = (hdr->backupDate
); } else { (handle)->volinfo_ptr.ext->backupDate = (hdr
->backupDate); } } while(0)
;
2022
2023#ifdef AFS_DEMAND_ATTACH_FS
2024 /*
2025 * for DAFS, we "lie" about volume state --
2026 * instead of returning the raw state from the disk header,
2027 * we compute state based upon the fileserver's internal
2028 * in-core state enumeration value reported to us via fssync,
2029 * along with the blessed and inService flags from the header.
2030 * -- tkeiser 11/27/2007
2031 */
2032
2033 /* Conditions that offline status is based on:
2034 volume is unattached state
2035 volume state is in (one of several error states)
2036 volume not in service
2037 volume is not marked as blessed (not on hold)
2038 volume in salvage req. state
2039 volume needsSalvaged
2040 next op would set volume offline
2041 next op would not leave volume online (based on several conditions)
2042 */
2043 if (!vp ||
2044 (V_attachState(vp) == VOL_STATE_UNATTACHED) ||
2045 VIsErrorState(V_attachState(vp)) ||
2046 !hdr->inService ||
2047 !hdr->blessed ||
2048 (V_attachState(vp) == VOL_STATE_SALVSYNC_REQ) ||
2049 hdr->needsSalvaged ||
2050 (vp->pending_vol_op &&
2051 (vp->pending_vol_op->com.command == FSYNC_VOL_OFF ||
2052 !VVolOpLeaveOnline_r(vp, vp->pending_vol_op) )
2053 )
2054 ) {
2055 VOLINT_INFO_STORE(handle, inUse, 0)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->inUse = (0); } else { (handle
)->volinfo_ptr.ext->inUse = (0); } } while(0)
;
2056 } else {
2057 VOLINT_INFO_STORE(handle, inUse, 1)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->inUse = (1); } else { (handle
)->volinfo_ptr.ext->inUse = (1); } } while(0)
;
2058 }
2059#else
2060 /* offline status based on program type, where != fileServer enum (1) is offline */
2061 if (hdr->inUse == fileServer) {
2062 VOLINT_INFO_STORE(handle, inUse, 1)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->inUse = (1); } else { (handle
)->volinfo_ptr.ext->inUse = (1); } } while(0)
;
2063 } else {
2064 VOLINT_INFO_STORE(handle, inUse, 0)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->inUse = (0); } else { (handle
)->volinfo_ptr.ext->inUse = (0); } } while(0)
;
2065 }
2066#endif
2067
2068
2069 switch(handle->volinfo_type) {
2070 /* NOTE: VOLINT_INFO_STORE not used in this section because values are specific to one volinfo_type */
2071 case VOLINT_INFO_TYPE_BASE:
2072
2073#ifdef AFS_DEMAND_ATTACH_FS
2074 /* see comment above where we set inUse bit */
2075 if (hdr->needsSalvaged ||
2076 (vp && VIsErrorState(V_attachState(vp)))) {
2077 handle->volinfo_ptr.base->needsSalvaged = 1;
2078 } else {
2079 handle->volinfo_ptr.base->needsSalvaged = 0;
2080 }
2081#else
2082 handle->volinfo_ptr.base->needsSalvaged = hdr->needsSalvaged;
2083#endif
2084 handle->volinfo_ptr.base->destroyMe = hdr->destroyMe;
2085 handle->volinfo_ptr.base->spare0 = hdr->minquota;
2086 handle->volinfo_ptr.base->spare1 =
2087 (long)hdr->weekUse[0] +
2088 (long)hdr->weekUse[1] +
2089 (long)hdr->weekUse[2] +
2090 (long)hdr->weekUse[3] +
2091 (long)hdr->weekUse[4] +
2092 (long)hdr->weekUse[5] +
2093 (long)hdr->weekUse[6];
2094 handle->volinfo_ptr.base->flags = 0;
2095 handle->volinfo_ptr.base->spare2 = hdr->volUpdateCounter;
2096 handle->volinfo_ptr.base->spare3 = 0;
2097 break;
2098
2099
2100 case VOLINT_INFO_TYPE_EXT:
2101 numStatBytes =
2102 4 * ((2 * VOLINT_STATS_NUM_RWINFO_FIELDS4) +
2103 (4 * VOLINT_STATS_NUM_TIME_FIELDS6));
2104
2105 /*
2106 * Copy out the stat fields in a single operation.
2107 */
2108 if ((now - hdr->dayUseDate) > OneDay(24*60*60)) {
2109 memset(&(handle->volinfo_ptr.ext->stat_reads[0]),
2110 0, numStatBytes);
2111 } else {
2112 memcpy((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
2113 (char *)&(hdr->stat_reads[0]),
2114 numStatBytes);
2115 }
2116 break;
2117 }
2118
2119 return 0;
2120}
2121
2122#ifdef AFS_DEMAND_ATTACH_FS
2123
2124/**
2125 * get struct Volume out of the fileserver.
2126 *
2127 * @param[in] volumeId volumeId for which we want state information
2128 * @param[in] pname partition name string
2129 * @param[inout] vp pointer to pointer to Volume object which
2130 * will be populated (see note)
2131 *
2132 * @return operation status
2133 * @retval 0 success
2134 * @retval non-zero failure
2135 *
2136 * @note if FSYNC_VolOp fails in certain ways, *vp will be set to NULL
2137 *
2138 * @internal
2139 */
2140static int
2141GetVolObject(afs_uint32 volumeId, char * pname, Volume ** vp)
2142{
2143 int code;
2144 SYNC_response res;
2145
2146 res.hdr.response_len = sizeof(res.hdr);
2147 res.payload.buf = *vp;
2148 res.payload.len = sizeof(Volume);
2149
2150 code = FSYNC_VolOp(volumeId,
2151 pname,
2152 FSYNC_VOL_QUERY,
2153 0,
2154 &res);
2155
2156 if (code != SYNC_OK) {
2157 switch (res.hdr.reason) {
2158 case FSYNC_WRONG_PART:
2159 case FSYNC_UNKNOWN_VOLID:
2160 *vp = NULL((void *)0);
2161 code = SYNC_OK;
2162 break;
2163 }
2164 }
2165
2166 return code;
2167}
2168
2169#endif
2170
2171/**
2172 * mode of volume list operation.
2173 */
2174typedef enum {
2175 VOL_INFO_LIST_SINGLE, /**< performing a single volume list op */
2176 VOL_INFO_LIST_MULTIPLE /**< performing a multi-volume list op */
2177} vol_info_list_mode_t;
2178
2179/**
2180 * abstract interface to populate wire-format volume metadata structures.
2181 *
2182 * @param[in] partId partition id
2183 * @param[in] volumeId volume id
2184 * @param[in] pname partition name
2185 * @param[in] volname volume file name
2186 * @param[in] handle handle to on-wire volume metadata object
2187 * @param[in] mode listing mode
2188 *
2189 * @return operation status
2190 * @retval 0 success
2191 * @retval -2 DESTROY_ME flag is set
2192 * @retval -1 general failure; some data filled in
2193 * @retval -3 couldn't create vtrans; some data filled in
2194 */
2195static int
2196GetVolInfo(afs_uint32 partId,
2197 afs_uint32 volumeId,
2198 char * pname,
2199 char * volname,
2200 volint_info_handle_t * handle,
2201 vol_info_list_mode_t mode)
2202{
2203 int code = -1;
2204 Errorbit32 error;
2205 struct volser_trans *ttc = NULL((void *)0);
2206 struct Volume *fill_tv, *tv = NULL((void *)0);
2207#ifdef AFS_DEMAND_ATTACH_FS
2208 struct Volume fs_tv_buf, *fs_tv = &fs_tv_buf; /* Create a structure, and a pointer to that structure */
2209 SYNC_PROTO_BUF_DECL(fs_res_buf)afs_int64 _fs_res_buf_l[768/sizeof(afs_int64)]; char * fs_res_buf
= (char *)(_fs_res_buf_l)
; /* Buffer for the pending_vol_op */
2210 SYNC_response fs_res; /* Response handle for the pending_vol_op */
2211 FSSYNC_VolOp_info pending_vol_op_res; /* Pending vol ops to full in volume */
2212
2213 /* Set up response handle for pending_vol_op */
2214 fs_res.hdr.response_len = sizeof(fs_res.hdr);
2215 fs_res.payload.buf = fs_res_buf;
2216 fs_res.payload.len = SYNC_PROTO_MAX_LEN768;
2217#endif
2218
2219 ttc = NewTrans(volumeId, partId);
2220 if (!ttc) {
2221 code = -3;
2222 VOLINT_INFO_STORE(handle, status, VOLSERVOLBUSY)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->status = ((1492325133L)); }
else { (handle)->volinfo_ptr.ext->status = ((1492325133L
)); } } while(0)
;
2223 VOLINT_INFO_STORE(handle, volid, volumeId)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->volid = (volumeId); } else
{ (handle)->volinfo_ptr.ext->volid = (volumeId); } } while
(0)
;
2224 goto drop;
2225 }
2226
2227 /* Get volume from volserver */
2228 if (mode == VOL_INFO_LIST_MULTIPLE)
2229 tv = VAttachVolumeByName(&error, pname, volname, V_PEEK6);
2230 else
2231 tv = VAttachVolumeByName_retry(&error, pname, volname, V_PEEK6);
2232 if (error) {
2233 Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n",
2234 volumeId, pname, volname, error);
2235 goto drop;
2236 }
2237
2238 /*
2239 * please note that destroyMe and needsSalvaged checks used to be ordered
2240 * in the opposite manner for ListVolumes and XListVolumes. I think it's
2241 * more correct to check destroyMe before needsSalvaged.
2242 * -- tkeiser 11/28/2007
2243 */
2244
2245 if (tv->header->diskstuff.destroyMe == DESTROY_ME0xD3) {
2246 switch (mode) {
2247 case VOL_INFO_LIST_MULTIPLE:
2248 code = -2;
2249 goto drop;
2250
2251 case VOL_INFO_LIST_SINGLE:
2252 Log("1 Volser: GetVolInfo: Volume %u (%s:%s) will be destroyed on next salvage\n",
2253 volumeId, pname, volname);
2254
2255 default:
2256 goto drop;
2257 }
2258 }
2259
2260 if (tv->header->diskstuff.needsSalvaged) {
2261 /*this volume will be salvaged */
2262 Log("1 Volser: GetVolInfo: Volume %u (%s:%s) needs to be salvaged\n",
2263 volumeId, pname, volname);
2264 }
2265
2266#ifdef AFS_DEMAND_ATTACH_FS
2267 /* If using DAFS, get volume from fsserver */
2268 if (GetVolObject(volumeId, pname, &fs_tv) != SYNC_OK || fs_tv == NULL((void *)0)) {
2269
2270 goto drop;
2271 }
2272
2273 /* fs_tv is a shallow copy, must populate certain structures before passing along */
2274 if (FSYNC_VolOp(volumeId, pname, FSYNC_VOL_QUERY_VOP, 0, &fs_res) == SYNC_OK) {
2275 /* If we if the pending vol op */
2276 memcpy(&pending_vol_op_res, fs_res.payload.buf, sizeof(FSSYNC_VolOp_info));
2277 fs_tv->pending_vol_op=&pending_vol_op_res;
2278 } else {
2279 fs_tv->pending_vol_op=NULL((void *)0);
2280 }
2281
2282 /* populate the header from the volserver copy */
2283 fs_tv->header=tv->header;
2284
2285 /* When using DAFS, use the fs volume info, populated with required structures */
2286 fill_tv = fs_tv;
2287#else
2288 /* When not using DAFS, just use the local volume info */
2289 fill_tv = tv;
2290#endif
2291
2292 /* ok, we have all the data we need; fill in the on-wire struct */
2293 code = FillVolInfo(fill_tv, handle);
2294
2295 drop:
2296 if (code == -1) {
2297 VOLINT_INFO_STORE(handle, status, 0)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->status = (0); } else { (handle
)->volinfo_ptr.ext->status = (0); } } while(0)
;
2298 strcpy((char *)VOLINT_INFO_PTR(handle, name)(((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) ? &
((handle)->volinfo_ptr.base->name) : &((handle)->
volinfo_ptr.ext->name))
, volname);
2299 VOLINT_INFO_STORE(handle, volid, volumeId)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->volid = (volumeId); } else
{ (handle)->volinfo_ptr.ext->volid = (volumeId); } } while
(0)
;
2300 }
2301 if (tv) {
2302 VDetachVolume(&error, tv);
2303 tv = NULL((void *)0);
2304 if (error) {
2305 VOLINT_INFO_STORE(handle, status, 0)do { if ((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) {
(handle)->volinfo_ptr.base->status = (0); } else { (handle
)->volinfo_ptr.ext->status = (0); } } while(0)
;
2306 strcpy((char *)VOLINT_INFO_PTR(handle, name)(((handle)->volinfo_type == VOLINT_INFO_TYPE_BASE) ? &
((handle)->volinfo_ptr.base->name) : &((handle)->
volinfo_ptr.ext->name))
, volname);
2307 Log("1 Volser: GetVolInfo: Could not detach volume %u (%s:%s)\n",
2308 volumeId, pname, volname);
2309 }
2310 }
2311 if (ttc) {
2312 DeleteTrans(ttc, 1);
2313 ttc = NULL((void *)0);
2314 }
2315 return code;
2316}
2317
2318
2319/*return the header information about the <volid> */
2320afs_int32
2321SAFSVolListOneVolume(struct rx_call *acid, afs_int32 partid,
2322 afs_uint32 volumeId, volEntries *volumeInfo)
2323{
2324 afs_int32 code;
2325
2326 code = VolListOneVolume(acid, partid, volumeId, volumeInfo);
2327 osi_auditU(acid, VS_Lst1VolEvent"AFS_VS_Lst1Vol", code, AUD_LONG5, volumeId, AUD_END0);
2328 return code;
2329}
2330
2331static afs_int32
2332VolListOneVolume(struct rx_call *acid, afs_int32 partid,
2333 afs_uint32 volumeId, volEntries *volumeInfo)
2334{
2335 struct DiskPartition64 *partP;
2336 char pname[9], volname[20];
2337 DIR *dirp;
2338 afs_uint32 volid;
2339 int found = 0;
2340 int code;
2341 volint_info_handle_t handle;
2342
2343 volumeInfo->volEntries_val = (volintInfo *) malloc(sizeof(volintInfo));
2344 if (!volumeInfo->volEntries_val)
2345 return ENOMEM12;
2346 memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
2347
2348 volumeInfo->volEntries_len = 1;
2349 if (GetPartName(partid, pname))
2350 return VOLSERILLEGAL_PARTITION(1492325125L);
2351 if (!(partP = VGetPartition(pname, 0)))
2352 return VOLSERILLEGAL_PARTITION(1492325125L);
2353 dirp = opendir(VPartitionPath(partP));
2354 if (dirp == NULL((void *)0))
2355 return VOLSERILLEGAL_PARTITION(1492325125L);
2356
2357 strcpy(volname, "");
2358
2359 while (strcmp(volname, "EOD") && !found) { /*while there are more volumes in the partition */
2360
2361 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2362 GetNextVol(dirp, volname, &volid);
2363 continue; /*back to while loop */
2364 }
2365
2366 if (volid == volumeId) { /*copy other things too */
2367 found = 1;
2368 break;
2369 }
2370
2371 GetNextVol(dirp, volname, &volid);
2372 }
2373
2374 if (found) {
2375#ifndef AFS_PTHREAD_ENV
2376 IOMGR_Poll(); /*make sure that the client does not time out */
2377#endif
2378
2379 handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
2380 handle.volinfo_ptr.base = volumeInfo->volEntries_val;
2381
2382 code = GetVolInfo(partid,
2383 volid,
2384 pname,
2385 volname,
2386 &handle,
2387 VOL_INFO_LIST_SINGLE);
2388 }
2389
2390 closedir(dirp);
2391 if (found)
2392 return code ? ENODEV19: 0;
2393 else
2394 return ENODEV19;
2395}
2396
2397/*------------------------------------------------------------------------
2398 * EXPORTED SAFSVolXListOneVolume
2399 *
2400 * Description:
2401 * Returns extended info on volume a_volID on partition a_partID.
2402 *
2403 * Arguments:
2404 * a_rxCidP : Pointer to the Rx call we're performing.
2405 * a_partID : Partition for which we want the extended list.
2406 * a_volID : Volume ID we wish to know about.
2407 * a_volumeXInfoP : Ptr to the extended info blob.
2408 *
2409 * Returns:
2410 * 0 Successful operation
2411 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2412 *
2413 * Environment:
2414 * Nothing interesting.
2415 *
2416 * Side Effects:
2417 * As advertised.
2418 *------------------------------------------------------------------------*/
2419
2420afs_int32
2421SAFSVolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
2422 afs_uint32 a_volID, volXEntries *a_volumeXInfoP)
2423{
2424 afs_int32 code;
2425
2426 code = VolXListOneVolume(a_rxCidP, a_partID, a_volID, a_volumeXInfoP);
2427 osi_auditU(a_rxCidP, VS_XLst1VlEvent"AFS_VS_XLst1Vl", code, AUD_LONG5, a_volID, AUD_END0);
2428 return code;
2429}
2430
2431static afs_int32
2432VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
2433 afs_uint32 a_volID, volXEntries *a_volumeXInfoP)
2434{ /*SAFSVolXListOneVolume */
2435
2436 struct DiskPartition64 *partP; /*Ptr to partition */
2437 char pname[9], volname[20]; /*Partition, volume names */
2438 DIR *dirp; /*Partition directory ptr */
2439 afs_uint32 currVolID; /*Current volume ID */
2440 int found = 0; /*Did we find the volume we need? */
2441 int code;
2442 volint_info_handle_t handle;
2443
2444 /*
2445 * Set up our pointers for action, marking our structure to hold exactly
2446 * one entry. Also, assume we'll fail in our quest.
2447 */
2448 a_volumeXInfoP->volXEntries_val =
2449 (volintXInfo *) malloc(sizeof(volintXInfo));
2450 if (!a_volumeXInfoP->volXEntries_val)
2451 return ENOMEM12;
2452 memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
2453
2454 a_volumeXInfoP->volXEntries_len = 1;
2455 code = ENODEV19;
2456
2457 /*
2458 * If the partition name we've been given is bad, bogue out.
2459 */
2460 if (GetPartName(a_partID, pname))
2461 return (VOLSERILLEGAL_PARTITION(1492325125L));
2462
2463 /*
2464 * Open the directory representing the given AFS parttion. If we can't
2465 * do that, we lose.
2466 */
2467 if (!(partP = VGetPartition(pname, 0)))
2468 return VOLSERILLEGAL_PARTITION(1492325125L);
2469 dirp = opendir(VPartitionPath(partP));
2470 if (dirp == NULL((void *)0))
2471 return (VOLSERILLEGAL_PARTITION(1492325125L));
2472
2473 strcpy(volname, "");
2474
2475 /*
2476 * Sweep through the partition directory, looking for the desired entry.
2477 * First, of course, figure out how many stat bytes to copy out of each
2478 * volume.
2479 */
2480 while (strcmp(volname, "EOD") && !found) {
2481 /*
2482 * If this is not a volume, move on to the next entry in the
2483 * partition's directory.
2484 */
2485 if (!strcmp(volname, "")) {
2486 GetNextVol(dirp, volname, &currVolID);
2487 continue;
2488 }
2489
2490 if (currVolID == a_volID) {
2491 /*
2492 * We found the volume entry we're interested. Pull out the
2493 * extended information, remembering to poll (so that the client
2494 * doesn't time out) and to set up a transaction on the volume.
2495 */
2496 found = 1;
2497 break;
2498 } /*Found desired volume */
2499
2500 GetNextVol(dirp, volname, &currVolID);
2501 }
2502
2503 if (found) {
2504#ifndef AFS_PTHREAD_ENV
2505 IOMGR_Poll();
2506#endif
2507
2508 handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
2509 handle.volinfo_ptr.ext = a_volumeXInfoP->volXEntries_val;
2510
2511 code = GetVolInfo(a_partID,
2512 a_volID,
2513 pname,
2514 volname,
2515 &handle,
2516 VOL_INFO_LIST_SINGLE);
2517
2518 }
2519
2520 /*
2521 * Clean up before going to dinner: close the partition directory,
2522 * return the proper value.
2523 */
2524 closedir(dirp);
2525 if (found)
2526 return code ? ENODEV19: 0;
2527 else
2528 return ENODEV19;
2529} /*SAFSVolXListOneVolume */
2530
2531/*returns all the volumes on partition partid. If flags = 1 then all the
2532* relevant info about the volumes is also returned */
2533afs_int32
2534SAFSVolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2535 volEntries *volumeInfo)
2536{
2537 afs_int32 code;
2538
2539 code = VolListVolumes(acid, partid, flags, volumeInfo);
2540 osi_auditU(acid, VS_ListVolEvent"AFS_VS_ListVol", code, AUD_END0);
2541 return code;
2542}
2543
2544static afs_int32
2545VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags,
2546 volEntries *volumeInfo)
2547{
2548 volintInfo *pntr;
2549 struct DiskPartition64 *partP;
2550 afs_int32 allocSize = 1000; /*to be changed to a larger figure */
2551 char pname[9], volname[20];
2552 DIR *dirp;
2553 afs_uint32 volid;
2554 int code;
2555 volint_info_handle_t handle;
2556
2557 volumeInfo->volEntries_val =
2558 (volintInfo *) malloc(allocSize * sizeof(volintInfo));
2559 if (!volumeInfo->volEntries_val)
2560 return ENOMEM12;
2561 memset(volumeInfo->volEntries_val, 0, sizeof(volintInfo)); /* Clear structure */
2562
2563 pntr = volumeInfo->volEntries_val;
2564 volumeInfo->volEntries_len = 0;
2565 if (GetPartName(partid, pname))
2566 return VOLSERILLEGAL_PARTITION(1492325125L);
2567 if (!(partP = VGetPartition(pname, 0)))
2568 return VOLSERILLEGAL_PARTITION(1492325125L);
2569 dirp = opendir(VPartitionPath(partP));
2570 if (dirp == NULL((void *)0))
2571 return VOLSERILLEGAL_PARTITION(1492325125L);
2572 strcpy(volname, "");
2573
2574 while (strcmp(volname, "EOD")) { /*while there are more partitions in the partition */
2575
2576 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
2577 GetNextVol(dirp, volname, &volid);
2578 continue; /*back to while loop */
2579 }
2580
2581 if (flags) { /*copy other things too */
2582#ifndef AFS_PTHREAD_ENV
2583 IOMGR_Poll(); /*make sure that the client does not time out */
2584#endif
2585
2586 handle.volinfo_type = VOLINT_INFO_TYPE_BASE;
2587 handle.volinfo_ptr.base = pntr;
2588
2589
2590 code = GetVolInfo(partid,
2591 volid,
2592 pname,
2593 volname,
2594 &handle,
2595 VOL_INFO_LIST_MULTIPLE);
2596 if (code == -2) { /* DESTROY_ME flag set */
2597 goto drop2;
2598 }
2599 } else {
2600 pntr->volid = volid;
2601 /*just volids are needed */
2602 }
2603
2604 pntr++;
2605 volumeInfo->volEntries_len += 1;
2606 if ((allocSize - volumeInfo->volEntries_len) < 5) {
2607 /*running out of space, allocate more space */
2608 allocSize = (allocSize * 3) / 2;
2609 pntr =
2610 (volintInfo *) realloc((char *)volumeInfo->volEntries_val,
2611 allocSize * sizeof(volintInfo));
2612 if (pntr == NULL((void *)0)) {
2613 closedir(dirp);
2614 return VOLSERNO_MEMORY(1492325134L);
2615 }
2616 volumeInfo->volEntries_val = pntr; /* point to new block */
2617 /* set pntr to the right position */
2618 pntr = volumeInfo->volEntries_val + volumeInfo->volEntries_len;
2619
2620 }
2621
2622 drop2:
2623 GetNextVol(dirp, volname, &volid);
2624
2625 }
2626
2627 closedir(dirp);
2628 return 0;
2629}
2630
2631/*------------------------------------------------------------------------
2632 * EXPORTED SAFSVolXListVolumes
2633 *
2634 * Description:
2635 * Returns all the volumes on partition a_partID. If a_flags
2636 * is set to 1, then all the relevant extended volume information
2637 * is also returned.
2638 *
2639 * Arguments:
2640 * a_rxCidP : Pointer to the Rx call we're performing.
2641 * a_partID : Partition for which we want the extended list.
2642 * a_flags : Various flags.
2643 * a_volumeXInfoP : Ptr to the extended info blob.
2644 *
2645 * Returns:
2646 * 0 Successful operation
2647 * VOLSERILLEGAL_PARTITION if we got a bogus partition ID
2648 * VOLSERNO_MEMORY if we ran out of memory allocating
2649 * our return blob
2650 *
2651 * Environment:
2652 * Nothing interesting.
2653 *
2654 * Side Effects:
2655 * As advertised.
2656 *------------------------------------------------------------------------*/
2657
2658afs_int32
2659SAFSVolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2660 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2661{
2662 afs_int32 code;
2663
2664 code = VolXListVolumes(a_rxCidP, a_partID, a_flags, a_volumeXInfoP);
2665 osi_auditU(a_rxCidP, VS_XLstVolEvent"AFS_VS_XLstVol", code, AUD_END0);
2666 return code;
2667}
2668
2669static afs_int32
2670VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID,
2671 afs_int32 a_flags, volXEntries *a_volumeXInfoP)
2672{ /*SAFSVolXListVolumes */
2673
2674 volintXInfo *xInfoP; /*Ptr to the extended vol info */
2675 struct DiskPartition64 *partP; /*Ptr to partition */
2676 afs_int32 allocSize = 1000; /*To be changed to a larger figure */
2677 char pname[9], volname[20]; /*Partition, volume names */
2678 DIR *dirp; /*Partition directory ptr */
2679 afs_uint32 volid; /*Current volume ID */
2680 int code;
2681 volint_info_handle_t handle;
2682
2683 /*
2684 * Allocate a large array of extended volume info structures, then
2685 * set it up for action.
2686 */
2687 a_volumeXInfoP->volXEntries_val =
2688 (volintXInfo *) malloc(allocSize * sizeof(volintXInfo));
2689 if (!a_volumeXInfoP->volXEntries_val)
2690 return ENOMEM12;
2691 memset(a_volumeXInfoP->volXEntries_val, 0, sizeof(volintXInfo)); /* Clear structure */
2692
2693 xInfoP = a_volumeXInfoP->volXEntries_val;
2694 a_volumeXInfoP->volXEntries_len = 0;
2695
2696 /*
2697 * If the partition name we've been given is bad, bogue out.
2698 */
2699 if (GetPartName(a_partID, pname))
2700 return (VOLSERILLEGAL_PARTITION(1492325125L));
2701
2702 /*
2703 * Open the directory representing the given AFS parttion. If we can't
2704 * do that, we lose.
2705 */
2706 if (!(partP = VGetPartition(pname, 0)))
2707 return VOLSERILLEGAL_PARTITION(1492325125L);
2708 dirp = opendir(VPartitionPath(partP));
2709 if (dirp == NULL((void *)0))
2710 return (VOLSERILLEGAL_PARTITION(1492325125L));
2711 strcpy(volname, "");
2712
2713 /*
2714 * Sweep through the partition directory, acting on each entry. First,
2715 * of course, figure out how many stat bytes to copy out of each volume.
2716 */
2717 while (strcmp(volname, "EOD")) {
2718
2719 /*
2720 * If this is not a volume, move on to the next entry in the
2721 * partition's directory.
2722 */
2723 if (!strcmp(volname, "")) {
2724 GetNextVol(dirp, volname, &volid);
2725 continue;
2726 }
2727
2728 if (a_flags) {
2729 /*
2730 * Full info about the volume desired. Poll to make sure the
2731 * client doesn't time out, then start up a new transaction.
2732 */
2733#ifndef AFS_PTHREAD_ENV
2734 IOMGR_Poll();
2735#endif
2736
2737 handle.volinfo_type = VOLINT_INFO_TYPE_EXT;
2738 handle.volinfo_ptr.ext = xInfoP;
2739
2740 code = GetVolInfo(a_partID,
2741 volid,
2742 pname,
2743 volname,
2744 &handle,
2745 VOL_INFO_LIST_MULTIPLE);
2746 if (code == -2) { /* DESTROY_ME flag set */
2747 goto drop2;
2748 }
2749 } else {
2750 /*
2751 * Just volume IDs are needed.
2752 */
2753 xInfoP->volid = volid;
2754 }
2755
2756 /*
2757 * Bump the pointer in the data area we're building, along with
2758 * the count of the number of entries it contains.
2759 */
2760 xInfoP++;
2761 (a_volumeXInfoP->volXEntries_len)++;
2762 if ((allocSize - a_volumeXInfoP->volXEntries_len) < 5) {
2763 /*
2764 * We're running out of space in the area we've built. Grow it.
2765 */
2766 allocSize = (allocSize * 3) / 2;
2767 xInfoP = (volintXInfo *)
2768 realloc((char *)a_volumeXInfoP->volXEntries_val,
2769 (allocSize * sizeof(volintXInfo)));
2770 if (xInfoP == NULL((void *)0)) {
2771 /*
2772 * Bummer, no memory. Bag it, tell our caller what went wrong.
2773 */
2774 closedir(dirp);
2775 return (VOLSERNO_MEMORY(1492325134L));
2776 }
2777
2778 /*
2779 * Memory reallocation worked. Correct our pointers so they
2780 * now point to the new block and the current open position within
2781 * the new block.
2782 */
2783 a_volumeXInfoP->volXEntries_val = xInfoP;
2784 xInfoP =
2785 a_volumeXInfoP->volXEntries_val +
2786 a_volumeXInfoP->volXEntries_len;
2787 }
2788
2789 drop2:
2790 GetNextVol(dirp, volname, &volid);
2791 } /*Sweep through the partition directory */
2792
2793 /*
2794 * We've examined all entries in the partition directory. Close it,
2795 * delete our transaction (if any), and go home happy.
2796 */
2797 closedir(dirp);
2798 return (0);
2799
2800} /*SAFSVolXListVolumes */
2801
2802/*this call is used to monitor the status of volser for debugging purposes.
2803 *information about all the active transactions is returned in transInfo*/
2804afs_int32
2805SAFSVolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2806{
2807 afs_int32 code;
2808
2809 code = VolMonitor(acid, transInfo);
2810 osi_auditU(acid, VS_MonitorEvent"AFS_VS_Monitor", code, AUD_END0);
2811 return code;
2812}
2813
2814static afs_int32
2815VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
2816{
2817 transDebugInfo *pntr;
2818 afs_int32 allocSize = 50;
2819 struct volser_trans *tt, *nt, *allTrans;
2820
2821 transInfo->transDebugEntries_val =
2822 (transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
2823 if (!transInfo->transDebugEntries_val)
2824 return ENOMEM12;
2825 pntr = transInfo->transDebugEntries_val;
2826 transInfo->transDebugEntries_len = 0;
2827
2828 VTRANS_LOCK;
2829 allTrans = TransList();
2830 if (allTrans == (struct volser_trans *)0)
2831 goto done; /*no active transactions */
2832 for (tt = allTrans; tt; tt = nt) { /*copy relevant info into pntr */
2833 nt = tt->next;
2834 VTRANS_OBJ_LOCK(tt);
2835 pntr->tid = tt->tid;
2836 pntr->time = tt->time;
2837 pntr->creationTime = tt->creationTime;
2838 pntr->returnCode = tt->returnCode;
2839 pntr->volid = tt->volid;
2840 pntr->partition = tt->partition;
2841 pntr->iflags = tt->iflags;
2842 pntr->vflags = tt->vflags;
2843 pntr->tflags = tt->tflags;
2844 strcpy(pntr->lastProcName, tt->lastProcName);
2845 pntr->callValid = 0;
2846 if (tt->rxCallPtr) { /*record call related info */
2847 pntr->callValid = 1;
2848 pntr->readNext = tt->rxCallPtr->rnext;
2849 pntr->transmitNext = tt->rxCallPtr->tnext;
2850 pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
2851 pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
2852 }
2853 VTRANS_OBJ_UNLOCK(tt);
2854 pntr++;
2855 transInfo->transDebugEntries_len += 1;
2856 if ((allocSize - transInfo->transDebugEntries_len) < 5) { /*alloc some more space */
2857 allocSize = (allocSize * 3) / 2;
2858 pntr =
2859 (transDebugInfo *) realloc((char *)transInfo->
2860 transDebugEntries_val,
2861 allocSize *
2862 sizeof(transDebugInfo));
2863 transInfo->transDebugEntries_val = pntr;
2864 pntr =
2865 transInfo->transDebugEntries_val +
2866 transInfo->transDebugEntries_len;
2867 /*set pntr to right position */
2868 }
2869
2870 }
2871done:
2872 VTRANS_UNLOCK;
2873
2874 return 0;
2875}
2876
2877afs_int32
2878SAFSVolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[],
2879 afs_int32 type, afs_uint32 pId, afs_uint32 cloneId,
2880 afs_uint32 backupId)
2881{
2882 afs_int32 code;
2883
2884 code = VolSetIdsTypes(acid, atid, name, type, pId, cloneId, backupId);
2885 osi_auditU(acid, VS_SetIdTyEvent"AFS_VS_SetIdTy", code, AUD_LONG5, atid, AUD_STR1, name,
2886 AUD_LONG5, type, AUD_LONG5, pId, AUD_LONG5, cloneId, AUD_LONG5,
2887 backupId, AUD_END0);
2888 return code;
2889}
2890
2891static afs_int32
2892VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[],
2893 afs_int32 type, afs_uint32 pId, afs_uint32 cloneId,
2894 afs_uint32 backupId)
2895{
2896 struct Volume *tv;
2897 Errorbit32 error = 0;
2898 struct volser_trans *tt;
2899 char caller[MAXKTCNAMELEN64];
2900
2901 if (strlen(name) > 31)
2902 return VOLSERBADNAME(1492325129L);
2903 if (!afsconf_SuperUser(tdir, acid, caller))
2904 return VOLSERBAD_ACCESS(1492325127L); /*not a super user */
2905 /* find the trans */
2906 tt = FindTrans(atid);
2907 if (!tt)
2908 return ENOENT2;
2909 if (tt->vflags & VTDeleted4) {
2910 Log("1 Volser: VolSetIds: volume %u has been deleted \n", tt->volid);
2911 TRELE(tt);
2912 return ENOENT2;
2913 }
2914 TSetRxCall(tt, acid, "SetIdsTypes");
2915 tv = tt->volume;
2916
2917 V_type(tv)((tv)->header->diskstuff.type) = type;
2918 V_backupId(tv)((tv)->header->diskstuff.backupId) = backupId;
2919 V_cloneId(tv)((tv)->header->diskstuff.cloneId) = cloneId;
2920 V_parentId(tv)((tv)->header->diskstuff.parentId) = pId;
2921 strcpy((&V_disk(tv)((tv)->header->diskstuff))->name, name);
2922 VUpdateVolume(&error, tv);
2923 if (error) {
2924 Log("1 Volser: SetIdsTypes: VUpdate failed code %d\n", error);
2925 LogError(error);
2926 goto fail;
2927 }
2928 TClearRxCall(tt);
2929 if (TRELE(tt) && !error)
2930 return VOLSERTRELE_ERROR(1492325120L);
2931
2932 return error;
2933 fail:
2934 TClearRxCall(tt);
2935 if (TRELE(tt) && !error)
2936 return VOLSERTRELE_ERROR(1492325120L);
2937 return error;
2938}
2939
2940afs_int32
2941SAFSVolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2942{
2943 afs_int32 code;
2944
2945 code = VolSetDate(acid, atid, cdate);
2946 osi_auditU(acid, VS_SetDateEvent"AFS_VS_SetDate", code, AUD_LONG5, atid, AUD_LONG5, cdate,
2947 AUD_END0);
2948 return code;
2949}
2950
2951static afs_int32
2952VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
2953{
2954 struct Volume *tv;
2955 Errorbit32 error = 0;
2956 struct volser_trans *tt;
2957 char caller[MAXKTCNAMELEN64];
2958
2959 if (!afsconf_SuperUser(tdir, acid, caller))
2960 return VOLSERBAD_ACCESS(1492325127L); /*not a super user */
2961 /* find the trans */
2962 tt = FindTrans(atid);
2963 if (!tt)
2964 return ENOENT2;
2965 if (tt->vflags & VTDeleted4) {
2966 Log("1 Volser: VolSetDate: volume %u has been deleted \n", tt->volid);
2967 TRELE(tt);
2968 return ENOENT2;
2969 }
2970 TSetRxCall(tt, acid, "SetDate");
2971 tv = tt->volume;
2972
2973 V_creationDate(tv)((tv)->header->diskstuff.creationDate) = cdate;
2974 VUpdateVolume(&error, tv);
2975 if (error) {
2976 Log("1 Volser: SetDate: VUpdate failed code %d\n", error);
2977 LogError(error);
2978 goto fail;
2979 }
2980 TClearRxCall(tt);
2981 if (TRELE(tt) && !error)
2982 return VOLSERTRELE_ERROR(1492325120L);
2983
2984 return error;
2985 fail:
2986 TClearRxCall(tt);
2987 if (TRELE(tt) && !error)
2988 return VOLSERTRELE_ERROR(1492325120L);
2989 return error;
2990}
2991
2992afs_int32
2993SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
2994 afs_uint32 volumeId)
2995{
2996#ifdef AFS_NT40_ENV
2997 return EXDEV18;
2998#else
2999 char caller[MAXKTCNAMELEN64];
3000 DIR *dirp;
3001 struct volser_trans *ttc;
3002 char pname[16], volname[20];
3003 struct DiskPartition64 *partP;
3004 afs_int32 ret = ENODEV19;
3005 afs_uint32 volid;
3006
3007 if (!afsconf_SuperUser(tdir, acid, caller))
3008 return VOLSERBAD_ACCESS(1492325127L); /*not a super user */
3009 if (GetPartName(partId, pname))
3010 return VOLSERILLEGAL_PARTITION(1492325125L);
3011 if (!(partP = VGetPartition(pname, 0)))
3012 return VOLSERILLEGAL_PARTITION(1492325125L);
3013 dirp = opendir(VPartitionPath(partP));
3014 if (dirp == NULL((void *)0))
3015 return VOLSERILLEGAL_PARTITION(1492325125L);
3016 strcpy(volname, "");
3017 ttc = (struct volser_trans *)0;
3018
3019 while (strcmp(volname, "EOD")) {
3020 if (!strcmp(volname, "")) { /* its not a volume, fetch next file */
3021 GetNextVol(dirp, volname, &volid);
3022 continue; /*back to while loop */
3023 }
3024
3025 if (volid == volumeId) { /*copy other things too */
3026#ifndef AFS_PTHREAD_ENV
3027 IOMGR_Poll(); /*make sure that the client doesnot time out */
3028#endif
3029 ttc = NewTrans(volumeId, partId);
3030 if (!ttc) {
3031 return VOLSERVOLBUSY(1492325133L);
3032 }
3033#ifdef AFS_NAMEI_ENV1
3034 ret = namei_ConvertROtoRWvolume(pname, volumeId);
3035#else
3036 ret = inode_ConvertROtoRWvolume(pname, volumeId);
3037#endif
3038 break;
3039 }
3040 GetNextVol(dirp, volname, &volid);
3041 }
3042
3043 if (ttc) {
3044 DeleteTrans(ttc, 1);
3045 ttc = (struct volser_trans *)0;
3046 }
3047
3048 closedir(dirp);
3049 return ret;
3050#endif
3051}
3052
3053afs_int32
3054SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
3055 struct volintSize *size)
3056{
3057 int code = 0;
3058 struct volser_trans *tt;
3059 char caller[MAXKTCNAMELEN64];
3060
3061 if (!afsconf_SuperUser(tdir, acid, caller))
3062 return VOLSERBAD_ACCESS(1492325127L); /*not a super user */
3063 tt = FindTrans(fromTrans);
3064 if (!tt)
3065 return ENOENT2;
3066 if (tt->vflags & VTDeleted4) {
3067 TRELE(tt);
3068 return ENOENT2;
3069 }
3070 TSetRxCall(tt, acid, "GetSize");
3071 code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size); /* measure volume's data */
3072 TClearRxCall(tt);
3073 if (TRELE(tt))
3074 return VOLSERTRELE_ERROR(1492325120L);
3075
3076/* osi_auditU(acid, VS_DumpEvent, code, AUD_LONG, fromTrans, AUD_END); */
3077 return code;
3078}
3079
3080afs_int32
3081SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 vid, afs_uint32 new,
3082 afs_uint32 where, afs_int32 verbose)
3083{
3084#if defined(AFS_NAMEI_ENV1) && !defined(AFS_NT40_ENV)
3085 Errorbit32 code, code2;
3086 Volume *vol=0, *newvol=0;
3087 struct volser_trans *tt = 0, *tt2 = 0;
3088 char caller[MAXKTCNAMELEN64];
3089 char line[128];
3090
3091 if (!afsconf_SuperUser(tdir, acall, caller))
3092 return EPERM1;
3093
3094 vol = VAttachVolume(&code, vid, V_VOLUPD3);
3095 if (!vol) {
3096 if (!code)
3097 code = ENOENT2;
3098 return code;
3099 }
3100 newvol = VAttachVolume(&code, new, V_VOLUPD3);
3101 if (!newvol) {
3102 VDetachVolume(&code2, vol);
3103 if (!code)
3104 code = ENOENT2;
3105 return code;
3106 }
3107 if (V_device(vol)((vol)->device) != V_device(newvol)((newvol)->device)
3108 || V_uniquifier(newvol)((newvol)->header->diskstuff.uniquifier) != 2) {
3109 if (V_device(vol)((vol)->device) != V_device(newvol)((newvol)->device)) {
3110 sprintf(line, "Volumes %u and %u are not in the same partition, aborted.\n",
3111 vid, new);
3112 rx_Write(acall, line, strlen(line))rx_WriteProc(acall, line, strlen(line));
3113 }
3114 if (V_uniquifier(newvol)((newvol)->header->diskstuff.uniquifier) != 2) {
3115 sprintf(line, "Volume %u is not freshly created, aborted.\n", new);
3116 rx_Write(acall, line, strlen(line))rx_WriteProc(acall, line, strlen(line));
3117 }
3118 line[0] = 0;
3119 rx_Write(acall, line, 1)rx_WriteProc(acall, line, 1);
3120 VDetachVolume(&code2, vol);
3121 VDetachVolume(&code2, newvol);
3122 return EINVAL22;
3123 }
3124 tt = NewTrans(vid, V_device(vol)((vol)->device));
3125 if (!tt) {
3126 sprintf(line, "Couldn't create transaction for %u, aborted.\n", vid);
3127 rx_Write(acall, line, strlen(line))rx_WriteProc(acall, line, strlen(line));
3128 line[0] = 0;
3129 rx_Write(acall, line, 1)rx_WriteProc(acall, line, 1);
3130 VDetachVolume(&code2, vol);
3131 VDetachVolume(&code2, newvol);
3132 return VOLSERVOLBUSY(1492325133L);
3133 }
3134 VTRANS_OBJ_LOCK(tt);
3135 tt->iflags = ITBusy2;
3136 tt->vflags = 0;
3137 TSetRxCall_r(tt, NULL((void *)0), "SplitVolume");
3138 VTRANS_OBJ_UNLOCK(tt);
3139
3140 tt2 = NewTrans(new, V_device(newvol)((newvol)->device));
3141 if (!tt2) {
3142 sprintf(line, "Couldn't create transaction for %u, aborted.\n", new);
3143 rx_Write(acall, line, strlen(line))rx_WriteProc(acall, line, strlen(line));
3144 line[0] = 0;
3145 rx_Write(acall, line, 1)rx_WriteProc(acall, line, 1);
3146 DeleteTrans(tt, 1);
3147 VDetachVolume(&code2, vol);
3148 VDetachVolume(&code2, newvol);
3149 return VOLSERVOLBUSY(1492325133L);
3150 }
3151 VTRANS_OBJ_LOCK(tt2);
3152 tt2->iflags = ITBusy2;
3153 tt2->vflags = 0;
3154 TSetRxCall_r(tt2, NULL((void *)0), "SplitVolume");
3155 VTRANS_OBJ_UNLOCK(tt2);
3156
3157 code = split_volume(acall, vol, newvol, where, verbose);
3158
3159 VDetachVolume(&code2, vol);
3160 DeleteTrans(tt, 1);
3161 VDetachVolume(&code2, newvol);
3162 DeleteTrans(tt2, 1);
3163 return code;
3164#else
3165 return VOLSERBADOP(1492325131L);
3166#endif
3167}
3168
3169/* GetPartName - map partid (a decimal number) into pname (a string)
3170 * Since for NT we actually want to return the drive name, we map through the
3171 * partition struct.
3172 */
3173static int
3174GetPartName(afs_int32 partid, char *pname)
3175{
3176 if (partid < 0)
3177 return -1;
3178 if (partid < 26) {
3179 strcpy(pname, "/vicep");
3180 pname[6] = 'a' + partid;
3181 pname[7] = '\0';
3182 return 0;
3183 } else if (partid < VOLMAXPARTS255) {
3184 strcpy(pname, "/vicep");
3185 partid -= 26;
3186 pname[6] = 'a' + (partid / 26);
3187 pname[7] = 'a' + (partid % 26);
3188 pname[8] = '\0';
3189 return 0;
3190 } else
3191 return -1;
3192}