2 * Copyright (c) 2007, Hartmut Reuter,
3 * RZG, Max-Planck-Institut f. Plasmaphysik.
11 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
12 #include <sys/types.h>
14 #ifdef AFS_PTHREAD_ENV
16 #else /* AFS_PTHREAD_ENV */
17 #include <afs/assert.h>
18 #endif /* AFS_PTHREAD_ENV */
40 #include <afs/afsint.h>
44 #include <afs/afssyscalls.h>
48 #include "partition.h"
49 #include "viceinode.h"
51 #ifdef AFS_RXOSD_SUPPORT
54 #include "../vol/vol_osd_prototypes.h"
59 #define CHANGEPARENT 4
61 #define NAMEI_VNODEMASK 0x03ffffff
62 #define NAMEI_TAGMASK 0x7
63 #define NAMEI_TAGSHIFT 26
64 #define NAMEI_UNIQMASK 0xffffffff
65 #define NAMEI_UNIQSHIFT 32
74 struct rx_call * call;
80 ExtractVnodes(struct Msg *m, Volume *vol, afs_int32 class,
81 struct VnodeExtract **list,
82 afs_int32 *length, afs_uint32 where,
83 struct VnodeDiskObject *vd,
84 afs_int32 *parent, struct VnodeDiskObject *parentvd)
87 char buf[SIZEOF_LARGEDISKVNODE];
88 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)&buf;
90 StreamHandle_t *stream = 0;
91 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
92 struct VnodeExtract *e;
100 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
102 sprintf(m->line, "Couldn't open %s Index of volume %u\n",
103 class ? "small":"large", V_id(vol));
104 rx_Write(m->call, m->line, strlen(m->line));
108 size = FDH_SIZE(fdP);
109 *list = (struct VnodeExtract *) malloc(size / vcp->diskSize
110 * sizeof(struct VnodeExtract));
115 memset(*list, 0, size / vcp->diskSize * sizeof(struct VnodeExtract));
116 stream = FDH_FDOPEN(fdP, "r");
118 sprintf(m->line, "Couldn't stream open %s Index of volume %u\n",
119 class ? "small":"large", V_id(vol));
120 rx_Write(m->call, m->line, strlen(m->line));
124 code = STREAM_SEEK(stream, vcp->diskSize, 0);
128 offset = vcp->diskSize;
130 while (!STREAM_EOF(stream)) {
131 afs_int32 vN = (offset >> (vcp->logSize -1)) - 1 + class;
132 if (STREAM_READ(vnode, vcp->diskSize, 1, stream) == 1) {
133 if (vnode->type != vNull) {
135 e->parent = vnode->parent;
136 if (vN == where && class == vLarge) {
137 memcpy(vd, vnode, vcp->diskSize);
138 *parent = vnode->parent;
142 offset += vcp->diskSize;
145 *length = (e - *list);
146 if (class == vLarge) {
148 offset = (*parent + 1 - class) << (vcp->logSize -1);
149 code = STREAM_SEEK(stream, offset, 0);
150 if (STREAM_READ(vnode, vcp->diskSize, 1, stream) == 1)
151 memcpy(parentvd, vnode, vcp->diskSize);
155 sprintf(m->line, "SplitVolume: extract didn't see directory %u\n", where);
156 rx_Write(m->call, m->line, strlen(m->line));
161 sprintf(m->line, "Volume %u has %u %s vnodes in volume %uu\n",
162 V_parentId(vol), *length, class? "small":"large");
163 rx_Write(m->call, m->line, strlen(m->line));
168 STREAM_CLOSE(stream);
179 FindVnodes(struct Msg *m, afs_uint32 where,
180 struct VnodeExtract *list, afs_int32 length,
181 struct VnodeExtract *dlist, afs_int32 dlength,
182 afs_int32 *needed, afs_int32 class)
184 afs_int32 i, j, found = 0;
185 afs_int32 parent = 0;
188 for (i=0; i<length; i++) {
189 if (list[i].vN == where) { /* dir to be replaced by mount point */
190 list[i].flag |= NEEDED;
191 parent = list[i].parent;
195 if (list[i].parent == where) { /* all 1st generation children */
196 list[i].flag |= (NEEDED + CHANGEPARENT);
200 if (list[0].vN & 1) { /* only for directories */
203 "SplitVolume: directory %u where to start new volume not found\n",
205 rx_Write(m->call, m->line, strlen(m->line));
209 for (i=0; i<length; i++) {
210 if (list[i].vN == parent) { /* dir where to create mount point */
211 list[i].flag |= PARENT;
217 sprintf(m->line, "SplitVolume: parent directory %u not found\n",
219 rx_Write(m->call, m->line, strlen(m->line));
226 for (i=0; i<dlength; i++) {
227 if (!(dlist[i].flag & NEEDED)) /* dirs to remain in old volume */
229 for (j=0; j<length; j++) {
230 if (list[j].parent == dlist[i].vN && !(list[j].flag & NEEDED)) {
231 list[j].flag |= NEEDED;
239 sprintf(m->line, "%u %s vnodes will go into the new volume\n",
240 *needed, class ? "small" : "large");
241 rx_Write(m->call, m->line, strlen(m->line));
247 copyDir(struct Msg *m, IHandle_t *inh, IHandle_t *outh)
249 FdHandle_t *infdP, *outfdP;
253 infdP = IH_OPEN(inh);
255 sprintf(m->line, "Couldn't open input directory %u.%u.%u\n",
256 infdP->fd_ih->ih_vid,
257 (afs_uint32)(infdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
258 (afs_uint32)(infdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
259 rx_Write(m->call, m->line, strlen(m->line));
262 outfdP = IH_OPEN(outh);
264 sprintf(m->line, "Couldn't open output directory %u.%u.%u\n",
265 outfdP->fd_ih->ih_vid,
266 (afs_uint32)(outfdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
267 (afs_uint32)(outfdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
268 rx_Write(m->call, m->line, strlen(m->line));
269 FDH_REALLYCLOSE(infdP);
273 FDH_SEEK(infdP, 0, 0);
274 FDH_SEEK(outfdP, 0, 0);
275 size = FDH_SIZE(infdP);
278 tlen = size > 2048 ? 2048 : size;
279 if (FDH_READ(infdP, tbuf, tlen) != tlen) {
280 sprintf(m->line, "Couldn't read directory %u.%u.%u\n",
281 infdP->fd_ih->ih_vid,
282 (afs_uint32)(infdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
283 (afs_uint32)(infdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
284 rx_Write(m->call, m->line, strlen(m->line));
285 FDH_REALLYCLOSE(infdP);
286 FDH_REALLYCLOSE(outfdP);
290 if (FDH_WRITE(outfdP, tbuf, tlen) != tlen) {
291 sprintf(m->line, "Couldn't write directory %u.%u.%u\n",
292 outfdP->fd_ih->ih_vid,
293 (afs_uint32)(outfdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
294 (afs_uint32)(outfdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
295 rx_Write(m->call, m->line, strlen(m->line));
296 FDH_REALLYCLOSE(infdP);
297 FDH_REALLYCLOSE(outfdP);
305 FDH_REALLYCLOSE(infdP);
309 afs_int32 copyVnodes(struct Msg *m, Volume *vol, Volume *newvol,
311 struct VnodeExtract *list, afs_int32 length,
312 afs_int32 where, afs_uint64 *blocks,
313 struct VnodeDiskObject *parVnode)
315 afs_int32 i, code = 0;
316 char buf[SIZEOF_LARGEDISKVNODE];
317 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)&buf;
319 FdHandle_t *newfdP = 0;
320 StreamHandle_t *newstream = 0;
321 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
322 struct VnodeExtract *e;
327 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
329 Log("Couldn't open %s Index of volume %u\n",
330 class ? "small":"large", V_id(vol));
334 newfdP = IH_OPEN(newvol->vnodeIndex[class].handle);
336 Log("Couldn't open %s Index of volume %u\n",
337 class ? "small":"large", V_id(newvol));
341 size = FDH_SIZE(fdP);
343 for (i=0; i<length; i++) {
347 offset = (e->vN + 1 - class) << (vcp->logSize -1);
348 if (FDH_SEEK(fdP, offset, 0) != offset
349 || FDH_READ(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
350 Log("Couldn't read in %s Index of volume %u at offset\n",
351 class ? "small":"large", V_id(vol), offset);
355 if (e->flag & PARENT) {
357 * do a preventive copy on write for later update
361 FdHandle_t *infdP = 0;
362 FdHandle_t *outfdP = 0;
363 char *tbuf = malloc(2048);
364 #if defined(NEARINODE_HINT) && !defined(AFS_NAMEI_ENV)
366 V_pref(vol,nearInode)
369 newino = IH_CREATE(V_linkHandle(vol), V_device(vol),
370 VPartitionPath(V_partition(vol)),
371 nearInode, V_parentId(vol),
372 e->vN, vnode->uniquifier,
374 IH_INIT(newh, V_device(vol), V_parentId(vol), newino);
375 ino = VNDISK_GET_INO(vnode);
376 IH_INIT(h, V_device(vol), V_parentId(vol), ino);
377 code = copyDir(m, h, newh);
380 /* Now update the vnode and write it back to disk */
381 VNDISK_SET_INO(vnode, newino);
383 if (FDH_SEEK(fdP, offset, 0) != offset
384 || FDH_WRITE(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
385 Log("Couldn't write in %s Index of volume %u at offset\n",
386 class ? "small":"large", V_id(vol), offset);
390 memcpy(parVnode, vnode, sizeof(struct VnodeDiskObject));
392 if (e->flag & NEEDED && e->vN != where) {
393 VNDISK_GET_LEN(size, vnode);
394 *blocks += (size + 0x3ff) >> 10;
395 ino = VNDISK_GET_INO(vnode);
399 #if defined(NEARINODE_HINT) && !defined(AFS_NAMEI_ENV)
400 V_pref(vol,nearInode)
402 IH_INIT(h, vol->device, V_parentId(vol), ino);
403 if (e->parent == where)
405 newino = IH_CREATE(V_linkHandle(newvol), V_device(newvol),
406 VPartitionPath(V_partition(newvol)),
407 nearInode, V_parentId(newvol),
408 e->vN, vnode->uniquifier,
410 if (!VALID_INO(newino)) {
411 Log("IH_CREATE failed for %u.%u.%u\n",
412 V_id(newvol), e->vN, vnode->uniquifier);
417 IH_INIT(newh, newvol->device, V_parentId(newvol), newino);
418 code = namei_replace_file_by_hardlink(newh, h);
419 VNDISK_SET_INO(vnode, newino);
420 #ifdef AFS_RXOSD_SUPPORT
422 code = osd_split_objects(vol, newvol, vnode, e->vN);
423 #endif /* AFS_RXOSD_SUPPORT */
427 if (e->flag & CHANGEPARENT)
428 vnode->parent = 1; /* in new root-directory */
430 if (FDH_SEEK(newfdP, offset, 0) != offset
431 || FDH_WRITE(newfdP, vnode, vcp->diskSize) != vcp->diskSize) {
432 Log("Couldn't write in %s Index of volume %u to offset\n",
433 class ? "small":"large", V_id(newvol),
442 * Now copy the root directory from old to new volume
444 if (class == vLarge) {
446 char buf2[SIZEOF_LARGEDISKVNODE];
447 struct VnodeDiskObject *vnode2 = (struct VnodeDiskObject *)&buf2;
448 afs_uint64 newoffset;
450 newoffset = vcp->diskSize;
451 if (FDH_SEEK(newfdP, newoffset, 0) != newoffset
452 || FDH_READ(newfdP, vnode2, vcp->diskSize) != vcp->diskSize) {
453 Log("splitvolume: couldn't read in large Index of new volume %u at offset %u\n",
454 V_id(newvol), vcp->diskSize);
458 offset = (where + 1 - class) << (vcp->logSize -1);
459 if (FDH_SEEK(fdP, offset, 0) != offset
460 || FDH_READ(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
461 Log("Couldn't read in large Index of old volume %u at offset\n",
466 VNDISK_GET_LEN(size, vnode);
467 *blocks += (size + 0x3ff) >> 10;
468 ino = VNDISK_GET_INO(vnode);
469 IH_INIT(h, vol->device, V_parentId(vol), ino);
470 newino = VNDISK_GET_INO(vnode2);
471 IH_INIT(newh, newvol->device, V_parentId(newvol), newino);
472 code = copyDir(m, h, newh);
474 Log("splitvolume: copyDir failed for new root from %u.u.u to %u.1.1\n",
475 V_id(vol), where, vnode->uniquifier, V_id(newvol));
479 VNDISK_SET_INO(vnode, newino);
480 vnode->uniquifier = 1;
482 vnode->parent = vnode2->parent;
483 vnode->serverModifyTime = vnode2->serverModifyTime;
484 if (FDH_SEEK(newfdP, newoffset, 0) != newoffset
485 || FDH_WRITE(newfdP, vnode, vcp->diskSize) != vcp->diskSize) {
486 Log("splitvolume: couldn't write in large Index of %u at offset %u\n",
487 V_id(newvol), vcp->diskSize);
500 findName(Volume *vol, struct VnodeDiskObject *vd, afs_uint32 vN,
501 afs_uint32 un, char *name,afs_int32 length)
507 ino = VNDISK_GET_INO(vd);
508 SetSalvageDirHandle(&dir, V_id(vol), V_device(vol), ino);
510 code = InverseLookup(&dir, vN, un, name, length);
516 createMountpoint(Volume *vol, Volume *newvol, struct VnodeDiskObject *parent,
517 afs_uint32 vN, struct VnodeDiskObject *vd, char *name)
523 struct VnodeDiskObject vnode;
524 FdHandle_t *fdP, *fdP2;
525 afs_uint64 offset, size;
526 afs_int32 class = vSmall;
527 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
534 TM_GetTimeOfDay(&now, 0);
535 fdP = IH_OPEN(vol->vnodeIndex[vSmall].handle);
537 Log("split volume: error opening small vnode index of %u\n", V_id(vol));
540 offset = vcp->diskSize;
541 if (FDH_SEEK(fdP, offset, 0) != offset) {
542 Log("split volume: error seeking in small vnode index of %u\n", V_id(vol));
546 if (FDH_READ(fdP, &vnode, vcp->diskSize) != vcp->diskSize)
548 if (vnode.type == vNull)
550 offset += vcp->diskSize;
552 memset(&vnode, 0, sizeof(vnode));
553 vnode.type = vSymlink;
554 V_nextVnodeUnique(vol)++;
555 vnode.uniquifier = V_nextVnodeUnique(vol);
556 vnode.author = vd->author;
557 vnode.owner = vd->owner;
558 vnode.group = vd->group;
559 vnode.modeBits = 0644;
560 vnode.unixModifyTime = now.tv_sec;
561 vnode.serverModifyTime = now.tv_sec;
562 vnode.dataVersion = 1;
566 newvN = (offset >> (VnodeClassInfo[class].logSize - 1)) - 1 + class;
567 #if defined(NEARINODE_HINT) && !defined(AFS_NAMEI_ENV)
568 V_pref(vol,nearInode)
570 newino = IH_CREATE(V_linkHandle(vol), V_device(vol),
571 VPartitionPath(V_partition(vol)), nearInode,
572 V_parentId(vol), newvN, vnode.uniquifier, 1);
574 IH_INIT(h, V_device(vol), V_parentId(vol), newino);
577 Log("split volume: couldn't open inode for mountpoint %u.%u.%u\n",
578 V_id(vol), newvN, vnode.uniquifier);
581 FDH_SEEK(fdP2, 0, 0);
582 sprintf(symlink, "#%s", V_name(newvol));
583 size = strlen(symlink) + 1;
584 if (FDH_WRITE(fdP2, symlink, size) != size) {
585 Log("split volume: couldn't write mountpoint %u.%u.%u\n",
586 V_id(vol), newvN, vnode.uniquifier);
589 FDH_REALLYCLOSE(fdP2);
591 VNDISK_SET_INO(&vnode, newino);
592 VNDISK_SET_LEN(&vnode, size);
593 #ifndef AFS_RXOSD_SUPPORT
594 vnode.vnodeMagic = SMALLVNODEMAGIC;
596 if (FDH_SEEK(fdP, offset, 0) != offset
597 || FDH_WRITE(fdP, &vnode, vcp->diskSize) != vcp->diskSize) {
598 Log("split volume: couldn't write vnode for mountpoint %u.%u.%u\n",
599 V_id(vol), newvN, vnode.uniquifier);
602 FDH_REALLYCLOSE(fdP);
604 fid.Volume = V_id(vol);
606 fid.Unique = vnode.uniquifier;
609 * Now update the parent directory.
612 ino = VNDISK_GET_INO(parent);
613 SetSalvageDirHandle(&dir, V_id(vol), V_device(vol), ino);
615 code = Delete(&dir, name);
617 Log("splitvolume: couldn't delete directory entry for %s in %u.%u.%u, code = %d\n",
618 name, V_id(vol), vN, parent->uniquifier, code);
621 code = Create(&dir, name, &fid);
625 vcp = &VnodeClassInfo[class];
626 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
627 offset = (vN + 1 - class) << (vcp->logSize -1);
628 parent->dataVersion++;
629 if (FDH_SEEK(fdP, offset, 0) != offset
630 || FDH_WRITE(fdP, parent, vcp->diskSize) != vcp->diskSize) {
631 Log("split volume: couldn't write vnode for parent directory %u.%u.%u\n",
632 V_id(vol), vN, parent->uniquifier);
635 FDH_REALLYCLOSE(fdP);
640 deleteVnodes(Volume *vol, afs_int32 class,
641 struct VnodeExtract *list, afs_int32 length,
644 afs_int32 i, code = 0;
645 char buf[SIZEOF_LARGEDISKVNODE];
646 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)&buf;
648 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
649 struct VnodeExtract *e;
654 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
656 Log("Couldn't open %s Index of volume %u\n",
657 class ? "small":"large", V_id(vol));
661 size = FDH_SIZE(fdP);
663 for (i=0; i<length; i++) {
665 if (e->flag & NEEDED) {
667 offset = (e->vN + 1 - class) << (vcp->logSize -1);
668 if (FDH_SEEK(fdP, offset, 0) != offset) {
669 Log("Couldn't seek in %s Index of volume %u to offset\n",
670 class ? "small":"large", V_id(vol), offset);
674 if (FDH_READ(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
675 Log("Couldn't read in %s Index of volume %u at offset\n",
676 class ? "small":"large", V_id(vol), offset);
680 VNDISK_GET_LEN(size, vnode);
681 *blocks += (size + 0x3ff) >> 10;
682 ino = VNDISK_GET_INO(vnode);
685 IH_INIT(h, vol->device, V_parentId(vol), ino);
686 IH_DEC(h, ino, V_parentId(vol));
687 #ifdef AFS_RXOSD_SUPPORT
689 code = osdRemove(vol, vnode, e->vN);
690 #endif /* AFS_RXOSD_SUPPORT */
692 memset(vnode, 0, vcp->diskSize);
694 if (FDH_SEEK(fdP, offset, 0) != offset
695 || FDH_WRITE(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
696 Log("Couldn't write in %s Index of volume %u to offset\n",
697 class ? "small":"large", V_id(vol),
709 split_volume(struct rx_call *call, Volume *vol, Volume *newvol,
710 afs_uint32 where, afs_int32 verbose)
713 struct VnodeExtract *dirList = 0;
714 struct VnodeExtract *fileList = 0;
715 afs_uint64 blocks = 0;
716 afs_uint32 filesNeeded, dirsNeeded;
718 char buf[SIZEOF_LARGEDISKVNODE];
719 char buf2[SIZEOF_LARGEDISKVNODE];
720 struct VnodeDiskObject *rootVnode = (struct VnodeDiskObject *)&buf;
721 struct VnodeDiskObject *parVnode = (struct VnodeDiskObject *)&buf2;
726 m = (struct Msg *) malloc(sizeof(struct Msg));
727 memset(m, 0, sizeof(struct Msg));
729 m->verbose = verbose;
732 * First step: planning
734 * Find out which directories will belong to the new volume
739 "1st step: extract vnode essence from large vnode file\n");
740 rx_Write(m->call, m->line, strlen(m->line));
743 code = ExtractVnodes(m, vol, vLarge, &dirList, &dl, where, rootVnode,
747 "ExtractVnodes failed for %u for directories with code %d\n",
749 rx_Write(m->call, m->line, strlen(m->line));
754 sprintf(m->line, "2nd step: look for name of vnode %u in directory %u.%u.%u\n",
755 where, V_id(vol), parent, parVnode->uniquifier);
756 rx_Write(m->call, m->line, strlen(m->line));
758 code = findName(vol, parVnode, where, rootVnode->uniquifier,
762 "splitvolume: could'nt find name of %u in directory %u.%u.%u.\n",
763 where, V_id(vol), parent, parVnode->uniquifier);
764 rx_Write(m->call, m->line, strlen(m->line));
768 sprintf(m->line, "name of %u is %s\n", where, name);
769 rx_Write(m->call, m->line, strlen(m->line));
773 sprintf(m->line, "3rd step: find all directory vnodes belonging to the subtree under %u \"%s\"\n",
775 rx_Write(m->call, m->line, strlen(m->line));
777 code = FindVnodes(m, where, dirList, dl, dirList, dl, &dirsNeeded, 1);
780 "FindVnodes for directories failed with code %d\n", code);
781 rx_Write(m->call, m->line, strlen(m->line));
786 sprintf(m->line, "4th step extract vnode essence from small vnode file\n");
787 rx_Write(m->call, m->line, strlen(m->line));
789 code = ExtractVnodes(m, vol, vSmall, &fileList, &fl, where, 0, 0, 0);
792 "ExtractVnodes failed for %u for files with code %d\n",
794 rx_Write(m->call, m->line, strlen(m->line));
798 sprintf(m->line, "5th step: find all small vnodes belonging to the subtree under %u \"%s\"\n",
800 rx_Write(m->call, m->line, strlen(m->line));
802 FindVnodes(m, where, fileList, fl, dirList, dl, &filesNeeded, 0);
805 * Third step: create hard links for all files needed
809 V_destroyMe(newvol) = DESTROY_ME;
810 V_inService(newvol) = 0;
812 sprintf(m->line, "6th step: create hard links in the AFSIDat tree between files of the old and new volume\n");
813 rx_Write(m->call, m->line, strlen(m->line));
815 code = copyVnodes(m, vol, newvol, 1, fileList, fl, where, &blocks, 0);
817 sprintf(m->line, "copyVnodes for files failed with code %d\n", code);
818 rx_Write(m->call, m->line, strlen(m->line));
823 * Forth step: create hard links for all directories and copy
824 * split directory to new root directory
828 sprintf(m->line, "7th step: create hard links in the AFSIDat tree between directories of the old and new volume and make dir %u to new volume's root directory.\n",
830 rx_Write(m->call, m->line, strlen(m->line));
832 code = copyVnodes(m, vol, newvol, 0, dirList, dl, where, &blocks, parVnode);
834 sprintf(m->line, "copyVnodes for directories failed with code %d\n", code);
835 rx_Write(m->call, m->line, strlen(m->line));
840 * Finalize new volume
844 sprintf(m->line, "8th step: write new volume's metadata to disk\n");
845 rx_Write(m->call, m->line, strlen(m->line));
848 V_diskused(newvol) = blocks;
849 #ifdef AFS_RXOSD_SUPPORT
850 V_osdFlag(newvol) = V_osdFlag(vol);
852 V_filecount(newvol) = filesNeeded + dirsNeeded;
853 V_destroyMe(newvol) = 0;
854 V_maxquota(newvol) = V_maxquota(vol);
855 V_uniquifier(newvol) = V_uniquifier(vol);
856 V_inService(newvol) = 1;
857 VUpdateVolume(&code, newvol);
860 * Sixth step: change directory entry in old volume:
861 * rename old tree and create mount point for new volume.
864 sprintf(m->line, "9th step: create mountpoint \"%s\" for new volume in old volume's directory %u.\n", name, parent);
865 rx_Write(m->call, m->line, strlen(m->line));
868 code = createMountpoint(vol, newvol, parVnode, parent, rootVnode, name);
870 sprintf(m->line, "createMountpoint failed with code %d\n", code);
871 rx_Write(m->call, m->line, strlen(m->line));
875 * Now both volumes should be ready and consistent, but the old volume
876 * contains still the vnodes and data we transferred into the new one.
877 * Delete orphaned vnodes and data.
882 sprintf(m->line, "10th step: delete large vnodes belonging to subtree in the old volume.\n");
883 rx_Write(m->call, m->line, strlen(m->line));
885 deleteVnodes(vol, vLarge, dirList, dl, &blocks);
887 sprintf(m->line, "11th step: delete small vnodes belonging to subtree in the old volume.\n");
888 rx_Write(m->call, m->line, strlen(m->line));
890 deleteVnodes(vol, vSmall, fileList, fl, &blocks);
891 V_diskused(vol) -= blocks;
892 V_filecount(vol) -= (filesNeeded + dirsNeeded + 1);
893 VUpdateVolume(&code, vol);
895 sprintf(m->line, "Finished!\n");
896 rx_Write(m->call, m->line, strlen(m->line));
901 rx_Write(m->call, m->line, 4);