2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <afs/afsutil.h>
22 #include <afs/cellconfig.h>
25 #include "vlserver_internal.h"
26 #include "afs/audit.h"
28 #ifdef HAVE_POSIX_REGEX /* use POSIX regexp library */
33 extern int restrictedQueryLevel
;
34 extern int extent_mod
;
35 extern struct afsconf_dir
*vldb_confdir
;
36 extern struct ubik_dbase
*VL_dbase
;
38 #define ABORT(c) do { \
43 #define VLDBALLOCLIMIT 10000
44 #define VLDBALLOCINCR 2048
46 static int put_attributeentry(struct vl_ctx
*ctx
,
47 struct vldbentry
**, struct vldbentry
**,
48 struct vldbentry
**, bulkentries
*,
49 struct nvlentry
*, afs_int32
*, afs_int32
*);
50 static int put_nattributeentry(struct vl_ctx
*ctx
,
51 struct nvldbentry
**, struct nvldbentry
**,
52 struct nvldbentry
**, nbulkentries
*,
53 struct nvlentry
*, afs_int32
, afs_int32
,
54 afs_int32
*, afs_int32
*);
55 static int RemoveEntry(struct vl_ctx
*ctx
, afs_int32 entryptr
,
56 struct nvlentry
*tentry
);
57 static void ReleaseEntry(struct nvlentry
*tentry
, afs_int32 releasetype
);
58 static int check_vldbentry(struct vldbentry
*aentry
);
59 static int check_nvldbentry(struct nvldbentry
*aentry
);
60 static int vldbentry_to_vlentry(struct vl_ctx
*ctx
,
61 struct vldbentry
*VldbEntry
,
62 struct nvlentry
*VlEntry
);
63 static int nvldbentry_to_vlentry(struct vl_ctx
*ctx
,
64 struct nvldbentry
*VldbEntry
,
65 struct nvlentry
*VlEntry
);
66 static int get_vldbupdateentry(struct vl_ctx
*ctx
, afs_int32 blockindex
,
67 struct VldbUpdateEntry
*updateentry
,
68 struct nvlentry
*VlEntry
);
69 static int repsite_exists(struct nvlentry
*VlEntry
, int server
, int partition
);
70 static void repsite_compress(struct nvlentry
*VlEntry
, int offset
);
71 static int vlentry_to_vldbentry(struct vl_ctx
*ctx
,
72 struct nvlentry
*VlEntry
,
73 struct vldbentry
*VldbEntry
);
74 static int vlentry_to_nvldbentry(struct vl_ctx
*ctx
,
75 struct nvlentry
*VlEntry
,
76 struct nvldbentry
*VldbEntry
);
77 static int vlentry_to_uvldbentry(struct vl_ctx
*ctx
,
78 struct nvlentry
*VlEntry
,
79 struct uvldbentry
*VldbEntry
);
80 static int InvalidVolname(char *volname
);
81 static int InvalidVoltype(afs_int32 voltype
);
82 static int InvalidOperation(afs_int32 voloper
);
83 static int InvalidReleasetype(afs_int32 releasetype
);
84 static int IpAddrToRelAddr(struct vl_ctx
*ctx
, afs_uint32 ipaddr
, int create
);
85 static int ChangeIPAddr(struct vl_ctx
*ctx
, afs_uint32 ipaddr1
,
89 countRequest(int opcode
)
92 dynamic_statistics
.requests
[opcode
- VL_LOWEST_OPCODE
]++;
97 countAbort(int opcode
)
100 dynamic_statistics
.aborts
[opcode
- VL_LOWEST_OPCODE
]++;
106 multiHomedExtentBase(struct vl_ctx
*ctx
, int srvidx
, struct extentaddr
**exp
,
115 if ((ctx
->hostaddress
[srvidx
] & 0xff000000) == 0xff000000) {
116 base
= (ctx
->hostaddress
[srvidx
] >> 16) & 0xff;
117 index
= ctx
->hostaddress
[srvidx
] & 0x0000ffff;
118 if (base
>= VL_MAX_ADDREXTBLKS
) {
119 VLog(0, ("Internal error: Multihome extent base is too large. "
120 "Base %d index %d\n", base
, index
));
123 if (index
>= VL_MHSRV_PERBLK
) {
124 VLog(0, ("Internal error: Multihome extent index is too large. "
125 "Base %d index %d\n", base
, index
));
128 if (!ctx
->ex_addr
[base
]) {
129 VLog(0, ("Internal error: Multihome extent does not exist. "
135 *exp
= &ctx
->ex_addr
[base
][index
];
142 multiHomedExtent(struct vl_ctx
*ctx
, int srvidx
, struct extentaddr
**exp
)
146 return multiHomedExtentBase(ctx
, srvidx
, exp
, &base
);
149 #define AFS_RXINFO_LEN 128
151 rxkadInfo(char *str
, struct rx_connection
*conn
, struct in_addr hostAddr
)
159 code
= rxkad_GetServerInfo(conn
, NULL
, &exp
, tname
, tinst
, tcell
,
162 snprintf(str
, AFS_RXINFO_LEN
,
163 "%s rxkad:%s%s%s%s%s", inet_ntoa(hostAddr
), tname
,
164 (tinst
[0] == '\0') ? "" : ".",
165 (tinst
[0] == '\0') ? "" : tinst
,
166 (tcell
[0] == '\0') ? "" : "@",
167 (tcell
[0] == '\0') ? "" : tcell
);
169 snprintf(str
, AFS_RXINFO_LEN
, "%s noauth", inet_ntoa(hostAddr
));
174 rxinfo(char *str
, struct rx_call
*rxcall
)
176 struct rx_connection
*conn
;
177 struct in_addr hostAddr
;
178 rx_securityIndex authClass
;
180 conn
= rx_ConnectionOf(rxcall
);
181 authClass
= rx_SecurityClassOf(conn
);
182 hostAddr
.s_addr
= rx_HostOf(rx_PeerOf(conn
));
186 return rxkadInfo(str
, conn
, hostAddr
);
191 snprintf(str
, AFS_RXINFO_LEN
, "%s noauth", inet_ntoa(hostAddr
));
196 /* This is called to initialize the database, set the appropriate locks and make sure that the vldb header is valid */
198 Init_VLdbase(struct vl_ctx
*ctx
,
199 int locktype
, /* indicate read or write transaction */
202 int code
= 0, pass
, wl
;
204 for (pass
= 1; pass
<= 3; pass
++) {
205 if (pass
== 2) { /* take write lock to rebuild the db */
206 code
= ubik_BeginTrans(VL_dbase
, UBIK_WRITETRANS
, &ctx
->trans
);
208 } else if (locktype
== LOCKREAD
) {
209 #ifdef UBIK_READ_WHILE_WRITE
210 code
= ubik_BeginTransReadAnyWrite(VL_dbase
, UBIK_READTRANS
, &ctx
->trans
);
212 code
= ubik_BeginTransReadAny(VL_dbase
, UBIK_READTRANS
, &ctx
->trans
);
216 code
= ubik_BeginTrans(VL_dbase
, UBIK_WRITETRANS
, &ctx
->trans
);
222 code
= ubik_SetLock(ctx
->trans
, 1, 1, locktype
);
225 ubik_AbortTrans(ctx
->trans
);
229 /* check that dbase is initialized and setup cheader */
230 /* 2nd pass we try to rebuild the header */
231 code
= CheckInit(ctx
->trans
, ((pass
== 2) ? 1 : 0));
232 if (!code
&& wl
&& extent_mod
)
233 code
= readExtents(ctx
->trans
); /* Fix the mh extent blocks */
236 ubik_AbortTrans(ctx
->trans
);
237 /* Only rebuld if the database is empty */
238 /* Exit if can't rebuild */
239 if ((pass
== 1) && (code
!= VL_EMPTY
))
243 } else { /* No code */
245 /* The database header was rebuilt; end the write transaction.
246 * This will call vlsynccache() to copy the write header buffers
247 * to the read header buffers, before calling vlsetache().
248 * Do a third pass to re-acquire the original lock, which
249 * may be a read lock. */
250 ubik_EndTrans(ctx
->trans
);
252 break; /* didn't rebuild and successful - exit */
257 code
= vlsetcache(ctx
, locktype
);
263 /* Create a new vldb entry; both new volume id and name must be unique
264 * (non-existant in vldb).
268 CreateEntry(struct rx_call
*rxcall
, struct vldbentry
*newentry
)
270 int this_op
= VLCREATEENTRY
;
272 afs_int32 code
, blockindex
;
273 struct nvlentry tentry
;
274 char rxstr
[AFS_RXINFO_LEN
];
276 countRequest(this_op
);
277 if (!afsconf_SuperUser(vldb_confdir
, rxcall
, NULL
)) {
281 /* Do some validity tests on new entry */
282 if ((code
= check_vldbentry(newentry
))
283 || (code
= Init_VLdbase(&ctx
, LOCKWRITE
, this_op
)))
287 ("OCreate Volume %d %s\n", newentry
->volumeId
[RWVOL
],
288 rxinfo(rxstr
, rxcall
)));
289 if (EntryIDExists(&ctx
, newentry
->volumeId
, MAXTYPES
, &code
)) {
290 /* at least one of the specified IDs already exists; we fail */
297 /* Is this following check (by volume name) necessary?? */
298 /* If entry already exists, we fail */
299 if (FindByName(&ctx
, newentry
->name
, &tentry
, &code
)) {
306 blockindex
= AllocBlock(&ctx
, &tentry
);
307 if (blockindex
== 0) {
308 code
= VL_CREATEFAIL
;
312 memset(&tentry
, 0, sizeof(struct nvlentry
));
313 /* Convert to its internal representation; both in host byte order */
314 if ((code
= vldbentry_to_vlentry(&ctx
, newentry
, &tentry
))) {
315 FreeBlock(&ctx
, blockindex
);
319 /* Actually insert the entry in vldb */
320 code
= ThreadVLentry(&ctx
, blockindex
, &tentry
);
322 FreeBlock(&ctx
, blockindex
);
325 return ubik_EndTrans(ctx
.trans
);
330 ubik_AbortTrans(ctx
.trans
);
335 SVL_CreateEntry(struct rx_call
*rxcall
, struct vldbentry
*newentry
)
339 code
= CreateEntry(rxcall
, newentry
);
340 osi_auditU(rxcall
, VLCreateEntryEvent
, code
, AUD_STR
,
341 (newentry
? newentry
->name
: NULL
), AUD_END
);
346 CreateEntryN(struct rx_call
*rxcall
, struct nvldbentry
*newentry
)
348 int this_op
= VLCREATEENTRYN
;
350 afs_int32 code
, blockindex
;
351 struct nvlentry tentry
;
352 char rxstr
[AFS_RXINFO_LEN
];
354 countRequest(this_op
);
355 if (!afsconf_SuperUser(vldb_confdir
, rxcall
, NULL
)) {
359 /* Do some validity tests on new entry */
360 if ((code
= check_nvldbentry(newentry
))
361 || (code
= Init_VLdbase(&ctx
, LOCKWRITE
, this_op
)))
365 ("Create Volume %d %s\n", newentry
->volumeId
[RWVOL
],
366 rxinfo(rxstr
, rxcall
)));
367 if (EntryIDExists(&ctx
, newentry
->volumeId
, MAXTYPES
, &code
)) {
368 /* at least one of the specified IDs already exists; we fail */
375 /* Is this following check (by volume name) necessary?? */
376 /* If entry already exists, we fail */
377 if (FindByName(&ctx
, newentry
->name
, &tentry
, &code
)) {
384 blockindex
= AllocBlock(&ctx
, &tentry
);
385 if (blockindex
== 0) {
386 code
= VL_CREATEFAIL
;
390 memset(&tentry
, 0, sizeof(struct nvlentry
));
391 /* Convert to its internal representation; both in host byte order */
392 if ((code
= nvldbentry_to_vlentry(&ctx
, newentry
, &tentry
))) {
393 FreeBlock(&ctx
, blockindex
);
397 /* Actually insert the entry in vldb */
398 code
= ThreadVLentry(&ctx
, blockindex
, &tentry
);
400 FreeBlock(&ctx
, blockindex
);
403 return ubik_EndTrans(ctx
.trans
);
408 ubik_AbortTrans(ctx
.trans
);
413 SVL_CreateEntryN(struct rx_call
*rxcall
, struct nvldbentry
*newentry
)
417 code
= CreateEntryN(rxcall
, newentry
);
418 osi_auditU(rxcall
, VLCreateEntryEvent
, code
, AUD_STR
,
419 (newentry
? newentry
->name
: NULL
), AUD_END
);
424 ChangeAddr(struct rx_call
*rxcall
, afs_uint32 ip1
, afs_uint32 ip2
)
426 int this_op
= VLCHANGEADDR
;
429 char rxstr
[AFS_RXINFO_LEN
];
431 countRequest(this_op
);
432 if (!afsconf_SuperUser(vldb_confdir
, rxcall
, NULL
)) {
436 if ((code
= Init_VLdbase(&ctx
, LOCKWRITE
, this_op
)))
439 VLog(1, ("Change Addr %u -> %u %s\n", ip1
, ip2
, rxinfo(rxstr
, rxcall
)));
440 if ((code
= ChangeIPAddr(&ctx
, ip1
, ip2
)))
443 code
= ubik_EndTrans(ctx
.trans
);
449 ubik_AbortTrans(ctx
.trans
);
454 SVL_ChangeAddr(struct rx_call
*rxcall
, afs_uint32 ip1
, afs_uint32 ip2
)
458 code
= ChangeAddr(rxcall
, ip1
, ip2
);
459 osi_auditU(rxcall
, VLChangeAddrEvent
, code
, AUD_LONG
, ip1
, AUD_LONG
,
464 /* Delete a vldb entry given the volume id. */
466 DeleteEntry(struct rx_call
*rxcall
, afs_uint32 volid
, afs_int32 voltype
)
468 int this_op
= VLDELETEENTRY
;
470 afs_int32 blockindex
, code
;
471 struct nvlentry tentry
;
472 char rxstr
[AFS_RXINFO_LEN
];
474 countRequest(this_op
);
475 if (!afsconf_SuperUser(vldb_confdir
, rxcall
, NULL
))
478 if ((voltype
!= -1) && (InvalidVoltype(voltype
)))
479 return VL_BADVOLTYPE
;
481 if ((code
= Init_VLdbase(&ctx
, LOCKWRITE
, this_op
)))
484 VLog(1, ("Delete Volume %u %s\n", volid
, rxinfo(rxstr
, rxcall
)));
485 blockindex
= FindByID(&ctx
, volid
, voltype
, &tentry
, &code
);
486 if (blockindex
== 0) { /* volid not found */
492 if (tentry
.flags
& VLDELETED
) { /* Already deleted; return */
493 ABORT(VL_ENTDELETED
);
495 if ((code
= RemoveEntry(&ctx
, blockindex
, &tentry
))) {
498 return ubik_EndTrans(ctx
.trans
);
502 ubik_AbortTrans(ctx
.trans
);
507 SVL_DeleteEntry(struct rx_call
*rxcall
, afs_uint32 volid
, afs_int32 voltype
)
511 code
= DeleteEntry(rxcall
, volid
, voltype
);
512 osi_auditU(rxcall
, VLDeleteEntryEvent
, code
, AUD_LONG
, volid
,
518 /* Get a vldb entry given its volume id; make sure it's not a deleted entry. */
520 GetEntryByID(struct rx_call
*rxcall
,
523 char *aentry
, /* entry data copied here */
528 afs_int32 blockindex
, code
;
529 struct nvlentry tentry
;
530 char rxstr
[AFS_RXINFO_LEN
];
532 countRequest(this_op
);
534 if ((voltype
!= -1) && (InvalidVoltype(voltype
)))
535 return VL_BADVOLTYPE
;
536 if ((code
= Init_VLdbase(&ctx
, LOCKREAD
, this_op
)))
539 VLog(5, ("GetVolumeByID %u (%d) %s\n", volid
, new,
540 rxinfo(rxstr
, rxcall
)));
541 blockindex
= FindByID(&ctx
, volid
, voltype
, &tentry
, &code
);
542 if (blockindex
== 0) { /* entry not found */
547 if (tentry
.flags
& VLDELETED
) { /* Entry is deleted! */
548 code
= VL_ENTDELETED
;
551 /* Convert from the internal to external form */
553 code
= vlentry_to_nvldbentry(&ctx
, &tentry
, (struct nvldbentry
*)aentry
);
555 code
= vlentry_to_uvldbentry(&ctx
, &tentry
, (struct uvldbentry
*)aentry
);
557 code
= vlentry_to_vldbentry(&ctx
, &tentry
, (struct vldbentry
*)aentry
);
562 return (ubik_EndTrans(ctx
.trans
));
566 ubik_AbortTrans(ctx
.trans
);
571 SVL_GetEntryByID(struct rx_call
*rxcall
,
574 vldbentry
*aentry
) /* entry data copied here */
576 return (GetEntryByID(rxcall
, volid
, voltype
, (char *)aentry
, 0,
581 SVL_GetEntryByIDN(struct rx_call
*rxcall
,
584 nvldbentry
*aentry
) /* entry data copied here */
586 return (GetEntryByID(rxcall
, volid
, voltype
, (char *)aentry
, 1,
591 SVL_GetEntryByIDU(struct rx_call
*rxcall
,
594 uvldbentry
*aentry
) /* entry data copied here */
596 return (GetEntryByID(rxcall
, volid
, voltype
, (char *)aentry
, 2,
600 /* returns true if the id is a decimal integer, in which case we interpret
601 * it as an id. make the cache manager much simpler */
603 NameIsId(char *aname
)
606 while ((tc
= *aname
++)) {
607 if (tc
> '9' || tc
< '0')
613 /* Get a vldb entry given the volume's name; of course, very similar to
614 * VLGetEntryByID() above. */
616 GetEntryByName(struct rx_call
*rxcall
,
618 char *aentry
, /* entry data copied here */
623 afs_int32 blockindex
, code
;
624 struct nvlentry tentry
;
625 char rxstr
[AFS_RXINFO_LEN
];
627 if (NameIsId(volname
)) {
628 return GetEntryByID(rxcall
, strtoul(volname
, NULL
, 10), -1, aentry
, new, this_op
);
631 countRequest(this_op
);
633 if (InvalidVolname(volname
))
635 if ((code
= Init_VLdbase(&ctx
, LOCKREAD
, this_op
)))
637 VLog(5, ("GetVolumeByName %s (%d) %s\n", volname
, new, rxinfo(rxstr
, rxcall
)));
638 blockindex
= FindByName(&ctx
, volname
, &tentry
, &code
);
639 if (blockindex
== 0) { /* entry not found */
644 if (tentry
.flags
& VLDELETED
) { /* Entry is deleted */
645 code
= VL_ENTDELETED
;
648 /* Convert to external entry representation */
650 code
= vlentry_to_nvldbentry(&ctx
, &tentry
, (struct nvldbentry
*)aentry
);
652 code
= vlentry_to_uvldbentry(&ctx
, &tentry
, (struct uvldbentry
*)aentry
);
654 code
= vlentry_to_vldbentry(&ctx
, &tentry
, (struct vldbentry
*)aentry
);
659 return (ubik_EndTrans(ctx
.trans
));
663 ubik_AbortTrans(ctx
.trans
);
669 SVL_GetEntryByNameO(struct rx_call
*rxcall
,
671 struct vldbentry
*aentry
) /* entry data copied here */
673 return (GetEntryByName(rxcall
, volname
, (char *)aentry
, 0,
678 SVL_GetEntryByNameN(struct rx_call
*rxcall
,
680 struct nvldbentry
*aentry
) /* entry data copied here */
682 return (GetEntryByName(rxcall
, volname
, (char *)aentry
, 1,
687 SVL_GetEntryByNameU(struct rx_call
*rxcall
,
689 struct uvldbentry
*aentry
) /* entry data copied here */
691 return (GetEntryByName(rxcall
, volname
, (char *)aentry
, 2,
695 /* Get the current value of the maximum volume id and bump the volume id counter by Maxvolidbump. */
697 getNewVolumeId(struct rx_call
*rxcall
, afs_uint32 Maxvolidbump
,
698 afs_uint32
*newvolumeid
)
700 int this_op
= VLGETNEWVOLUMEID
;
702 afs_uint32 maxvolumeid
;
704 char rxstr
[AFS_RXINFO_LEN
];
706 countRequest(this_op
);
707 if (!afsconf_SuperUser(vldb_confdir
, rxcall
, NULL
))
710 if (Maxvolidbump
> MAXBUMPCOUNT
)
711 return VL_BADVOLIDBUMP
;
713 if ((code
= Init_VLdbase(&ctx
, LOCKWRITE
, this_op
)))
716 *newvolumeid
= maxvolumeid
= NextUnusedID(&ctx
,
717 ntohl(ctx
.cheader
->vital_header
.MaxVolumeId
), Maxvolidbump
, &code
);
722 maxvolumeid
+= Maxvolidbump
;
723 VLog(1, ("GetNewVolid newmax=%u %s\n", maxvolumeid
, rxinfo(rxstr
, rxcall
)));
724 ctx
.cheader
->vital_header
.MaxVolumeId
= htonl(maxvolumeid
);
725 if (write_vital_vlheader(&ctx
)) {
728 return ubik_EndTrans(ctx
.trans
);
732 ubik_AbortTrans(ctx
.trans
);
737 SVL_GetNewVolumeId(struct rx_call
*rxcall
, afs_uint32 Maxvolidbump
,
738 afs_uint32
*newvolumeid
)
742 code
= getNewVolumeId(rxcall
, Maxvolidbump
, newvolumeid
);
743 osi_auditU(rxcall
, VLGetNewVolumeIdEvent
, code
, AUD_END
);
748 /* Simple replace the contents of the vldb entry, volid, with
749 * newentry. No individual checking/updating per field (alike
750 * VLUpdateEntry) is done. */
753 ReplaceEntry(struct rx_call
*rxcall
, afs_uint32 volid
, afs_int32 voltype
,
754 struct vldbentry
*newentry
, afs_int32 releasetype
)
756 int this_op
= VLREPLACEENTRY
;
758 afs_int32 blockindex
, code
, typeindex
;
760 int hashVol
[MAXTYPES
];
761 struct nvlentry tentry
;
762 afs_uint32 checkids
[MAXTYPES
];
763 char rxstr
[AFS_RXINFO_LEN
];
765 countRequest(this_op
);
766 for (typeindex
= 0; typeindex
< MAXTYPES
; typeindex
++)
767 hashVol
[typeindex
] = 0;
769 if (!afsconf_SuperUser(vldb_confdir
, rxcall
, NULL
))
772 if ((code
= check_vldbentry(newentry
)))
775 if (voltype
!= -1 && InvalidVoltype(voltype
))
776 return VL_BADVOLTYPE
;
778 if (releasetype
&& InvalidReleasetype(releasetype
))
779 return VL_BADRELLOCKTYPE
;
780 if ((code
= Init_VLdbase(&ctx
, LOCKWRITE
, this_op
)))
783 VLog(1, ("OReplace Volume %u %s\n", volid
, rxinfo(rxstr
, rxcall
)));
784 /* find vlentry we're changing */
785 blockindex
= FindByID(&ctx
, volid
, voltype
, &tentry
, &code
);
786 if (blockindex
== 0) { /* entry not found */
792 /* check that we're not trying to change the RW vol ID */
793 if (newentry
->volumeId
[RWVOL
] != tentry
.volumeId
[RWVOL
]) {
797 /* make sure none of the IDs we are changing to are already in use */
798 memset(&checkids
, 0, sizeof(checkids
));
799 for (typeindex
= ROVOL
; typeindex
< MAXTYPES
; typeindex
++) {
800 if (tentry
.volumeId
[typeindex
] != newentry
->volumeId
[typeindex
]) {
801 checkids
[typeindex
] = newentry
->volumeId
[typeindex
];
804 if (EntryIDExists(&ctx
, checkids
, MAXTYPES
, &code
)) {
810 /* make sure the name we're changing to doesn't already exist */
811 if (strcmp(newentry
->name
, tentry
.name
)) {
812 struct nvlentry tmp_entry
;
813 if (FindByName(&ctx
, newentry
->name
, &tmp_entry
, &code
)) {
820 /* unhash volid entries if they're disappearing or changing.
821 * Remember if we need to hash in the new value (we don't have to
822 * rehash if volid stays same */
823 for (typeindex
= ROVOL
; typeindex
<= BACKVOL
; typeindex
++) {
824 if (tentry
.volumeId
[typeindex
] != newentry
->volumeId
[typeindex
]) {
825 if (tentry
.volumeId
[typeindex
])
827 UnhashVolid(&ctx
, typeindex
, blockindex
, &tentry
))) {
830 /* we must rehash new id if the id is different and the ID is nonzero */
831 hashVol
[typeindex
] = 1; /* must rehash this guy if he exists */
835 /* Rehash volname if it changes */
836 if (strcmp(newentry
->name
, tentry
.name
)) { /* Name changes; redo hashing */
837 if ((code
= UnhashVolname(&ctx
, blockindex
, &tentry
))) {
843 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
844 * doesn't touch hash chains */
845 if ((code
= vldbentry_to_vlentry(&ctx
, newentry
, &tentry
))) {
849 for (typeindex
= ROVOL
; typeindex
<= BACKVOL
; typeindex
++) {
850 if (hashVol
[typeindex
] && tentry
.volumeId
[typeindex
]) {
851 if ((code
= HashVolid(&ctx
, typeindex
, blockindex
, &tentry
))) {
858 HashVolname(&ctx
, blockindex
, &tentry
);
861 ReleaseEntry(&tentry
, releasetype
); /* Unlock entry if necessary */
862 if (vlentrywrite(ctx
.trans
, blockindex
, &tentry
, sizeof(tentry
))) {
866 return ubik_EndTrans(ctx
.trans
);
870 ubik_AbortTrans(ctx
.trans
);
875 SVL_ReplaceEntry(struct rx_call
*rxcall
, afs_uint32 volid
, afs_int32 voltype
,
876 struct vldbentry
*newentry
, afs_int32 releasetype
)
880 code
= ReplaceEntry(rxcall
, volid
, voltype
, newentry
, releasetype
);
881 osi_auditU(rxcall
, VLReplaceVLEntryEvent
, code
, AUD_LONG
, volid
, AUD_END
);
886 ReplaceEntryN(struct rx_call
*rxcall
, afs_uint32 volid
, afs_int32 voltype
,
887 struct nvldbentry
*newentry
, afs_int32 releasetype
)
889 int this_op
= VLREPLACEENTRYN
;
891 afs_int32 blockindex
, code
, typeindex
;
893 int hashVol
[MAXTYPES
];
894 struct nvlentry tentry
;
895 char rxstr
[AFS_RXINFO_LEN
];
897 countRequest(this_op
);
898 for (typeindex
= 0; typeindex
< MAXTYPES
; typeindex
++)
899 hashVol
[typeindex
] = 0;
901 if (!afsconf_SuperUser(vldb_confdir
, rxcall
, NULL
))
904 if ((code
= check_nvldbentry(newentry
)))
907 if (voltype
!= -1 && InvalidVoltype(voltype
))
908 return VL_BADVOLTYPE
;
910 if (releasetype
&& InvalidReleasetype(releasetype
))
911 return VL_BADRELLOCKTYPE
;
912 if ((code
= Init_VLdbase(&ctx
, LOCKWRITE
, this_op
)))
915 VLog(1, ("Replace Volume %u %s\n", volid
, rxinfo(rxstr
, rxcall
)));
916 /* find vlentry we're changing */
917 blockindex
= FindByID(&ctx
, volid
, voltype
, &tentry
, &code
);
918 if (blockindex
== 0) { /* entry not found */
924 /* check that we're not trying to change the RW vol ID */
925 if (newentry
->volumeId
[RWVOL
] != tentry
.volumeId
[RWVOL
]) {
929 /* unhash volid entries if they're disappearing or changing.
930 * Remember if we need to hash in the new value (we don't have to
931 * rehash if volid stays same */
932 for (typeindex
= ROVOL
; typeindex
<= BACKVOL
; typeindex
++) {
933 if (tentry
.volumeId
[typeindex
] != newentry
->volumeId
[typeindex
]) {
934 if (tentry
.volumeId
[typeindex
])
936 UnhashVolid(&ctx
, typeindex
, blockindex
, &tentry
))) {
939 /* we must rehash new id if the id is different and the ID is nonzero */
940 hashVol
[typeindex
] = 1; /* must rehash this guy if he exists */
944 /* Rehash volname if it changes */
945 if (strcmp(newentry
->name
, tentry
.name
)) { /* Name changes; redo hashing */
946 if ((code
= UnhashVolname(&ctx
, blockindex
, &tentry
))) {
952 /* after this, tentry is new entry, not old one. vldbentry_to_vlentry
953 * doesn't touch hash chains */
954 if ((code
= nvldbentry_to_vlentry(&ctx
, newentry
, &tentry
))) {
958 for (typeindex
= ROVOL
; typeindex
<= BACKVOL
; typeindex
++) {
959 if (hashVol
[typeindex
] && tentry
.volumeId
[typeindex
]) {
960 if ((code
= HashVolid(&ctx
, typeindex
, blockindex
, &tentry
))) {
967 HashVolname(&ctx
, blockindex
, &tentry
);
970 ReleaseEntry(&tentry
, releasetype
); /* Unlock entry if necessary */
971 if (vlentrywrite(ctx
.trans
, blockindex
, &tentry
, sizeof(tentry
))) {
975 return ubik_EndTrans(ctx
.trans
);
979 ubik_AbortTrans(ctx
.trans
);
984 SVL_ReplaceEntryN(struct rx_call
*rxcall
, afs_uint32 volid
, afs_int32 voltype
,
985 struct nvldbentry
*newentry
, afs_int32 releasetype
)
989 code
= ReplaceEntryN(rxcall
, volid
, voltype
, newentry
, releasetype
);
990 osi_auditU(rxcall
, VLReplaceVLEntryEvent
, code
, AUD_LONG
, volid
, AUD_END
);
995 /* Update a vldb entry (accessed thru its volume id). Almost all of the
996 * entry's fields can be modified in a single call by setting the
997 * appropriate bits in the Mask field in VldbUpdateentry. */
998 /* this routine may never have been tested; use replace entry instead
999 * unless you're brave */
1001 UpdateEntry(struct rx_call
*rxcall
,
1004 struct VldbUpdateEntry
*updateentry
, /* Update entry copied here */
1005 afs_int32 releasetype
)
1007 int this_op
= VLUPDATEENTRY
;
1009 afs_int32 blockindex
, code
;
1010 struct nvlentry tentry
;
1011 char rxstr
[AFS_RXINFO_LEN
];
1013 countRequest(this_op
);
1014 if (!afsconf_SuperUser(vldb_confdir
, rxcall
, NULL
))
1016 if ((voltype
!= -1) && (InvalidVoltype(voltype
)))
1017 return VL_BADVOLTYPE
;
1018 if (releasetype
&& InvalidReleasetype(releasetype
))
1019 return VL_BADRELLOCKTYPE
;
1020 if ((code
= Init_VLdbase(&ctx
, LOCKWRITE
, this_op
)))
1023 VLog(1, ("Update Volume %u %s\n", volid
, rxinfo(rxstr
, rxcall
)));
1024 blockindex
= FindByID(&ctx
, volid
, voltype
, &tentry
, &code
);
1025 if (blockindex
== 0) { /* entry not found */
1031 /* Do the actual updating of the entry, tentry. */
1033 get_vldbupdateentry(&ctx
, blockindex
, updateentry
, &tentry
))) {
1037 ReleaseEntry(&tentry
, releasetype
); /* Unlock entry if necessary */
1038 if (vlentrywrite(ctx
.trans
, blockindex
, &tentry
, sizeof(tentry
))) {
1041 return ubik_EndTrans(ctx
.trans
);
1044 countAbort(this_op
);
1045 ubik_AbortTrans(ctx
.trans
);
1050 SVL_UpdateEntry(struct rx_call
*rxcall
,
1053 struct VldbUpdateEntry
*updateentry
,
1054 afs_int32 releasetype
)
1058 code
= UpdateEntry(rxcall
, volid
, voltype
, updateentry
, releasetype
);
1059 osi_auditU(rxcall
, VLUpdateEntryEvent
, code
, AUD_LONG
, volid
, AUD_END
);
1064 UpdateEntryByName(struct rx_call
*rxcall
,
1066 struct VldbUpdateEntry
*updateentry
, /* Update entry copied here */
1067 afs_int32 releasetype
)
1069 int this_op
= VLUPDATEENTRYBYNAME
;
1071 afs_int32 blockindex
, code
;
1072 struct nvlentry tentry
;
1074 countRequest(this_op
);
1075 if (!afsconf_SuperUser(vldb_confdir
, rxcall
, NULL
))
1077 if (releasetype
&& InvalidReleasetype(releasetype
))
1078 return VL_BADRELLOCKTYPE
;
1079 if ((code
= Init_VLdbase(&ctx
, LOCKWRITE
, this_op
)))
1082 blockindex
= FindByName(&ctx
, volname
, &tentry
, &code
);
1083 if (blockindex
== 0) { /* entry not found */
1089 /* Do the actual updating of the entry, tentry. */
1091 get_vldbupdateentry(&ctx
, blockindex
, updateentry
, &tentry
))) {
1095 ReleaseEntry(&tentry
, releasetype
); /* Unlock entry if necessary */
1096 if (vlentrywrite(ctx
.trans
, blockindex
, &tentry
, sizeof(tentry
))) {
1099 return ubik_EndTrans(ctx
.trans
);
1102 countAbort(this_op
);
1103 ubik_AbortTrans(ctx
.trans
);
1108 SVL_UpdateEntryByName(struct rx_call
*rxcall
,
1110 struct VldbUpdateEntry
*updateentry
, /* Update entry copied here */
1111 afs_int32 releasetype
)
1115 code
= UpdateEntryByName(rxcall
, volname
, updateentry
, releasetype
);
1116 osi_auditU(rxcall
, VLUpdateEntryEvent
, code
, AUD_LONG
, -1, AUD_END
);
1120 /* Set a lock to the vldb entry for volid (of type voltype if not -1). */
1122 SetLock(struct rx_call
*rxcall
, afs_uint32 volid
, afs_int32 voltype
,
1125 int this_op
= VLSETLOCK
;
1126 afs_int32 timestamp
, blockindex
, code
;
1128 struct nvlentry tentry
;
1129 char rxstr
[AFS_RXINFO_LEN
];
1131 countRequest(this_op
);
1132 if (!afsconf_SuperUser(vldb_confdir
, rxcall
, NULL
))
1134 if ((voltype
!= -1) && (InvalidVoltype(voltype
)))
1135 return VL_BADVOLTYPE
;
1136 if (InvalidOperation(voloper
))
1137 return VL_BADVOLOPER
;
1138 if ((code
= Init_VLdbase(&ctx
, LOCKWRITE
, this_op
)))
1141 VLog(1, ("SetLock Volume %u %s\n", volid
, rxinfo(rxstr
, rxcall
)));
1142 blockindex
= FindByID(&ctx
, volid
, voltype
, &tentry
, &code
);
1143 if (blockindex
== NULLO
) {
1148 if (tentry
.flags
& VLDELETED
) {
1149 ABORT(VL_ENTDELETED
);
1151 timestamp
= FT_ApproxTime();
1153 /* Check if entry is already locked; note that we unlock any entry
1154 * locked more than MAXLOCKTIME seconds */
1155 if ((tentry
.LockTimestamp
)
1156 && ((timestamp
- tentry
.LockTimestamp
) < MAXLOCKTIME
)) {
1157 ABORT(VL_ENTRYLOCKED
);
1160 /* Consider it an unlocked entry: set current timestamp, caller
1161 * and active vol operation */
1162 tentry
.LockTimestamp
= timestamp
;
1163 tentry
.LockAfsId
= 0; /* Not implemented yet */
1164 if (tentry
.flags
& VLOP_RELEASE
) {
1165 ABORT(VL_RERELEASE
);
1167 tentry
.flags
&= ~VLOP_ALLOPERS
; /* Clear any possible older operation bit */
1168 tentry
.flags
|= voloper
;
1170 if (vlentrywrite(ctx
.trans
, blockindex
, &tentry
, sizeof(tentry
))) {
1173 return ubik_EndTrans(ctx
.trans
);
1176 countAbort(this_op
);
1177 ubik_AbortTrans(ctx
.trans
);
1182 SVL_SetLock(struct rx_call
*rxcall
, afs_uint32 volid
, afs_int32 voltype
,
1187 code
= SetLock(rxcall
, volid
, voltype
, voloper
);
1188 osi_auditU(rxcall
, VLSetLockEvent
, code
, AUD_LONG
, volid
, AUD_END
);
1192 /* Release an already locked vldb entry. Releasetype determines what
1193 * fields (afsid and/or volume operation) will be cleared along with
1194 * the lock time stamp. */
1197 ReleaseLock(struct rx_call
*rxcall
, afs_uint32 volid
, afs_int32 voltype
,
1198 afs_int32 releasetype
)
1200 int this_op
= VLRELEASELOCK
;
1201 afs_int32 blockindex
, code
;
1203 struct nvlentry tentry
;
1204 char rxstr
[AFS_RXINFO_LEN
];
1206 countRequest(this_op
);
1207 if (!afsconf_SuperUser(vldb_confdir
, rxcall
, NULL
))
1209 if ((voltype
!= -1) && (InvalidVoltype(voltype
)))
1210 return VL_BADVOLTYPE
;
1211 if (releasetype
&& InvalidReleasetype(releasetype
))
1212 return VL_BADRELLOCKTYPE
;
1213 if ((code
= Init_VLdbase(&ctx
, LOCKWRITE
, this_op
)))
1216 VLog(1, ("ReleaseLock Volume %u %s\n", volid
, rxinfo(rxstr
, rxcall
)));
1217 blockindex
= FindByID(&ctx
, volid
, voltype
, &tentry
, &code
);
1218 if (blockindex
== NULLO
) {
1223 if (tentry
.flags
& VLDELETED
) {
1224 ABORT(VL_ENTDELETED
);
1227 ReleaseEntry(&tentry
, releasetype
); /* Unlock the appropriate fields */
1228 if (vlentrywrite(ctx
.trans
, blockindex
, &tentry
, sizeof(tentry
))) {
1231 return ubik_EndTrans(ctx
.trans
);
1234 countAbort(this_op
);
1235 ubik_AbortTrans(ctx
.trans
);
1240 SVL_ReleaseLock(struct rx_call
*rxcall
, afs_uint32 volid
, afs_int32 voltype
,
1241 afs_int32 releasetype
)
1245 code
= ReleaseLock(rxcall
, volid
, voltype
, releasetype
);
1246 osi_auditU(rxcall
, VLReleaseLockEvent
, code
, AUD_LONG
, volid
, AUD_END
);
1250 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1251 * the remaining parameters (i.e. next_index) are used so that sequential
1252 * calls to this routine will get the next (all) vldb entries.
1255 ListEntry(struct rx_call
*rxcall
, afs_int32 previous_index
,
1256 afs_int32
*count
, afs_int32
*next_index
,
1257 struct vldbentry
*aentry
)
1259 int this_op
= VLLISTENTRY
;
1262 struct nvlentry tentry
;
1263 char rxstr
[AFS_RXINFO_LEN
];
1265 countRequest(this_op
);
1267 if (!afsconf_CheckRestrictedQuery(vldb_confdir
, rxcall
,
1268 restrictedQueryLevel
))
1271 if ((code
= Init_VLdbase(&ctx
, LOCKREAD
, this_op
)))
1273 VLog(25, ("OListEntry index=%d %s\n", previous_index
,
1274 rxinfo(rxstr
, rxcall
)));
1275 *next_index
= NextEntry(&ctx
, previous_index
, &tentry
, count
);
1277 code
= vlentry_to_vldbentry(&ctx
, &tentry
, aentry
);
1279 countAbort(this_op
);
1280 ubik_AbortTrans(ctx
.trans
);
1284 return ubik_EndTrans(ctx
.trans
);
1288 SVL_ListEntry(struct rx_call
*rxcall
, afs_int32 previous_index
,
1289 afs_int32
*count
, afs_int32
*next_index
,
1290 struct vldbentry
*aentry
)
1294 code
= ListEntry(rxcall
, previous_index
, count
, next_index
, aentry
);
1295 osi_auditU(rxcall
, VLListEntryEvent
, code
, AUD_LONG
, previous_index
, AUD_END
);
1299 /* ListEntry returns a single vldb entry, aentry, with offset previous_index;
1300 * the remaining parameters (i.e. next_index) are used so that sequential
1301 * calls to this routine will get the next (all) vldb entries.
1304 ListEntryN(struct rx_call
*rxcall
, afs_int32 previous_index
,
1305 afs_int32
*count
, afs_int32
*next_index
,
1306 struct nvldbentry
*aentry
)
1308 int this_op
= VLLISTENTRYN
;
1311 struct nvlentry tentry
;
1312 char rxstr
[AFS_RXINFO_LEN
];
1314 countRequest(this_op
);
1316 if (!afsconf_CheckRestrictedQuery(vldb_confdir
, rxcall
,
1317 restrictedQueryLevel
))
1320 if ((code
= Init_VLdbase(&ctx
, LOCKREAD
, this_op
)))
1322 VLog(25, ("ListEntry index=%d %s\n", previous_index
, rxinfo(rxstr
, rxcall
)));
1323 *next_index
= NextEntry(&ctx
, previous_index
, &tentry
, count
);
1325 code
= vlentry_to_nvldbentry(&ctx
, &tentry
, aentry
);
1327 countAbort(this_op
);
1328 ubik_AbortTrans(ctx
.trans
);
1333 return ubik_EndTrans(ctx
.trans
);
1337 SVL_ListEntryN(struct rx_call
*rxcall
, afs_int32 previous_index
,
1338 afs_int32
*count
, afs_int32
*next_index
,
1339 struct nvldbentry
*aentry
)
1343 code
= ListEntryN(rxcall
, previous_index
, count
, next_index
, aentry
);
1344 osi_auditU(rxcall
, VLListEntryEventN
, code
, AUD_LONG
, previous_index
, AUD_END
);
1348 /* Retrieves in vldbentries all vldb entries that match the specified
1349 * attributes (by server number, partition, volume type, and flag); if volume
1350 * id is specified then the associated list for that entry is returned.
1351 * CAUTION: This could be a very expensive call since in most cases
1352 * sequential search of all vldb entries is performed.
1355 ListAttributes(struct rx_call
*rxcall
,
1356 struct VldbListByAttributes
*attributes
,
1357 afs_int32
*nentries
,
1358 bulkentries
*vldbentries
)
1360 int this_op
= VLLISTATTRIBUTES
;
1361 int code
, allocCount
= 0;
1363 struct nvlentry tentry
;
1364 struct vldbentry
*Vldbentry
= 0, *VldbentryFirst
= 0, *VldbentryLast
= 0;
1366 char rxstr
[AFS_RXINFO_LEN
];
1368 countRequest(this_op
);
1370 if (!afsconf_CheckRestrictedQuery(vldb_confdir
, rxcall
,
1371 restrictedQueryLevel
))
1374 vldbentries
->bulkentries_val
= 0;
1375 vldbentries
->bulkentries_len
= *nentries
= 0;
1376 if ((code
= Init_VLdbase(&ctx
, LOCKREAD
, this_op
)))
1378 allocCount
= VLDBALLOCCOUNT
;
1379 Vldbentry
= VldbentryFirst
= vldbentries
->bulkentries_val
=
1380 malloc(allocCount
* sizeof(vldbentry
));
1381 if (Vldbentry
== NULL
) {
1385 VldbentryLast
= VldbentryFirst
+ allocCount
;
1386 /* Handle the attribute by volume id totally separate of the rest
1387 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1388 if (attributes
->Mask
& VLLIST_VOLUMEID
) {
1389 afs_int32 blockindex
;
1392 FindByID(&ctx
, attributes
->volumeid
, -1, &tentry
, &code
);
1393 if (blockindex
== 0) {
1399 code
= put_attributeentry(&ctx
, &Vldbentry
, &VldbentryFirst
,
1400 &VldbentryLast
, vldbentries
, &tentry
,
1401 nentries
, &allocCount
);
1405 afs_int32 nextblockindex
= 0, count
= 0, k
= 0, match
= 0;
1406 while ((nextblockindex
=
1407 NextEntry(&ctx
, nextblockindex
, &tentry
, &count
))) {
1408 if (++pollcount
> 50) {
1409 #ifndef AFS_PTHREAD_ENV
1415 if (attributes
->Mask
& VLLIST_SERVER
) {
1418 IpAddrToRelAddr(&ctx
, attributes
->server
, 0)) == -1)
1420 for (k
= 0; k
< OMAXNSERVERS
; k
++) {
1421 if (tentry
.serverNumber
[k
] == BADSERVERID
)
1423 if (tentry
.serverNumber
[k
] == serverindex
) {
1431 if (attributes
->Mask
& VLLIST_PARTITION
) {
1433 if (tentry
.serverPartition
[k
] != attributes
->partition
)
1436 for (k
= 0; k
< OMAXNSERVERS
; k
++) {
1437 if (tentry
.serverNumber
[k
] == BADSERVERID
)
1439 if (tentry
.serverPartition
[k
] ==
1440 attributes
->partition
) {
1450 if (attributes
->Mask
& VLLIST_FLAG
) {
1451 if (!(tentry
.flags
& attributes
->flag
))
1454 code
= put_attributeentry(&ctx
, &Vldbentry
, &VldbentryFirst
,
1455 &VldbentryLast
, vldbentries
, &tentry
,
1456 nentries
, &allocCount
);
1461 if (vldbentries
->bulkentries_len
1462 && (allocCount
> vldbentries
->bulkentries_len
)) {
1464 vldbentries
->bulkentries_val
=
1465 realloc(vldbentries
->bulkentries_val
,
1466 vldbentries
->bulkentries_len
* sizeof(vldbentry
));
1467 if (vldbentries
->bulkentries_val
== NULL
) {
1473 ("ListAttrs nentries=%d %s\n", vldbentries
->bulkentries_len
,
1474 rxinfo(rxstr
, rxcall
)));
1475 return ubik_EndTrans(ctx
.trans
);
1478 if (vldbentries
->bulkentries_val
)
1479 free(vldbentries
->bulkentries_val
);
1480 vldbentries
->bulkentries_val
= 0;
1481 vldbentries
->bulkentries_len
= 0;
1483 countAbort(this_op
);
1484 ubik_AbortTrans(ctx
.trans
);
1489 SVL_ListAttributes(struct rx_call
*rxcall
,
1490 struct VldbListByAttributes
*attributes
,
1491 afs_int32
*nentries
,
1492 bulkentries
*vldbentries
)
1496 code
= ListAttributes(rxcall
, attributes
, nentries
, vldbentries
);
1497 osi_auditU(rxcall
, VLListAttributesEvent
, code
, AUD_END
);
1502 ListAttributesN(struct rx_call
*rxcall
,
1503 struct VldbListByAttributes
*attributes
,
1504 afs_int32
*nentries
,
1505 nbulkentries
*vldbentries
)
1507 int this_op
= VLLISTATTRIBUTESN
;
1508 int code
, allocCount
= 0;
1510 struct nvlentry tentry
;
1511 struct nvldbentry
*Vldbentry
= 0, *VldbentryFirst
= 0, *VldbentryLast
= 0;
1513 char rxstr
[AFS_RXINFO_LEN
];
1515 countRequest(this_op
);
1517 if (!afsconf_CheckRestrictedQuery(vldb_confdir
, rxcall
,
1518 restrictedQueryLevel
))
1521 vldbentries
->nbulkentries_val
= 0;
1522 vldbentries
->nbulkentries_len
= *nentries
= 0;
1523 if ((code
= Init_VLdbase(&ctx
, LOCKREAD
, this_op
)))
1525 allocCount
= VLDBALLOCCOUNT
;
1526 Vldbentry
= VldbentryFirst
= vldbentries
->nbulkentries_val
=
1527 malloc(allocCount
* sizeof(nvldbentry
));
1528 if (Vldbentry
== NULL
) {
1532 VldbentryLast
= VldbentryFirst
+ allocCount
;
1533 /* Handle the attribute by volume id totally separate of the rest
1534 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!) */
1535 if (attributes
->Mask
& VLLIST_VOLUMEID
) {
1536 afs_int32 blockindex
;
1539 FindByID(&ctx
, attributes
->volumeid
, -1, &tentry
, &code
);
1540 if (blockindex
== 0) {
1546 code
= put_nattributeentry(&ctx
, &Vldbentry
, &VldbentryFirst
,
1547 &VldbentryLast
, vldbentries
, &tentry
,
1548 0, 0, nentries
, &allocCount
);
1552 afs_int32 nextblockindex
= 0, count
= 0, k
= 0, match
= 0;
1553 while ((nextblockindex
=
1554 NextEntry(&ctx
, nextblockindex
, &tentry
, &count
))) {
1555 if (++pollcount
> 50) {
1556 #ifndef AFS_PTHREAD_ENV
1563 if (attributes
->Mask
& VLLIST_SERVER
) {
1566 IpAddrToRelAddr(&ctx
, attributes
->server
, 0)) == -1)
1568 for (k
= 0; k
< NMAXNSERVERS
; k
++) {
1569 if (tentry
.serverNumber
[k
] == BADSERVERID
)
1571 if (tentry
.serverNumber
[k
] == serverindex
) {
1579 if (attributes
->Mask
& VLLIST_PARTITION
) {
1581 if (tentry
.serverPartition
[k
] != attributes
->partition
)
1584 for (k
= 0; k
< NMAXNSERVERS
; k
++) {
1585 if (tentry
.serverNumber
[k
] == BADSERVERID
)
1587 if (tentry
.serverPartition
[k
] ==
1588 attributes
->partition
) {
1598 if (attributes
->Mask
& VLLIST_FLAG
) {
1599 if (!(tentry
.flags
& attributes
->flag
))
1602 code
= put_nattributeentry(&ctx
, &Vldbentry
, &VldbentryFirst
,
1603 &VldbentryLast
, vldbentries
,
1604 &tentry
, 0, 0, nentries
, &allocCount
);
1609 if (vldbentries
->nbulkentries_len
1610 && (allocCount
> vldbentries
->nbulkentries_len
)) {
1612 vldbentries
->nbulkentries_val
=
1613 realloc(vldbentries
->nbulkentries_val
,
1614 vldbentries
->nbulkentries_len
* sizeof(nvldbentry
));
1615 if (vldbentries
->nbulkentries_val
== NULL
) {
1621 ("NListAttrs nentries=%d %s\n", vldbentries
->nbulkentries_len
,
1622 rxinfo(rxstr
, rxcall
)));
1623 return ubik_EndTrans(ctx
.trans
);
1626 countAbort(this_op
);
1627 ubik_AbortTrans(ctx
.trans
);
1628 if (vldbentries
->nbulkentries_val
)
1629 free(vldbentries
->nbulkentries_val
);
1630 vldbentries
->nbulkentries_val
= 0;
1631 vldbentries
->nbulkentries_len
= 0;
1636 SVL_ListAttributesN(struct rx_call
*rxcall
,
1637 struct VldbListByAttributes
*attributes
,
1638 afs_int32
*nentries
,
1639 nbulkentries
*vldbentries
)
1643 code
= ListAttributesN(rxcall
, attributes
, nentries
, vldbentries
);
1644 osi_auditU(rxcall
, VLListAttributesNEvent
, code
, AUD_END
);
1649 ListAttributesN2(struct rx_call
*rxcall
,
1650 struct VldbListByAttributes
*attributes
,
1651 char *name
, /* Wildcarded volume name */
1652 afs_int32 startindex
,
1653 afs_int32
*nentries
,
1654 nbulkentries
*vldbentries
,
1655 afs_int32
*nextstartindex
)
1657 int this_op
= VLLISTATTRIBUTESN2
;
1658 int code
= 0, maxCount
= VLDBALLOCCOUNT
;
1660 struct nvlentry tentry
;
1661 struct nvldbentry
*Vldbentry
= 0, *VldbentryFirst
= 0, *VldbentryLast
= 0;
1662 afs_int32 blockindex
= 0, count
= 0, k
, match
;
1663 afs_int32 matchindex
= 0;
1664 int serverindex
= -1; /* no server found */
1665 int findserver
= 0, findpartition
= 0, findflag
= 0, findname
= 0;
1667 int namematchRWBK
, namematchRO
, thismatch
;
1670 char volumename
[VL_MAXNAMELEN
+3]; /* regex anchors */
1671 char rxstr
[AFS_RXINFO_LEN
];
1672 #ifdef HAVE_POSIX_REGEX
1674 int need_regfree
= 0;
1679 countRequest(this_op
);
1681 if (!afsconf_CheckRestrictedQuery(vldb_confdir
, rxcall
,
1682 restrictedQueryLevel
))
1685 vldbentries
->nbulkentries_val
= 0;
1686 vldbentries
->nbulkentries_len
= 0;
1688 *nextstartindex
= -1;
1690 code
= Init_VLdbase(&ctx
, LOCKREAD
, this_op
);
1694 Vldbentry
= VldbentryFirst
= vldbentries
->nbulkentries_val
=
1695 malloc(maxCount
* sizeof(nvldbentry
));
1696 if (Vldbentry
== NULL
) {
1697 countAbort(this_op
);
1698 ubik_AbortTrans(ctx
.trans
);
1702 VldbentryLast
= VldbentryFirst
+ maxCount
;
1704 /* Handle the attribute by volume id totally separate of the rest
1705 * (thus additional Mask values are ignored if VLLIST_VOLUMEID is set!)
1707 if (attributes
->Mask
& VLLIST_VOLUMEID
) {
1709 FindByID(&ctx
, attributes
->volumeid
, -1, &tentry
, &code
);
1710 if (blockindex
== 0) {
1715 put_nattributeentry(&ctx
, &Vldbentry
, &VldbentryFirst
,
1716 &VldbentryLast
, vldbentries
, &tentry
, 0,
1717 0, nentries
, &maxCount
);
1723 /* Search each entry in the database and return all entries
1724 * that match the request. It checks volumename (with
1725 * wildcarding), entry flags, server, and partition.
1728 /* Get the server index for matching server address */
1729 if (attributes
->Mask
& VLLIST_SERVER
) {
1731 IpAddrToRelAddr(&ctx
, attributes
->server
, 0);
1732 if (serverindex
== -1)
1736 findpartition
= ((attributes
->Mask
& VLLIST_PARTITION
) ? 1 : 0);
1737 findflag
= ((attributes
->Mask
& VLLIST_FLAG
) ? 1 : 0);
1738 if (name
&& (strcmp(name
, ".*") != 0) && (strcmp(name
, "") != 0)) {
1739 if (!afsconf_SuperUser(vldb_confdir
, rxcall
, NULL
)) {
1743 size
= snprintf(volumename
, sizeof(volumename
), "^%s$", name
);
1744 if (size
< 0 || size
>= sizeof(volumename
)) {
1748 #ifdef HAVE_POSIX_REGEX
1749 if (regcomp(&re
, volumename
, REG_NOSUB
) != 0) {
1755 t
= (char *)re_comp(volumename
);
1764 /* Read each entry and see if it is the one we want */
1765 blockindex
= startindex
;
1766 while ((blockindex
= NextEntry(&ctx
, blockindex
, &tentry
, &count
))) {
1767 if (++pollcount
> 50) {
1768 #ifndef AFS_PTHREAD_ENV
1774 /* Step through each server index searching for a match.
1775 * Match to an existing RW, BK, or RO volume name (preference
1776 * is in this order). Remember which index we matched against.
1778 namematchRWBK
= namematchRO
= 0; /* 0->notTried; 1->match; 2->noMatch */
1782 && (tentry
.serverNumber
[k
] != BADSERVERID
)); k
++) {
1783 thismatch
= 0; /* does this index match */
1785 /* Match against the RW or BK volume name. Remember
1786 * results in namematchRWBK. Prefer RW over BK.
1788 if (tentry
.serverFlags
[k
] & VLSF_RWVOL
) {
1789 /* Does the name match the RW name */
1790 if (tentry
.flags
& VLF_RWEXISTS
) {
1792 size
= snprintf(volumename
, sizeof(volumename
),
1794 if (size
< 0 || size
>= sizeof(volumename
)) {
1798 #ifdef HAVE_POSIX_REGEX
1799 if (regexec(&re
, volumename
, 0, NULL
, 0) == 0) {
1800 thismatch
= VLSF_RWVOL
;
1803 if (re_exec(volumename
)) {
1804 thismatch
= VLSF_RWVOL
;
1808 thismatch
= VLSF_RWVOL
;
1812 /* Does the name match the BK name */
1813 if (!thismatch
&& (tentry
.flags
& VLF_BACKEXISTS
)) {
1815 /* If this fails, the tentry.name is invalid */
1816 size
= snprintf(volumename
, sizeof(volumename
),
1817 "%s.backup", tentry
.name
);
1818 if (size
< 0 || size
>= sizeof(volumename
)) {
1822 #ifdef HAVE_POSIX_REGEX
1823 if (regexec(&re
, volumename
, 0, NULL
, 0) == 0) {
1824 thismatch
= VLSF_BACKVOL
;
1827 if (re_exec(volumename
)) {
1828 thismatch
= VLSF_BACKVOL
;
1832 thismatch
= VLSF_BACKVOL
;
1836 namematchRWBK
= (thismatch
? 1 : 2);
1839 /* Match with the RO volume name. Compare once and
1840 * remember results in namematchRO. Note that this will
1841 * pick up entries marked NEWREPSITEs and DONTUSE.
1844 if (tentry
.flags
& VLF_ROEXISTS
) {
1848 ((namematchRO
== 1) ? VLSF_ROVOL
: 0);
1850 /* If this fails, the tentry.name is invalid */
1851 size
= snprintf(volumename
, sizeof(volumename
),
1852 "%s.readonly", tentry
.name
);
1853 if (size
< 0 || size
>= sizeof(volumename
)) {
1857 #ifdef HAVE_POSIX_REGEX
1858 if (regexec(&re
, volumename
, 0, NULL
, 0) == 0) {
1859 thismatch
= VLSF_ROVOL
;
1862 if (re_exec(volumename
))
1863 thismatch
= VLSF_ROVOL
;
1867 thismatch
= VLSF_ROVOL
;
1870 namematchRO
= (thismatch
? 1 : 2);
1873 /* Is there a server match */
1874 if (thismatch
&& findserver
1875 && (tentry
.serverNumber
[k
] != serverindex
))
1878 /* Is there a partition match */
1879 if (thismatch
&& findpartition
1880 && (tentry
.serverPartition
[k
] != attributes
->partition
))
1883 /* Is there a flag match */
1884 if (thismatch
&& findflag
1885 && !(tentry
.flags
& attributes
->flag
))
1888 /* We found a match. Remember the index, and type */
1892 matchtype
= thismatch
;
1895 /* Since we prefer RW and BK volume matches over RO matches,
1896 * if we have already checked the RWBK name, then we already
1897 * found the best match and so end the search.
1899 * If we tried matching against the RW, BK, and RO volume names
1900 * and both failed, then we end the search (none will match).
1902 if ((match
&& namematchRWBK
)
1903 || ((namematchRWBK
== 2) && (namematchRO
== 2)))
1907 /* Passed all the tests. Take it */
1910 put_nattributeentry(&ctx
, &Vldbentry
, &VldbentryFirst
,
1911 &VldbentryLast
, vldbentries
, &tentry
,
1912 matchtype
, matchindex
, nentries
,
1917 if (*nentries
>= maxCount
)
1918 break; /* collected the max */
1921 *nextstartindex
= (blockindex
? blockindex
: -1);
1925 #ifdef HAVE_POSIX_REGEX
1931 countAbort(this_op
);
1932 ubik_AbortTrans(ctx
.trans
);
1933 if (vldbentries
->nbulkentries_val
)
1934 free(vldbentries
->nbulkentries_val
);
1935 vldbentries
->nbulkentries_val
= 0;
1936 vldbentries
->nbulkentries_len
= 0;
1937 *nextstartindex
= -1;
1940 ("N2ListAttrs nentries=%d %s\n", vldbentries
->nbulkentries_len
,
1941 rxinfo(rxstr
, rxcall
)));
1942 code
= ubik_EndTrans(ctx
.trans
);
1949 SVL_ListAttributesN2(struct rx_call
*rxcall
,
1950 struct VldbListByAttributes
*attributes
,
1951 char *name
, /* Wildcarded volume name */
1952 afs_int32 startindex
,
1953 afs_int32
*nentries
,
1954 nbulkentries
*vldbentries
,
1955 afs_int32
*nextstartindex
)
1959 code
= ListAttributesN2(rxcall
, attributes
, name
, startindex
,
1960 nentries
, vldbentries
, nextstartindex
);
1961 osi_auditU(rxcall
, VLListAttributesN2Event
, code
, AUD_END
);
1965 /* Retrieves in vldbentries all vldb entries that match the specified
1966 * attributes (by server number, partition, volume type, and flag); if
1967 * volume id is specified then the associated list for that entry is
1968 * returned. CAUTION: This could be a very expensive call since in most
1969 * cases sequential search of all vldb entries is performed.
1972 LinkedList(struct rx_call
*rxcall
,
1973 struct VldbListByAttributes
*attributes
,
1974 afs_int32
*nentries
,
1975 vldb_list
*vldbentries
)
1977 int this_op
= VLLINKEDLIST
;
1980 struct nvlentry tentry
;
1981 vldblist vllist
, *vllistptr
;
1982 afs_int32 blockindex
, count
, match
;
1987 countRequest(this_op
);
1989 if (!afsconf_CheckRestrictedQuery(vldb_confdir
, rxcall
,
1990 restrictedQueryLevel
))
1993 if ((code
= Init_VLdbase(&ctx
, LOCKREAD
, this_op
)))
1997 vldbentries
->node
= NULL
;
1998 vllistptr
= &vldbentries
->node
;
2000 /* List by volumeid */
2001 if (attributes
->Mask
& VLLIST_VOLUMEID
) {
2003 FindByID(&ctx
, attributes
->volumeid
, -1, &tentry
, &code
);
2010 vllist
= malloc(sizeof(single_vldbentry
));
2011 if (vllist
== NULL
) {
2015 code
= vlentry_to_vldbentry(&ctx
, &tentry
, &vllist
->VldbEntry
);
2019 vllist
->next_vldb
= NULL
;
2021 *vllistptr
= vllist
; /* Thread onto list */
2022 vllistptr
= &vllist
->next_vldb
;
2026 /* Search by server, partition, and flags */
2028 for (blockindex
= NextEntry(&ctx
, 0, &tentry
, &count
); blockindex
;
2029 blockindex
= NextEntry(&ctx
, blockindex
, &tentry
, &count
)) {
2032 if (++pollcount
> 50) {
2033 #ifndef AFS_PTHREAD_ENV
2039 /* Does this volume exist on the desired server */
2040 if (attributes
->Mask
& VLLIST_SERVER
) {
2042 IpAddrToRelAddr(&ctx
, attributes
->server
, 0);
2043 if (serverindex
== -1)
2045 for (k
= 0; k
< OMAXNSERVERS
; k
++) {
2046 if (tentry
.serverNumber
[k
] == BADSERVERID
)
2048 if (tentry
.serverNumber
[k
] == serverindex
) {
2057 /* Does this volume exist on the desired partition */
2058 if (attributes
->Mask
& VLLIST_PARTITION
) {
2060 if (tentry
.serverPartition
[k
] != attributes
->partition
)
2063 for (k
= 0; k
< OMAXNSERVERS
; k
++) {
2064 if (tentry
.serverNumber
[k
] == BADSERVERID
)
2066 if (tentry
.serverPartition
[k
] ==
2067 attributes
->partition
) {
2077 /* Does this volume have the desired flags */
2078 if (attributes
->Mask
& VLLIST_FLAG
) {
2079 if (!(tentry
.flags
& attributes
->flag
))
2083 vllist
= malloc(sizeof(single_vldbentry
));
2084 if (vllist
== NULL
) {
2088 code
= vlentry_to_vldbentry(&ctx
, &tentry
, &vllist
->VldbEntry
);
2092 vllist
->next_vldb
= NULL
;
2094 *vllistptr
= vllist
; /* Thread onto list */
2095 vllistptr
= &vllist
->next_vldb
;
2097 if (smallMem
&& (*nentries
>= VLDBALLOCCOUNT
)) {
2098 code
= VL_SIZEEXCEEDED
;
2104 return ubik_EndTrans(ctx
.trans
);
2107 countAbort(this_op
);
2108 ubik_AbortTrans(ctx
.trans
);
2113 SVL_LinkedList(struct rx_call
*rxcall
,
2114 struct VldbListByAttributes
*attributes
,
2115 afs_int32
*nentries
,
2116 vldb_list
*vldbentries
)
2120 code
= LinkedList(rxcall
, attributes
, nentries
, vldbentries
);
2121 osi_auditU(rxcall
, VLLinkedListEvent
, code
, AUD_END
);
2126 LinkedListN(struct rx_call
*rxcall
,
2127 struct VldbListByAttributes
*attributes
,
2128 afs_int32
*nentries
,
2129 nvldb_list
*vldbentries
)
2131 int this_op
= VLLINKEDLISTN
;
2134 struct nvlentry tentry
;
2135 nvldblist vllist
, *vllistptr
;
2136 afs_int32 blockindex
, count
, match
;
2141 countRequest(this_op
);
2143 if (!afsconf_CheckRestrictedQuery(vldb_confdir
, rxcall
,
2144 restrictedQueryLevel
))
2147 if ((code
= Init_VLdbase(&ctx
, LOCKREAD
, this_op
)))
2151 vldbentries
->node
= NULL
;
2152 vllistptr
= &vldbentries
->node
;
2154 /* List by volumeid */
2155 if (attributes
->Mask
& VLLIST_VOLUMEID
) {
2157 FindByID(&ctx
, attributes
->volumeid
, -1, &tentry
, &code
);
2164 vllist
= malloc(sizeof(single_nvldbentry
));
2165 if (vllist
== NULL
) {
2169 code
= vlentry_to_nvldbentry(&ctx
, &tentry
, &vllist
->VldbEntry
);
2173 vllist
->next_vldb
= NULL
;
2175 *vllistptr
= vllist
; /* Thread onto list */
2176 vllistptr
= &vllist
->next_vldb
;
2180 /* Search by server, partition, and flags */
2182 for (blockindex
= NextEntry(&ctx
, 0, &tentry
, &count
); blockindex
;
2183 blockindex
= NextEntry(&ctx
, blockindex
, &tentry
, &count
)) {
2186 if (++pollcount
> 50) {
2187 #ifndef AFS_PTHREAD_ENV
2193 /* Does this volume exist on the desired server */
2194 if (attributes
->Mask
& VLLIST_SERVER
) {
2196 IpAddrToRelAddr(&ctx
, attributes
->server
, 0);
2197 if (serverindex
== -1)
2199 for (k
= 0; k
< NMAXNSERVERS
; k
++) {
2200 if (tentry
.serverNumber
[k
] == BADSERVERID
)
2202 if (tentry
.serverNumber
[k
] == serverindex
) {
2211 /* Does this volume exist on the desired partition */
2212 if (attributes
->Mask
& VLLIST_PARTITION
) {
2214 if (tentry
.serverPartition
[k
] != attributes
->partition
)
2217 for (k
= 0; k
< NMAXNSERVERS
; k
++) {
2218 if (tentry
.serverNumber
[k
] == BADSERVERID
)
2220 if (tentry
.serverPartition
[k
] ==
2221 attributes
->partition
) {
2231 /* Does this volume have the desired flags */
2232 if (attributes
->Mask
& VLLIST_FLAG
) {
2233 if (!(tentry
.flags
& attributes
->flag
))
2237 vllist
= malloc(sizeof(single_nvldbentry
));
2238 if (vllist
== NULL
) {
2242 code
= vlentry_to_nvldbentry(&ctx
, &tentry
, &vllist
->VldbEntry
);
2246 vllist
->next_vldb
= NULL
;
2248 *vllistptr
= vllist
; /* Thread onto list */
2249 vllistptr
= &vllist
->next_vldb
;
2251 if (smallMem
&& (*nentries
>= VLDBALLOCCOUNT
)) {
2252 code
= VL_SIZEEXCEEDED
;
2258 return ubik_EndTrans(ctx
.trans
);
2261 countAbort(this_op
);
2262 ubik_AbortTrans(ctx
.trans
);
2267 SVL_LinkedListN(struct rx_call
*rxcall
,
2268 struct VldbListByAttributes
*attributes
,
2269 afs_int32
*nentries
,
2270 nvldb_list
*vldbentries
)
2274 code
= LinkedListN(rxcall
, attributes
, nentries
, vldbentries
);
2275 osi_auditU(rxcall
, VLLinkedListNEvent
, code
, AUD_END
);
2279 /* Get back vldb header statistics (allocs, frees, maxvolumeid,
2280 * totalentries, etc) and dynamic statistics (number of requests and/or
2281 * aborts per remote procedure call, etc)
2284 GetStats(struct rx_call
*rxcall
,
2286 vital_vlheader
*vital_header
)
2288 int this_op
= VLGETSTATS
;
2291 char rxstr
[AFS_RXINFO_LEN
];
2293 countRequest(this_op
);
2295 if (!afsconf_CheckRestrictedQuery(vldb_confdir
, rxcall
,
2296 restrictedQueryLevel
))
2299 if ((code
= Init_VLdbase(&ctx
, LOCKREAD
, this_op
)))
2301 VLog(5, ("GetStats %s\n", rxinfo(rxstr
, rxcall
)));
2302 memcpy((char *)vital_header
, (char *)&ctx
.cheader
->vital_header
,
2303 sizeof(vital_vlheader
));
2304 memcpy((char *)stats
, (char *)&dynamic_statistics
, sizeof(vldstats
));
2305 return ubik_EndTrans(ctx
.trans
);
2309 SVL_GetStats(struct rx_call
*rxcall
,
2311 vital_vlheader
*vital_header
)
2315 code
= GetStats(rxcall
, stats
, vital_header
);
2316 osi_auditU(rxcall
, VLGetStatsEvent
, code
, AUD_END
);
2320 /* Get the list of file server addresses from the VLDB. Currently it's pretty
2321 * easy to do. In the future, it might require a little bit of grunging
2322 * through the VLDB, but that's life.
2325 SVL_GetAddrs(struct rx_call
*rxcall
,
2328 struct VLCallBack
*spare3
,
2329 afs_int32
*nentries
,
2332 int this_op
= VLGETADDRS
;
2338 countRequest(this_op
);
2339 addrsp
->bulkaddrs_len
= *nentries
= 0;
2340 addrsp
->bulkaddrs_val
= 0;
2341 memset(spare3
, 0, sizeof(struct VLCallBack
));
2343 if ((code
= Init_VLdbase(&ctx
, LOCKREAD
, this_op
)))
2346 VLog(5, ("GetAddrs\n"));
2347 addrsp
->bulkaddrs_val
= taddrp
=
2348 malloc(sizeof(afs_uint32
) * (MAXSERVERID
+ 1));
2349 nservers
= *nentries
= addrsp
->bulkaddrs_len
= 0;
2356 for (i
= 0; i
<= MAXSERVERID
; i
++) {
2357 if ((*taddrp
= ntohl(ctx
.cheader
->IpMappedAddr
[i
]))) {
2363 addrsp
->bulkaddrs_len
= *nentries
= nservers
;
2364 return (ubik_EndTrans(ctx
.trans
));
2367 countAbort(this_op
);
2368 ubik_AbortTrans(ctx
.trans
);
2373 append_addr(char *buffer
, afs_uint32 addr
, size_t buffer_size
)
2375 int n
= strlen(buffer
);
2376 if (buffer_size
> n
) {
2377 snprintf(buffer
+ n
, buffer_size
- n
, "%u.%u.%u.%u",
2378 (addr
>> 24) & 0xff, (addr
>> 16) & 0xff, (addr
>> 8) & 0xff,
2384 SVL_RegisterAddrs(struct rx_call
*rxcall
, afsUUID
*uuidp
, afs_int32 spare1
,
2387 int this_op
= VLREGADDR
;
2390 int cnt
, h
, i
, j
, k
, m
;
2391 struct extentaddr
*exp
= 0, *tex
;
2394 afs_uint32 addrs
[VL_MAXIPADDRS_PERMH
];
2396 int count
, willChangeEntry
, foundUuidEntry
, willReplaceCnt
;
2397 int WillReplaceEntry
, WillChange
[MAXSERVERID
+ 1];
2399 int ReplaceEntry
= 0;
2402 countRequest(this_op
);
2403 if (!afsconf_SuperUser(vldb_confdir
, rxcall
, NULL
))
2405 if ((code
= Init_VLdbase(&ctx
, LOCKWRITE
, this_op
)))
2408 /* Eliminate duplicates from IP address list */
2409 for (k
= 0, cnt
= 0; k
< addrsp
->bulkaddrs_len
; k
++) {
2410 if (addrsp
->bulkaddrs_val
[k
] == 0)
2412 for (m
= 0; m
< cnt
; m
++) {
2413 if (addrs
[m
] == addrsp
->bulkaddrs_val
[k
])
2417 if (m
== VL_MAXIPADDRS_PERMH
) {
2419 ("Number of addresses exceeds %d. Cannot register IP addr 0x%x in VLDB\n",
2420 VL_MAXIPADDRS_PERMH
, addrsp
->bulkaddrs_val
[k
]));
2422 addrs
[m
] = addrsp
->bulkaddrs_val
[k
];
2428 code
= VL_INDEXERANGE
;
2435 /* For each server registered within the VLDB */
2436 for (srvidx
= 0; srvidx
<= MAXSERVERID
; srvidx
++) {
2437 willChangeEntry
= 0;
2438 WillReplaceEntry
= 1;
2439 code
= multiHomedExtent(&ctx
, srvidx
, &exp
);
2444 /* See if the addresses to register will change this server entry */
2445 tuuid
= exp
->ex_hostuuid
;
2446 afs_ntohuuid(&tuuid
);
2447 if (afs_uuid_equal(uuidp
, &tuuid
)) {
2451 for (mhidx
= 0; mhidx
< VL_MAXIPADDRS_PERMH
; mhidx
++) {
2452 if (!exp
->ex_addrs
[mhidx
])
2454 for (k
= 0; k
< cnt
; k
++) {
2455 if (ntohl(exp
->ex_addrs
[mhidx
]) == addrs
[k
]) {
2456 willChangeEntry
= 1;
2457 WillChange
[count
] = srvidx
;
2462 WillReplaceEntry
= 0;
2466 /* The server is not registered as a multihomed.
2467 * See if the addresses to register will replace this server entry.
2469 for (k
= 0; k
< cnt
; k
++) {
2470 if (ctx
.hostaddress
[srvidx
] == addrs
[k
]) {
2471 willChangeEntry
= 1;
2472 WillChange
[count
] = srvidx
;
2473 WillReplaceEntry
= 1;
2478 if (willChangeEntry
) {
2479 if (WillReplaceEntry
) {
2481 ReplaceEntry
= srvidx
;
2487 /* If we found the uuid in the VLDB and if we are replacing another
2488 * entire entry, then complain and fail. Also, if we did not find
2489 * the uuid in the VLDB and the IP addresses being registered was
2490 * found in more than one other entry, then we don't know which one
2491 * to replace and will complain and fail.
2493 if ((foundUuidEntry
&& (willReplaceCnt
> 0))
2494 || (!foundUuidEntry
&& (count
> 1))) {
2496 ("The following fileserver is being registered in the VLDB:\n"));
2497 for (addrbuf
[0] = '\0', k
= 0; k
< cnt
; k
++) {
2499 strlcat(addrbuf
, " ", sizeof(addrbuf
));
2500 append_addr(addrbuf
, addrs
[k
], sizeof(addrbuf
));
2502 VLog(0, (" [%s]\n", addrbuf
));
2504 if (foundUuidEntry
) {
2505 code
= multiHomedExtent(&ctx
, FoundUuid
, &exp
);
2507 VLog(0, (" It would have replaced the existing VLDB server "
2509 for (addrbuf
[0] = '\0', mhidx
= 0; mhidx
< VL_MAXIPADDRS_PERMH
; mhidx
++) {
2510 if (!exp
->ex_addrs
[mhidx
])
2513 strlcat(addrbuf
, " ", sizeof(addrbuf
));
2514 append_addr(addrbuf
, ntohl(exp
->ex_addrs
[mhidx
]), sizeof(addrbuf
));
2516 VLog(0, (" entry %d: [%s]\n", FoundUuid
, addrbuf
));
2521 VLog(0, (" Yet another VLDB server entry exists:\n"));
2523 VLog(0, (" Yet other VLDB server entries exist:\n"));
2524 for (j
= 0; j
< count
; j
++) {
2525 srvidx
= WillChange
[j
];
2526 VLog(0, (" entry %d: ", srvidx
));
2528 code
= multiHomedExtent(&ctx
, srvidx
, &exp
);
2534 for (mhidx
= 0; mhidx
< VL_MAXIPADDRS_PERMH
; mhidx
++) {
2535 if (!exp
->ex_addrs
[mhidx
])
2538 strlcat(addrbuf
, " ", sizeof(addrbuf
));
2539 append_addr(addrbuf
, ntohl(exp
->ex_addrs
[mhidx
]), sizeof(addrbuf
));
2542 append_addr(addrbuf
, ctx
.hostaddress
[srvidx
], sizeof(addrbuf
));
2544 VLog(0, (" entry %d: [%s]\n", srvidx
, addrbuf
));
2548 VLog(0, (" You must 'vos changeaddr' this other server entry\n"));
2551 (" You must 'vos changeaddr' these other server entries\n"));
2554 (" and/or remove the sysid file from the registering fileserver\n"));
2555 VLog(0, (" before the fileserver can be registered in the VLDB.\n"));
2557 code
= VL_MULTIPADDR
;
2561 /* Passed the checks. Now find and update the existing mh entry, or create
2564 if (foundUuidEntry
) {
2565 /* Found the entry with same uuid. See if we need to change it */
2568 code
= multiHomedExtentBase(&ctx
, FoundUuid
, &exp
, &base
);
2572 /* Determine if the entry has changed */
2573 for (k
= 0; ((k
< cnt
) && !change
); k
++) {
2574 if (ntohl(exp
->ex_addrs
[k
]) != addrs
[k
])
2577 for (; ((k
< VL_MAXIPADDRS_PERMH
) && !change
); k
++) {
2578 if (exp
->ex_addrs
[k
] != 0)
2582 return (ubik_EndTrans(ctx
.trans
));
2586 VLog(0, ("The following fileserver is being registered in the VLDB:\n"));
2587 for (addrbuf
[0] = '\0', k
= 0; k
< cnt
; k
++) {
2589 strlcat(addrbuf
, " ", sizeof(addrbuf
));
2590 append_addr(addrbuf
, addrs
[k
], sizeof(addrbuf
));
2592 VLog(0, (" [%s]\n", addrbuf
));
2594 if (foundUuidEntry
) {
2596 (" It will replace the following existing entry in the VLDB (same uuid):\n"));
2597 for (addrbuf
[0] = '\0', k
= 0; k
< VL_MAXIPADDRS_PERMH
; k
++) {
2598 if (exp
->ex_addrs
[k
] == 0)
2601 strlcat(addrbuf
, " ", sizeof(addrbuf
));
2602 append_addr(addrbuf
, ntohl(exp
->ex_addrs
[k
]), sizeof(addrbuf
));
2604 VLog(0, (" entry %d: [%s]\n", FoundUuid
, addrbuf
));
2605 } else if (willReplaceCnt
|| (count
== 1)) {
2606 /* If we are not replacing an entry and there is only one entry to change,
2607 * then we will replace that entry.
2609 if (!willReplaceCnt
) {
2610 ReplaceEntry
= WillChange
[0];
2614 /* Have an entry that needs to be replaced */
2615 code
= multiHomedExtentBase(&ctx
, ReplaceEntry
, &exp
, &base
);
2621 (" It will replace the following existing entry in the VLDB (new uuid):\n"));
2622 for (addrbuf
[0] = '\0', k
= 0; k
< VL_MAXIPADDRS_PERMH
; k
++) {
2623 if (exp
->ex_addrs
[k
] == 0)
2626 strlcat(addrbuf
, " ", sizeof(addrbuf
));
2627 append_addr(addrbuf
, ntohl(exp
->ex_addrs
[k
]), sizeof(addrbuf
));
2629 VLog(0, (" entry %d: [%s]\n", ReplaceEntry
, addrbuf
));
2631 /* Not a mh entry. So we have to create a new mh entry and
2632 * put it on the ReplaceEntry slot of the ctx.hostaddress array.
2635 append_addr(addrbuf
, ctx
.hostaddress
[ReplaceEntry
], sizeof(addrbuf
));
2636 VLog(0, (" It will replace existing entry %d, %s,"
2637 " in the VLDB (new uuid):\n", ReplaceEntry
, addrbuf
));
2639 FindExtentBlock(&ctx
, uuidp
, 1, ReplaceEntry
, &exp
, &base
);
2647 /* There is no entry for this server, must create a new mh entry as
2648 * well as use a new slot of the ctx.hostaddress array.
2650 VLog(0, (" It will create a new entry in the VLDB.\n"));
2651 code
= FindExtentBlock(&ctx
, uuidp
, 1, -1, &exp
, &base
);
2659 /* Now we have a mh entry to fill in. Update the uuid, bump the
2660 * uniquifier, and fill in its IP addresses.
2663 afs_htonuuid(&tuuid
);
2664 exp
->ex_hostuuid
= tuuid
;
2665 exp
->ex_uniquifier
= htonl(ntohl(exp
->ex_uniquifier
) + 1);
2666 for (k
= 0; k
< cnt
; k
++) {
2667 exp
->ex_addrs
[k
] = htonl(addrs
[k
]);
2669 for (; k
< VL_MAXIPADDRS_PERMH
; k
++) {
2670 exp
->ex_addrs
[k
] = 0;
2673 /* Write the new mh entry out */
2676 DOFFSET(ntohl(ctx
.ex_addr
[0]->ex_contaddrs
[base
]),
2677 (char *)ctx
.ex_addr
[base
], (char *)exp
), (char *)exp
,
2683 /* Remove any common addresses from other mh entres. We know these entries
2684 * are being changed and not replaced so they are mh entries.
2687 for (i
= 0; i
< count
; i
++) {
2690 /* Skip the entry we replaced */
2691 if (willReplaceCnt
&& (WillChange
[i
] == ReplaceEntry
))
2694 code
= multiHomedExtentBase(&ctx
, WillChange
[i
], &tex
, &base
);
2700 (" The following existing entries in the VLDB will be updated:\n"));
2702 for (addrbuf
[0] = '\0', h
= j
= 0; j
< VL_MAXIPADDRS_PERMH
; j
++) {
2703 if (tex
->ex_addrs
[j
]) {
2705 strlcat(addrbuf
, " ", sizeof(addrbuf
));
2706 append_addr(addrbuf
, ntohl(tex
->ex_addrs
[j
]), sizeof(addrbuf
));
2709 for (k
= 0; k
< cnt
; k
++) {
2710 if (ntohl(tex
->ex_addrs
[j
]) == addrs
[k
])
2714 /* Not found, so we keep it */
2715 tex
->ex_addrs
[h
] = tex
->ex_addrs
[j
];
2719 for (j
= h
; j
< VL_MAXIPADDRS_PERMH
; j
++) {
2720 tex
->ex_addrs
[j
] = 0; /* zero rest of mh entry */
2722 VLog(0, (" entry %d: [%s]\n", WillChange
[i
], addrbuf
));
2724 /* Write out the modified mh entry */
2725 tex
->ex_uniquifier
= htonl(ntohl(tex
->ex_uniquifier
) + 1);
2727 DOFFSET(ntohl(ctx
.ex_addr
[0]->ex_contaddrs
[base
]),
2728 (char *)ctx
.ex_addr
[base
], (char *)tex
);
2729 if (vlwrite(ctx
.trans
, doff
, (char *)tex
, sizeof(*tex
))) {
2735 return (ubik_EndTrans(ctx
.trans
));
2738 countAbort(this_op
);
2739 ubik_AbortTrans(ctx
.trans
);
2744 SVL_GetAddrsU(struct rx_call
*rxcall
,
2745 struct ListAddrByAttributes
*attributes
,
2747 afs_int32
*uniquifier
,
2748 afs_int32
*nentries
,
2751 int this_op
= VLGETADDRSU
;
2752 afs_int32 code
, index
;
2754 int nservers
, i
, j
, base
= 0;
2755 struct extentaddr
*exp
= 0;
2757 afs_uint32
*taddrp
, taddr
;
2758 char rxstr
[AFS_RXINFO_LEN
];
2760 countRequest(this_op
);
2761 addrsp
->bulkaddrs_len
= *nentries
= 0;
2762 addrsp
->bulkaddrs_val
= 0;
2763 VLog(5, ("GetAddrsU %s\n", rxinfo(rxstr
, rxcall
)));
2764 if ((code
= Init_VLdbase(&ctx
, LOCKREAD
, this_op
)))
2767 if (attributes
->Mask
& VLADDR_IPADDR
) {
2768 if (attributes
->Mask
& (VLADDR_INDEX
| VLADDR_UUID
)) {
2772 /* Search for a server registered with the VLDB with this ip address. */
2773 for (index
= 0; index
<= MAXSERVERID
; index
++) {
2774 code
= multiHomedExtent(&ctx
, index
, &exp
);
2779 for (j
= 0; j
< VL_MAXIPADDRS_PERMH
; j
++) {
2780 if (exp
->ex_addrs
[j
]
2781 && (ntohl(exp
->ex_addrs
[j
]) == attributes
->ipaddr
)) {
2785 if (j
< VL_MAXIPADDRS_PERMH
)
2789 if (index
> MAXSERVERID
) {
2793 } else if (attributes
->Mask
& VLADDR_INDEX
) {
2794 if (attributes
->Mask
& (VLADDR_IPADDR
| VLADDR_UUID
)) {
2798 /* VLADDR_INDEX index is one based */
2799 if (attributes
->index
< 1 || attributes
->index
> MAXSERVERID
) {
2800 code
= VL_INDEXERANGE
;
2803 index
= attributes
->index
- 1;
2804 code
= multiHomedExtent(&ctx
, index
, &exp
);
2809 } else if (attributes
->Mask
& VLADDR_UUID
) {
2810 if (attributes
->Mask
& (VLADDR_IPADDR
| VLADDR_INDEX
)) {
2814 if (!ctx
.ex_addr
[0]) { /* mh servers probably aren't setup on this vldb */
2818 code
= FindExtentBlock(&ctx
, &attributes
->uuid
, 0, -1, &exp
, &base
);
2830 addrsp
->bulkaddrs_val
= taddrp
=
2831 malloc(sizeof(afs_uint32
) * (MAXSERVERID
+ 1));
2832 nservers
= *nentries
= addrsp
->bulkaddrs_len
= 0;
2837 tuuid
= exp
->ex_hostuuid
;
2838 afs_ntohuuid(&tuuid
);
2839 if (afs_uuid_is_nil(&tuuid
)) {
2846 *uniquifier
= ntohl(exp
->ex_uniquifier
);
2847 for (i
= 0; i
< VL_MAXIPADDRS_PERMH
; i
++) {
2848 if (exp
->ex_addrs
[i
]) {
2849 taddr
= ntohl(exp
->ex_addrs
[i
]);
2850 /* Weed out duplicates */
2851 for (j
= 0; j
< nservers
; j
++) {
2852 if (taddrp
[j
] == taddr
)
2855 if ((j
== nservers
) && (j
<= MAXSERVERID
)) {
2856 taddrp
[nservers
] = taddr
;
2861 addrsp
->bulkaddrs_len
= *nentries
= nservers
;
2862 return (ubik_EndTrans(ctx
.trans
));
2865 countAbort(this_op
);
2866 ubik_AbortTrans(ctx
.trans
);
2870 /* ============> End of Exported vldb RPC functions <============= */
2873 /* Routine that copies the given vldb entry to the output buffer, vldbentries. */
2875 put_attributeentry(struct vl_ctx
*ctx
,
2876 struct vldbentry
**Vldbentry
,
2877 struct vldbentry
**VldbentryFirst
,
2878 struct vldbentry
**VldbentryLast
,
2879 bulkentries
*vldbentries
,
2880 struct nvlentry
*entry
,
2881 afs_int32
*nentries
,
2882 afs_int32
*alloccnt
)
2888 if (*Vldbentry
== *VldbentryLast
) {
2890 return VL_SIZEEXCEEDED
; /* no growing if smallMem defined */
2892 /* Allocate another set of memory; each time allocate twice as
2893 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2894 * then grow in increments of VLDBALLOCINCR.
2896 allo
= (*alloccnt
> VLDBALLOCLIMIT
) ? VLDBALLOCINCR
: *alloccnt
;
2897 reall
= realloc(*VldbentryFirst
,
2898 (*alloccnt
+ allo
) * sizeof(vldbentry
));
2902 *VldbentryFirst
= vldbentries
->bulkentries_val
= reall
;
2903 *Vldbentry
= *VldbentryFirst
+ *alloccnt
;
2904 *VldbentryLast
= *Vldbentry
+ allo
;
2908 code
= vlentry_to_vldbentry(ctx
, entry
, *Vldbentry
);
2914 vldbentries
->bulkentries_len
++;
2919 put_nattributeentry(struct vl_ctx
*ctx
,
2920 struct nvldbentry
**Vldbentry
,
2921 struct nvldbentry
**VldbentryFirst
,
2922 struct nvldbentry
**VldbentryLast
,
2923 nbulkentries
*vldbentries
,
2924 struct nvlentry
*entry
,
2925 afs_int32 matchtype
,
2926 afs_int32 matchindex
,
2927 afs_int32
*nentries
,
2928 afs_int32
*alloccnt
)
2934 if (*Vldbentry
== *VldbentryLast
) {
2936 return VL_SIZEEXCEEDED
; /* no growing if smallMem defined */
2938 /* Allocate another set of memory; each time allocate twice as
2939 * many blocks as the last time. When we reach VLDBALLOCLIMIT,
2940 * then grow in increments of VLDBALLOCINCR.
2942 allo
= (*alloccnt
> VLDBALLOCLIMIT
) ? VLDBALLOCINCR
: *alloccnt
;
2943 reall
= realloc(*VldbentryFirst
,
2944 (*alloccnt
+ allo
) * sizeof(nvldbentry
));
2948 *VldbentryFirst
= vldbentries
->nbulkentries_val
= reall
;
2949 *Vldbentry
= *VldbentryFirst
+ *alloccnt
;
2950 *VldbentryLast
= *Vldbentry
+ allo
;
2953 code
= vlentry_to_nvldbentry(ctx
, entry
, *Vldbentry
);
2957 (*Vldbentry
)->matchindex
= (matchtype
<< 16) + matchindex
;
2960 vldbentries
->nbulkentries_len
++;
2965 /* Common code to actually remove a vldb entry from the database. */
2967 RemoveEntry(struct vl_ctx
*ctx
, afs_int32 entryptr
,
2968 struct nvlentry
*tentry
)
2972 if ((code
= UnthreadVLentry(ctx
, entryptr
, tentry
)))
2974 if ((code
= FreeBlock(ctx
, entryptr
)))
2980 ReleaseEntry(struct nvlentry
*tentry
, afs_int32 releasetype
)
2982 if (releasetype
& LOCKREL_TIMESTAMP
)
2983 tentry
->LockTimestamp
= 0;
2984 if (releasetype
& LOCKREL_OPCODE
)
2985 tentry
->flags
&= ~VLOP_ALLOPERS
;
2986 if (releasetype
& LOCKREL_AFSID
)
2987 tentry
->LockAfsId
= 0;
2991 /* Verify that the incoming vldb entry is valid; multi type of error codes
2994 check_vldbentry(struct vldbentry
*aentry
)
2998 if (InvalidVolname(aentry
->name
))
3000 if (aentry
->nServers
<= 0 || aentry
->nServers
> OMAXNSERVERS
)
3001 return VL_BADSERVER
;
3002 for (i
= 0; i
< aentry
->nServers
; i
++) {
3003 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
3004 return VL_BADSERVER; */
3005 if (aentry
->serverPartition
[i
] < 0
3006 || aentry
->serverPartition
[i
] > MAXPARTITIONID
)
3007 return VL_BADPARTITION
;
3008 if (aentry
->serverFlags
[i
] < 0
3009 || aentry
->serverFlags
[i
] > MAXSERVERFLAG
)
3010 return VL_BADSERVERFLAG
;
3016 check_nvldbentry(struct nvldbentry
*aentry
)
3020 if (InvalidVolname(aentry
->name
))
3022 if (aentry
->nServers
<= 0 || aentry
->nServers
> NMAXNSERVERS
)
3023 return VL_BADSERVER
;
3024 for (i
= 0; i
< aentry
->nServers
; i
++) {
3025 /* if (aentry->serverNumber[i] < 0 || aentry->serverNumber[i] > MAXSERVERID)
3026 return VL_BADSERVER; */
3027 if (aentry
->serverPartition
[i
] < 0
3028 || aentry
->serverPartition
[i
] > MAXPARTITIONID
)
3029 return VL_BADPARTITION
;
3030 if (aentry
->serverFlags
[i
] < 0
3031 || aentry
->serverFlags
[i
] > MAXSERVERFLAG
)
3032 return VL_BADSERVERFLAG
;
3038 /* Convert from the external vldb entry representation to its internal
3039 (more compact) form. This call should not change the hash chains! */
3041 vldbentry_to_vlentry(struct vl_ctx
*ctx
,
3042 struct vldbentry
*VldbEntry
,
3043 struct nvlentry
*VlEntry
)
3047 if (strcmp(VlEntry
->name
, VldbEntry
->name
))
3048 strncpy(VlEntry
->name
, VldbEntry
->name
, sizeof(VlEntry
->name
));
3049 for (i
= 0; i
< VldbEntry
->nServers
; i
++) {
3050 serverindex
= IpAddrToRelAddr(ctx
, VldbEntry
->serverNumber
[i
], 1);
3051 if (serverindex
== -1)
3052 return VL_BADSERVER
;
3053 VlEntry
->serverNumber
[i
] = serverindex
;
3054 VlEntry
->serverPartition
[i
] = VldbEntry
->serverPartition
[i
];
3055 VlEntry
->serverFlags
[i
] = VldbEntry
->serverFlags
[i
];
3057 for (; i
< OMAXNSERVERS
; i
++)
3058 VlEntry
->serverNumber
[i
] = VlEntry
->serverPartition
[i
] =
3059 VlEntry
->serverFlags
[i
] = BADSERVERID
;
3060 for (i
= 0; i
< MAXTYPES
; i
++)
3061 VlEntry
->volumeId
[i
] = VldbEntry
->volumeId
[i
];
3062 VlEntry
->cloneId
= VldbEntry
->cloneId
;
3063 VlEntry
->flags
= VldbEntry
->flags
;
3068 nvldbentry_to_vlentry(struct vl_ctx
*ctx
,
3069 struct nvldbentry
*VldbEntry
,
3070 struct nvlentry
*VlEntry
)
3074 if (strcmp(VlEntry
->name
, VldbEntry
->name
))
3075 strncpy(VlEntry
->name
, VldbEntry
->name
, sizeof(VlEntry
->name
));
3076 for (i
= 0; i
< VldbEntry
->nServers
; i
++) {
3077 serverindex
= IpAddrToRelAddr(ctx
, VldbEntry
->serverNumber
[i
], 1);
3078 if (serverindex
== -1)
3079 return VL_BADSERVER
;
3080 VlEntry
->serverNumber
[i
] = serverindex
;
3081 VlEntry
->serverPartition
[i
] = VldbEntry
->serverPartition
[i
];
3082 VlEntry
->serverFlags
[i
] = VldbEntry
->serverFlags
[i
];
3084 for (; i
< NMAXNSERVERS
; i
++)
3085 VlEntry
->serverNumber
[i
] = VlEntry
->serverPartition
[i
] =
3086 VlEntry
->serverFlags
[i
] = BADSERVERID
;
3087 for (i
= 0; i
< MAXTYPES
; i
++)
3088 VlEntry
->volumeId
[i
] = VldbEntry
->volumeId
[i
];
3089 VlEntry
->cloneId
= VldbEntry
->cloneId
;
3090 VlEntry
->flags
= VldbEntry
->flags
;
3095 /* Update the vldb entry with the new fields as indicated by the value of
3096 * the Mask entry in the updateentry structure. All necessary validation
3097 * checks are performed.
3100 get_vldbupdateentry(struct vl_ctx
*ctx
,
3101 afs_int32 blockindex
,
3102 struct VldbUpdateEntry
*updateentry
,
3103 struct nvlentry
*VlEntry
)
3105 int i
, j
, code
, serverindex
;
3106 afs_uint32 checkids
[MAXTYPES
];
3108 /* check if any specified new IDs are already present in the db. Do
3109 * this check before doing anything else, so we don't get a half-
3111 memset(&checkids
, 0, sizeof(checkids
));
3112 if (updateentry
->Mask
& VLUPDATE_RWID
) {
3113 checkids
[RWVOL
] = updateentry
->spares3
; /* rw id */
3115 if (updateentry
->Mask
& VLUPDATE_READONLYID
) {
3116 checkids
[ROVOL
] = updateentry
->ReadOnlyId
;
3118 if (updateentry
->Mask
& VLUPDATE_BACKUPID
) {
3119 checkids
[BACKVOL
] = updateentry
->BackupId
;
3122 if (EntryIDExists(ctx
, checkids
, MAXTYPES
, &code
)) {
3128 if (updateentry
->Mask
& VLUPDATE_VOLUMENAME
) {
3129 struct nvlentry tentry
;
3131 if (InvalidVolname(updateentry
->name
))
3134 if (FindByName(ctx
, updateentry
->name
, &tentry
, &code
)) {
3135 return VL_NAMEEXIST
;
3140 if ((code
= UnhashVolname(ctx
, blockindex
, VlEntry
)))
3142 strncpy(VlEntry
->name
, updateentry
->name
, sizeof(VlEntry
->name
));
3143 HashVolname(ctx
, blockindex
, VlEntry
);
3146 if (updateentry
->Mask
& VLUPDATE_VOLNAMEHASH
) {
3147 if ((code
= UnhashVolname(ctx
, blockindex
, VlEntry
))) {
3148 if (code
!= VL_NOENT
)
3151 HashVolname(ctx
, blockindex
, VlEntry
);
3154 if (updateentry
->Mask
& VLUPDATE_FLAGS
) {
3155 VlEntry
->flags
= updateentry
->flags
;
3157 if (updateentry
->Mask
& VLUPDATE_CLONEID
) {
3158 VlEntry
->cloneId
= updateentry
->cloneId
;
3160 if (updateentry
->Mask
& VLUPDATE_RWID
) {
3161 if ((code
= UnhashVolid(ctx
, RWVOL
, blockindex
, VlEntry
))) {
3162 if (code
!= VL_NOENT
)
3165 VlEntry
->volumeId
[RWVOL
] = updateentry
->spares3
; /* rw id */
3166 if ((code
= HashVolid(ctx
, RWVOL
, blockindex
, VlEntry
)))
3169 if (updateentry
->Mask
& VLUPDATE_READONLYID
) {
3170 if ((code
= UnhashVolid(ctx
, ROVOL
, blockindex
, VlEntry
))) {
3171 if (code
!= VL_NOENT
)
3174 VlEntry
->volumeId
[ROVOL
] = updateentry
->ReadOnlyId
;
3175 if ((code
= HashVolid(ctx
, ROVOL
, blockindex
, VlEntry
)))
3178 if (updateentry
->Mask
& VLUPDATE_BACKUPID
) {
3179 if ((code
= UnhashVolid(ctx
, BACKVOL
, blockindex
, VlEntry
))) {
3180 if (code
!= VL_NOENT
)
3183 VlEntry
->volumeId
[BACKVOL
] = updateentry
->BackupId
;
3184 if ((code
= HashVolid(ctx
, BACKVOL
, blockindex
, VlEntry
)))
3187 if (updateentry
->Mask
& VLUPDATE_REPSITES
) {
3188 if (updateentry
->nModifiedRepsites
<= 0
3189 || updateentry
->nModifiedRepsites
> OMAXNSERVERS
)
3190 return VL_BADSERVER
;
3191 for (i
= 0; i
< updateentry
->nModifiedRepsites
; i
++) {
3192 /* if (updateentry->RepsitesTargetServer[i] < 0 || updateentry->RepsitesTargetServer[i] > MAXSERVERID)
3193 return VL_BADSERVER; */
3194 if (updateentry
->RepsitesTargetPart
[i
] < 0
3195 || updateentry
->RepsitesTargetPart
[i
] > MAXPARTITIONID
)
3196 return VL_BADPARTITION
;
3197 if (updateentry
->RepsitesMask
[i
] & VLUPDATE_REPS_DELETE
) {
3199 repsite_exists(VlEntry
,
3200 IpAddrToRelAddr(ctx
, updateentry
->
3201 RepsitesTargetServer
[i
],
3203 updateentry
->RepsitesTargetPart
[i
])) !=
3205 repsite_compress(VlEntry
, j
);
3207 return VL_NOREPSERVER
;
3209 if (updateentry
->RepsitesMask
[i
] & VLUPDATE_REPS_ADD
) {
3210 /* if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
3211 return VL_BADSERVER; */
3212 if (updateentry
->RepsitesNewPart
[i
] < 0
3213 || updateentry
->RepsitesNewPart
[i
] > MAXPARTITIONID
)
3214 return VL_BADPARTITION
;
3217 IpAddrToRelAddr(ctx
, updateentry
->RepsitesNewServer
[i
], 1),
3218 updateentry
->RepsitesNewPart
[i
]) != -1)
3219 return VL_DUPREPSERVER
;
3221 VlEntry
->serverNumber
[j
] != BADSERVERID
3222 && j
< OMAXNSERVERS
; j
++);
3223 if (j
>= OMAXNSERVERS
)
3226 IpAddrToRelAddr(ctx
, updateentry
->RepsitesNewServer
[i
],
3228 return VL_BADSERVER
;
3229 VlEntry
->serverNumber
[j
] = serverindex
;
3230 VlEntry
->serverPartition
[j
] = updateentry
->RepsitesNewPart
[i
];
3231 if (updateentry
->RepsitesNewFlags
[i
] < 0
3232 || updateentry
->RepsitesNewFlags
[i
] > MAXSERVERFLAG
)
3233 return VL_BADSERVERFLAG
;
3234 VlEntry
->serverFlags
[j
] = updateentry
->RepsitesNewFlags
[i
];
3236 if (updateentry
->RepsitesMask
[i
] & VLUPDATE_REPS_MODSERV
) {
3237 /*n if (updateentry->RepsitesNewServer[i] < 0 || updateentry->RepsitesNewServer[i] > MAXSERVERID)
3238 return VL_BADSERVER; */
3240 repsite_exists(VlEntry
,
3241 IpAddrToRelAddr(ctx
, updateentry
->
3242 RepsitesTargetServer
[i
],
3244 updateentry
->RepsitesTargetPart
[i
])) !=
3246 VlEntry
->serverNumber
[j
] =
3247 IpAddrToRelAddr(ctx
, updateentry
->RepsitesNewServer
[i
],
3250 return VL_NOREPSERVER
;
3252 if (updateentry
->RepsitesMask
[i
] & VLUPDATE_REPS_MODPART
) {
3253 if (updateentry
->RepsitesNewPart
[i
] < 0
3254 || updateentry
->RepsitesNewPart
[i
] > MAXPARTITIONID
)
3255 return VL_BADPARTITION
;
3257 repsite_exists(VlEntry
,
3258 IpAddrToRelAddr(ctx
, updateentry
->
3259 RepsitesTargetServer
[i
],
3261 updateentry
->RepsitesTargetPart
[i
])) !=
3263 VlEntry
->serverPartition
[j
] =
3264 updateentry
->RepsitesNewPart
[i
];
3266 return VL_NOREPSERVER
;
3268 if (updateentry
->RepsitesMask
[i
] & VLUPDATE_REPS_MODFLAG
) {
3270 repsite_exists(VlEntry
,
3271 IpAddrToRelAddr(ctx
, updateentry
->
3272 RepsitesTargetServer
[i
],
3274 updateentry
->RepsitesTargetPart
[i
])) !=
3276 if (updateentry
->RepsitesNewFlags
[i
] < 0
3277 || updateentry
->RepsitesNewFlags
[i
] > MAXSERVERFLAG
)
3278 return VL_BADSERVERFLAG
;
3279 VlEntry
->serverFlags
[j
] =
3280 updateentry
->RepsitesNewFlags
[i
];
3282 return VL_NOREPSERVER
;
3290 /* Check if the specified [server,partition] entry is found in the vldb
3291 * entry's repsite table; it's offset in the table is returned, if it's
3294 repsite_exists(struct nvlentry
*VlEntry
, int server
, int partition
)
3298 for (i
= 0; VlEntry
->serverNumber
[i
] != BADSERVERID
&& i
< OMAXNSERVERS
;
3300 if ((VlEntry
->serverNumber
[i
] == server
)
3301 && (VlEntry
->serverPartition
[i
] == partition
))
3309 /* Repsite table compression: used when deleting a repsite entry so that
3310 * all active repsite entries are on the top of the table. */
3312 repsite_compress(struct nvlentry
*VlEntry
, int offset
)
3314 int repsite_offset
= offset
;
3316 VlEntry
->serverNumber
[repsite_offset
] != BADSERVERID
3317 && repsite_offset
< OMAXNSERVERS
- 1; repsite_offset
++) {
3318 VlEntry
->serverNumber
[repsite_offset
] =
3319 VlEntry
->serverNumber
[repsite_offset
+ 1];
3320 VlEntry
->serverPartition
[repsite_offset
] =
3321 VlEntry
->serverPartition
[repsite_offset
+ 1];
3322 VlEntry
->serverFlags
[repsite_offset
] =
3323 VlEntry
->serverFlags
[repsite_offset
+ 1];
3325 VlEntry
->serverNumber
[repsite_offset
] = BADSERVERID
;
3329 /* Convert from the internal (compacted) vldb entry to the external
3330 * representation used by the interface. */
3332 vlentry_to_vldbentry(struct vl_ctx
*ctx
, struct nvlentry
*VlEntry
,
3333 struct vldbentry
*VldbEntry
)
3336 struct extentaddr
*exp
;
3338 memset(VldbEntry
, 0, sizeof(struct vldbentry
));
3339 strncpy(VldbEntry
->name
, VlEntry
->name
, sizeof(VldbEntry
->name
));
3340 for (i
= 0; i
< OMAXNSERVERS
; i
++) {
3341 if (VlEntry
->serverNumber
[i
] == BADSERVERID
)
3343 code
= multiHomedExtent(ctx
, VlEntry
->serverNumber
[i
], &exp
);
3347 /* For now return the first ip address back */
3348 for (j
= 0; j
< VL_MAXIPADDRS_PERMH
; j
++) {
3349 if (exp
->ex_addrs
[j
]) {
3350 VldbEntry
->serverNumber
[i
] = ntohl(exp
->ex_addrs
[j
]);
3355 VldbEntry
->serverNumber
[i
] =
3356 ctx
->hostaddress
[VlEntry
->serverNumber
[i
]];
3357 VldbEntry
->serverPartition
[i
] = VlEntry
->serverPartition
[i
];
3358 VldbEntry
->serverFlags
[i
] = VlEntry
->serverFlags
[i
];
3360 VldbEntry
->nServers
= i
;
3361 for (i
= 0; i
< MAXTYPES
; i
++)
3362 VldbEntry
->volumeId
[i
] = VlEntry
->volumeId
[i
];
3363 VldbEntry
->cloneId
= VlEntry
->cloneId
;
3364 VldbEntry
->flags
= VlEntry
->flags
;
3370 /* Convert from the internal (compacted) vldb entry to the external
3371 * representation used by the interface. */
3373 vlentry_to_nvldbentry(struct vl_ctx
*ctx
, struct nvlentry
*VlEntry
,
3374 struct nvldbentry
*VldbEntry
)
3377 struct extentaddr
*exp
;
3379 memset(VldbEntry
, 0, sizeof(struct nvldbentry
));
3380 strncpy(VldbEntry
->name
, VlEntry
->name
, sizeof(VldbEntry
->name
));
3381 for (i
= 0; i
< NMAXNSERVERS
; i
++) {
3382 if (VlEntry
->serverNumber
[i
] == BADSERVERID
)
3384 code
= multiHomedExtent(ctx
, VlEntry
->serverNumber
[i
], &exp
);
3389 /* For now return the first ip address back */
3390 for (j
= 0; j
< VL_MAXIPADDRS_PERMH
; j
++) {
3391 if (exp
->ex_addrs
[j
]) {
3392 VldbEntry
->serverNumber
[i
] = ntohl(exp
->ex_addrs
[j
]);
3397 VldbEntry
->serverNumber
[i
] =
3398 ctx
->hostaddress
[VlEntry
->serverNumber
[i
]];
3399 VldbEntry
->serverPartition
[i
] = VlEntry
->serverPartition
[i
];
3400 VldbEntry
->serverFlags
[i
] = VlEntry
->serverFlags
[i
];
3402 VldbEntry
->nServers
= i
;
3403 for (i
= 0; i
< MAXTYPES
; i
++)
3404 VldbEntry
->volumeId
[i
] = VlEntry
->volumeId
[i
];
3405 VldbEntry
->cloneId
= VlEntry
->cloneId
;
3406 VldbEntry
->flags
= VlEntry
->flags
;
3412 vlentry_to_uvldbentry(struct vl_ctx
*ctx
, struct nvlentry
*VlEntry
,
3413 struct uvldbentry
*VldbEntry
)
3416 struct extentaddr
*exp
;
3418 memset(VldbEntry
, 0, sizeof(struct uvldbentry
));
3419 strncpy(VldbEntry
->name
, VlEntry
->name
, sizeof(VldbEntry
->name
));
3420 for (i
= 0; i
< NMAXNSERVERS
; i
++) {
3421 if (VlEntry
->serverNumber
[i
] == BADSERVERID
)
3423 VldbEntry
->serverFlags
[i
] = VlEntry
->serverFlags
[i
];
3424 VldbEntry
->serverUnique
[i
] = 0;
3425 code
= multiHomedExtent(ctx
, VlEntry
->serverNumber
[i
], &exp
);
3432 tuuid
= exp
->ex_hostuuid
;
3433 afs_ntohuuid(&tuuid
);
3434 VldbEntry
->serverFlags
[i
] |= VLSF_UUID
;
3435 VldbEntry
->serverNumber
[i
] = tuuid
;
3436 VldbEntry
->serverUnique
[i
] = ntohl(exp
->ex_uniquifier
);
3438 VldbEntry
->serverNumber
[i
].time_low
=
3439 ctx
->hostaddress
[VlEntry
->serverNumber
[i
]];
3441 VldbEntry
->serverPartition
[i
] = VlEntry
->serverPartition
[i
];
3444 VldbEntry
->nServers
= i
;
3445 for (i
= 0; i
< MAXTYPES
; i
++)
3446 VldbEntry
->volumeId
[i
] = VlEntry
->volumeId
[i
];
3447 VldbEntry
->cloneId
= VlEntry
->cloneId
;
3448 VldbEntry
->flags
= VlEntry
->flags
;
3453 #define LEGALCHARS ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
3456 /* Verify that the volname is a valid volume name. */
3458 InvalidVolname(char *volname
)
3464 slen
= strlen(volname
);
3465 if (slen
>= VL_MAXNAMELEN
)
3467 return (slen
!= strspn(volname
, map
));
3471 /* Verify that the given volume type is valid. */
3473 InvalidVoltype(afs_int32 voltype
)
3475 if (voltype
!= RWVOL
&& voltype
!= ROVOL
&& voltype
!= BACKVOL
)
3482 InvalidOperation(afs_int32 voloper
)
3484 if (voloper
!= VLOP_MOVE
&& voloper
!= VLOP_RELEASE
3485 && voloper
!= VLOP_BACKUP
&& voloper
!= VLOP_DELETE
3486 && voloper
!= VLOP_DUMP
)
3492 InvalidReleasetype(afs_int32 releasetype
)
3494 if ((releasetype
& LOCKREL_TIMESTAMP
) || (releasetype
& LOCKREL_OPCODE
)
3495 || (releasetype
& LOCKREL_AFSID
))
3501 IpAddrToRelAddr(struct vl_ctx
*ctx
, afs_uint32 ipaddr
, int create
)
3505 struct extentaddr
*exp
;
3507 for (i
= 0; i
<= MAXSERVERID
; i
++) {
3508 if (ctx
->hostaddress
[i
] == ipaddr
)
3510 code
= multiHomedExtent(ctx
, i
, &exp
);
3514 for (j
= 0; j
< VL_MAXIPADDRS_PERMH
; j
++) {
3515 if (exp
->ex_addrs
[j
] && (ntohl(exp
->ex_addrs
[j
]) == ipaddr
)) {
3522 /* allocate the new server a server id pronto */
3524 for (i
= 0; i
<= MAXSERVERID
; i
++) {
3525 if (ctx
->cheader
->IpMappedAddr
[i
] == 0) {
3526 ctx
->cheader
->IpMappedAddr
[i
] = htonl(ipaddr
);
3529 DOFFSET(0, ctx
->cheader
, &ctx
->cheader
->IpMappedAddr
[i
]),
3530 (char *)&ctx
->cheader
->IpMappedAddr
[i
],
3532 ctx
->hostaddress
[i
] = ipaddr
;
3543 ChangeIPAddr(struct vl_ctx
*ctx
, afs_uint32 ipaddr1
, afs_uint32 ipaddr2
)
3547 struct extentaddr
*exp
= NULL
;
3551 afs_int32 blockindex
, count
;
3553 struct nvlentry tentry
;
3554 int ipaddr1_id
= -1, ipaddr2_id
= -1;
3558 /* Don't let addr change to 255.*.*.* : Causes internal error below */
3559 if ((ipaddr2
& 0xff000000) == 0xff000000)
3560 return (VL_BADSERVER
);
3562 /* If we are removing an address, ip1 will be -1 and ip2 will be
3563 * the original address. This prevents an older revision vlserver
3564 * from removing the IP address (won't find server 0xfffffff in
3565 * the VLDB). An older revision vlserver does not have the check
3566 * to see if any volumes exist on the server being removed.
3568 if (ipaddr1
== 0xffffffff) {
3573 for (i
= 0; i
<= MAXSERVERID
; i
++) {
3574 struct extentaddr
*texp
= NULL
;
3577 code
= multiHomedExtentBase(ctx
, i
, &texp
, &tbase
);
3582 for (mhidx
= 0; mhidx
< VL_MAXIPADDRS_PERMH
; mhidx
++) {
3583 if (!texp
->ex_addrs
[mhidx
])
3585 if (ntohl(texp
->ex_addrs
[mhidx
]) == ipaddr1
) {
3590 if (ipaddr2
!= 0 && ntohl(texp
->ex_addrs
[mhidx
]) == ipaddr2
) {
3595 if (ctx
->hostaddress
[i
] == ipaddr1
) {
3600 if (ipaddr2
!= 0 && ctx
->hostaddress
[i
] == ipaddr2
) {
3605 if (ipaddr1_id
>= 0 && (ipaddr2
== 0 || ipaddr2_id
>= 0)) {
3606 /* we've either found both IPs already in the VLDB, or we found
3607 * ipaddr1, and we're not going to find ipaddr2 because it's 0 */
3612 if (ipaddr1_id
< 0) {
3613 return VL_NOENT
; /* not found */
3616 if (ipaddr2_id
>= 0 && ipaddr2_id
!= ipaddr1_id
) {
3617 char buf1
[16], buf2
[16];
3618 VLog(0, ("Cannot change IP address from %s to %s because the latter "
3619 "is in use by server id %d\n",
3620 afs_inet_ntoa_r(htonl(ipaddr1
), buf1
),
3621 afs_inet_ntoa_r(htonl(ipaddr2
), buf2
),
3623 return VL_MULTIPADDR
;
3626 /* If we are removing a server entry, a volume cannot
3627 * exist on the server. If one does, don't remove the
3628 * server entry: return error "volume entry exists".
3631 for (blockindex
= NextEntry(ctx
, 0, &tentry
, &count
); blockindex
;
3632 blockindex
= NextEntry(ctx
, blockindex
, &tentry
, &count
)) {
3633 if (++pollcount
> 50) {
3634 #ifndef AFS_PTHREAD_ENV
3639 for (j
= 0; j
< NMAXNSERVERS
; j
++) {
3640 if (tentry
.serverNumber
[j
] == BADSERVERID
)
3642 if (tentry
.serverNumber
[j
] == ipaddr1_id
) {
3648 /* Do not allow changing addresses in multi-homed entries.
3649 Older versions of this RPC would silently "downgrade" mh entries
3650 to single-homed entries and orphan the mh enties. */
3652 append_addr(addrbuf1
, ipaddr1
, sizeof(addrbuf1
));
3653 VLog(0, ("Refusing to change address %s in multi-homed entry; "
3654 "use RegisterAddrs instead.\n", addrbuf1
));
3655 return VL_NOENT
; /* single-homed entry not found */
3658 /* Log a message saying we are changing/removing an IP address */
3660 ("The following IP address is being %s:\n",
3661 (ipaddr2
? "changed" : "removed")));
3662 addrbuf1
[0] = addrbuf2
[0] = '\0';
3664 for (mhidx
= 0; mhidx
< VL_MAXIPADDRS_PERMH
; mhidx
++) {
3665 if (!exp
->ex_addrs
[mhidx
])
3668 strlcat(addrbuf1
, " ", sizeof(addrbuf1
));
3669 append_addr(addrbuf1
, ntohl(exp
->ex_addrs
[mhidx
]), sizeof(addrbuf1
));
3672 append_addr(addrbuf1
, ipaddr1
, sizeof(addrbuf1
));
3675 append_addr(addrbuf2
, ipaddr2
, sizeof(addrbuf2
));
3677 VLog(0, (" entry %d: [%s] -> [%s]\n", ipaddr1_id
, addrbuf1
, addrbuf2
));
3679 /* Change the registered uuuid addresses */
3680 if (exp
&& base
!= -1) {
3681 memset(&tuuid
, 0, sizeof(afsUUID
));
3682 afs_htonuuid(&tuuid
);
3683 exp
->ex_hostuuid
= tuuid
;
3686 DOFFSET(ntohl(ctx
->ex_addr
[0]->ex_contaddrs
[base
]),
3687 (char *)ctx
->ex_addr
[base
], (char *)exp
),
3688 (char *)&tuuid
, sizeof(tuuid
));
3693 /* Now change the host address entry */
3694 ctx
->cheader
->IpMappedAddr
[ipaddr1_id
] = htonl(ipaddr2
);
3696 vlwrite(ctx
->trans
, DOFFSET(0, ctx
->cheader
, &ctx
->cheader
->IpMappedAddr
[ipaddr1_id
]),
3698 &ctx
->cheader
->IpMappedAddr
[ipaddr1_id
], sizeof(afs_int32
));
3699 ctx
->hostaddress
[ipaddr1_id
] = ipaddr2
;
3706 /* see if the vlserver is back yet */
3708 SVL_ProbeServer(struct rx_call
*rxcall
)