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 */
42 #include <afs/afsint.h>
46 #include <afs/afssyscalls.h>
47 #include <afs/ihandle.h>
48 #include <afs/vnode.h>
49 #include <afs/volume.h>
50 #include <afs/partition.h>
51 #include <afs/viceinode.h>
56 #include "volser_internal.h"
57 #ifdef AFS_RXOSD_SUPPORT
60 #include "../vol/vol_osd_prototypes.h"
65 #define CHANGEPARENT 4
67 #define NAMEI_VNODEMASK 0x03ffffff
68 #define NAMEI_TAGMASK 0x7
69 #define NAMEI_TAGSHIFT 26
70 #define NAMEI_UNIQMASK 0xffffffff
71 #define NAMEI_UNIQSHIFT 32
80 struct rx_call * call;
86 ExtractVnodes(struct Msg *m, Volume *vol, afs_int32 class,
87 struct VnodeExtract **list,
88 afs_uint32 *length, afs_uint32 where,
89 struct VnodeDiskObject *vd,
90 afs_uint32 *parent, struct VnodeDiskObject *parentvd)
93 char buf[SIZEOF_LARGEDISKVNODE];
94 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)&buf;
96 StreamHandle_t *stream = 0;
97 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
98 struct VnodeExtract *e;
106 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
108 sprintf(m->line, "Couldn't open %s Index of volume %u\n",
109 class ? "small":"large", V_id(vol));
110 rx_Write(m->call, m->line, strlen(m->line));
114 size = FDH_SIZE(fdP);
115 *list = (struct VnodeExtract *) malloc(size / vcp->diskSize
116 * sizeof(struct VnodeExtract));
121 memset(*list, 0, size / vcp->diskSize * sizeof(struct VnodeExtract));
122 stream = FDH_FDOPEN(fdP, "r");
124 sprintf(m->line, "Couldn't stream open %s Index of volume %u\n",
125 class ? "small":"large", V_id(vol));
126 rx_Write(m->call, m->line, strlen(m->line));
130 code = STREAM_SEEK(stream, vcp->diskSize, 0);
134 offset = vcp->diskSize;
136 while (!STREAM_EOF(stream)) {
137 afs_int32 vN = (offset >> (vcp->logSize -1)) - 1 + class;
138 if (STREAM_READ(vnode, vcp->diskSize, 1, stream) == 1) {
139 if (vnode->type != vNull) {
141 e->parent = vnode->parent;
142 if (vN == where && class == vLarge) {
143 memcpy(vd, vnode, vcp->diskSize);
144 *parent = vnode->parent;
148 offset += vcp->diskSize;
151 *length = (e - *list);
152 if (class == vLarge) {
154 offset = (*parent + 1 - class) << (vcp->logSize -1);
155 code = STREAM_SEEK(stream, offset, 0);
156 if (STREAM_READ(vnode, vcp->diskSize, 1, stream) == 1)
157 memcpy(parentvd, vnode, vcp->diskSize);
161 sprintf(m->line, "SplitVolume: extract didn't see directory %u\n", where);
162 rx_Write(m->call, m->line, strlen(m->line));
167 sprintf(m->line, "Volume %u has %u %s vnodes in volume %u\n",
168 V_parentId(vol), *length, class? "small":"large",
170 rx_Write(m->call, m->line, strlen(m->line));
175 STREAM_CLOSE(stream);
186 FindVnodes(struct Msg *m, afs_uint32 where,
187 struct VnodeExtract *list, afs_int32 length,
188 struct VnodeExtract *dlist, afs_int32 dlength,
189 afs_uint32 *needed, afs_int32 class)
191 afs_int32 i, j, found = 0;
192 afs_int32 parent = 0;
195 for (i=0; i<length; i++) {
196 if (list[i].vN == where) { /* dir to be replaced by mount point */
197 list[i].flag |= NEEDED;
198 parent = list[i].parent;
202 if (list[i].parent == where) { /* all 1st generation children */
203 list[i].flag |= (NEEDED + CHANGEPARENT);
207 if (list[0].vN & 1) { /* only for directories */
210 "SplitVolume: directory %u where to start new volume not found\n",
212 rx_Write(m->call, m->line, strlen(m->line));
216 for (i=0; i<length; i++) {
217 if (list[i].vN == parent) { /* dir where to create mount point */
218 list[i].flag |= PARENT;
224 sprintf(m->line, "SplitVolume: parent directory %u not found\n",
226 rx_Write(m->call, m->line, strlen(m->line));
233 for (i=0; i<dlength; i++) {
234 if (!(dlist[i].flag & NEEDED)) /* dirs to remain in old volume */
236 for (j=0; j<length; j++) {
237 if (list[j].parent == dlist[i].vN && !(list[j].flag & NEEDED)) {
238 list[j].flag |= NEEDED;
246 sprintf(m->line, "%u %s vnodes will go into the new volume\n",
247 *needed, class ? "small" : "large");
248 rx_Write(m->call, m->line, strlen(m->line));
254 copyDir(struct Msg *m, IHandle_t *inh, IHandle_t *outh)
256 FdHandle_t *infdP, *outfdP;
260 infdP = IH_OPEN(inh);
262 sprintf(m->line, "Couldn't open input directory %u.%u.%u\n",
263 infdP->fd_ih->ih_vid,
264 (afs_uint32)(infdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
265 (afs_uint32)(infdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
266 rx_Write(m->call, m->line, strlen(m->line));
269 outfdP = IH_OPEN(outh);
271 sprintf(m->line, "Couldn't open output directory %u.%u.%u\n",
272 outfdP->fd_ih->ih_vid,
273 (afs_uint32)(outfdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
274 (afs_uint32)(outfdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
275 rx_Write(m->call, m->line, strlen(m->line));
276 FDH_REALLYCLOSE(infdP);
280 FDH_SEEK(infdP, 0, 0);
281 FDH_SEEK(outfdP, 0, 0);
282 size = FDH_SIZE(infdP);
285 tlen = size > 2048 ? 2048 : size;
286 if (FDH_READ(infdP, tbuf, tlen) != tlen) {
287 sprintf(m->line, "Couldn't read directory %u.%u.%u\n",
288 infdP->fd_ih->ih_vid,
289 (afs_uint32)(infdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
290 (afs_uint32)(infdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
291 rx_Write(m->call, m->line, strlen(m->line));
292 FDH_REALLYCLOSE(infdP);
293 FDH_REALLYCLOSE(outfdP);
297 if (FDH_WRITE(outfdP, tbuf, tlen) != tlen) {
298 sprintf(m->line, "Couldn't write directory %u.%u.%u\n",
299 outfdP->fd_ih->ih_vid,
300 (afs_uint32)(outfdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
301 (afs_uint32)(outfdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
302 rx_Write(m->call, m->line, strlen(m->line));
303 FDH_REALLYCLOSE(infdP);
304 FDH_REALLYCLOSE(outfdP);
312 FDH_REALLYCLOSE(infdP);
316 afs_int32 copyVnodes(struct Msg *m, Volume *vol, Volume *newvol,
318 struct VnodeExtract *list, afs_int32 length,
319 afs_int32 where, afs_uint64 *blocks,
320 struct VnodeDiskObject *parVnode)
322 afs_int32 i, code = 0;
323 char buf[SIZEOF_LARGEDISKVNODE];
324 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)&buf;
326 FdHandle_t *newfdP = 0;
327 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
328 struct VnodeExtract *e;
333 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
335 Log("Couldn't open %s Index of volume %u\n",
336 class ? "small":"large", V_id(vol));
340 newfdP = IH_OPEN(newvol->vnodeIndex[class].handle);
342 Log("Couldn't open %s Index of volume %u\n",
343 class ? "small":"large", V_id(newvol));
347 size = FDH_SIZE(fdP);
349 for (i=0; i<length; i++) {
353 offset = (e->vN + 1 - class) << (vcp->logSize -1);
354 if (FDH_SEEK(fdP, offset, 0) != offset
355 || FDH_READ(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
356 Log("Couldn't read in %s Index of volume %u at offset %"
357 AFS_UINT64_FMT "\n", class ? "small":"large",
362 if (e->flag & PARENT) {
364 * do a preventive copy on write for later update
368 #if defined(NEARINODE_HINT) && !defined(AFS_NAMEI_ENV)
370 V_pref(vol,nearInode)
373 newino = IH_CREATE(V_linkHandle(vol), V_device(vol),
374 VPartitionPath(V_partition(vol)),
375 nearInode, V_parentId(vol),
376 e->vN, vnode->uniquifier,
378 IH_INIT(newh, V_device(vol), V_parentId(vol), newino);
379 ino = VNDISK_GET_INO(vnode);
380 IH_INIT(h, V_device(vol), V_parentId(vol), ino);
381 code = copyDir(m, h, newh);
384 /* Now update the vnode and write it back to disk */
385 VNDISK_SET_INO(vnode, newino);
387 if (FDH_SEEK(fdP, offset, 0) != offset
388 || FDH_WRITE(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
389 Log("Couldn't write in %s Index of volume %u at offset %"
390 AFS_UINT64_FMT "\n", class ? "small":"large",
395 memcpy(parVnode, vnode, sizeof(struct VnodeDiskObject));
397 if (e->flag & NEEDED && e->vN != where) {
398 VNDISK_GET_LEN(size, vnode);
399 *blocks += (size + 0x3ff) >> 10;
400 ino = VNDISK_GET_INO(vnode);
404 #if defined(NEARINODE_HINT) && !defined(AFS_NAMEI_ENV)
405 V_pref(vol,nearInode)
407 IH_INIT(h, vol->device, V_parentId(vol), ino);
408 if (e->parent == where)
410 newino = IH_CREATE(V_linkHandle(newvol), V_device(newvol),
411 VPartitionPath(V_partition(newvol)),
412 nearInode, V_parentId(newvol),
413 e->vN, vnode->uniquifier,
415 if (!VALID_INO(newino)) {
416 Log("IH_CREATE failed for %u.%u.%u\n",
417 V_id(newvol), e->vN, vnode->uniquifier);
422 IH_INIT(newh, newvol->device, V_parentId(newvol), newino);
423 code = namei_replace_file_by_hardlink(newh, h);
424 VNDISK_SET_INO(vnode, newino);
425 #ifdef AFS_RXOSD_SUPPORT
427 code = osd_split_objects(vol, newvol, vnode, e->vN);
428 #endif /* AFS_RXOSD_SUPPORT */
432 if (e->flag & CHANGEPARENT)
433 vnode->parent = 1; /* in new root-directory */
435 if (FDH_SEEK(newfdP, offset, 0) != offset
436 || FDH_WRITE(newfdP, vnode, vcp->diskSize) != vcp->diskSize) {
437 Log("Couldn't write in %s Index of volume %u to offset %"
438 AFS_UINT64_FMT "\n", class ? "small":"large",
439 V_id(newvol), offset);
447 * Now copy the root directory from old to new volume
449 if (class == vLarge) {
451 char buf2[SIZEOF_LARGEDISKVNODE];
452 struct VnodeDiskObject *vnode2 = (struct VnodeDiskObject *)&buf2;
453 afs_uint64 newoffset;
455 newoffset = vcp->diskSize;
456 if (FDH_SEEK(newfdP, newoffset, 0) != newoffset
457 || FDH_READ(newfdP, vnode2, vcp->diskSize) != vcp->diskSize) {
458 Log("splitvolume: couldn't read in large Index of new volume %u at offset %u\n",
459 V_id(newvol), vcp->diskSize);
463 offset = (where + 1 - class) << (vcp->logSize -1);
464 if (FDH_SEEK(fdP, offset, 0) != offset
465 || FDH_READ(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
466 Log("Couldn't read in large Index of old volume %u at offset %"
467 AFS_UINT64_FMT "\n", V_id(vol), offset);
471 VNDISK_GET_LEN(size, vnode);
472 *blocks += (size + 0x3ff) >> 10;
473 ino = VNDISK_GET_INO(vnode);
474 IH_INIT(h, vol->device, V_parentId(vol), ino);
475 newino = VNDISK_GET_INO(vnode2);
476 IH_INIT(newh, newvol->device, V_parentId(newvol), newino);
477 code = copyDir(m, h, newh);
479 Log("splitvolume: copyDir failed for new root from "
480 "%u.%u.%u to %u.1.1\n",
481 V_id(vol), where, vnode->uniquifier, V_id(newvol));
485 VNDISK_SET_INO(vnode, newino);
486 vnode->uniquifier = 1;
488 vnode->parent = vnode2->parent;
489 vnode->serverModifyTime = vnode2->serverModifyTime;
490 if (FDH_SEEK(newfdP, newoffset, 0) != newoffset
491 || FDH_WRITE(newfdP, vnode, vcp->diskSize) != vcp->diskSize) {
492 Log("splitvolume: couldn't write in large Index of %u at offset %u\n",
493 V_id(newvol), vcp->diskSize);
506 findName(Volume *vol, struct VnodeDiskObject *vd, afs_uint32 vN,
507 afs_uint32 un, char *name,afs_int32 length)
513 ino = VNDISK_GET_INO(vd);
514 SetSalvageDirHandle(&dir, V_id(vol), V_device(vol), ino);
516 code = InverseLookup(&dir, vN, un, name, length);
522 createMountpoint(Volume *vol, Volume *newvol, struct VnodeDiskObject *parent,
523 afs_uint32 vN, struct VnodeDiskObject *vd, char *name)
529 struct VnodeDiskObject vnode;
530 FdHandle_t *fdP, *fdP2;
531 afs_uint64 offset, size;
532 afs_int32 class = vSmall;
533 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
534 #if defined(NEARINODE_HINT) && !defined(AFS_NAMEI_ENV)
542 FT_GetTimeOfDay(&now, 0);
543 fdP = IH_OPEN(vol->vnodeIndex[vSmall].handle);
545 Log("split volume: error opening small vnode index of %u\n", V_id(vol));
548 offset = vcp->diskSize;
549 if (FDH_SEEK(fdP, offset, 0) != offset) {
550 Log("split volume: error seeking in small vnode index of %u\n", V_id(vol));
554 if (FDH_READ(fdP, &vnode, vcp->diskSize) != vcp->diskSize)
556 if (vnode.type == vNull)
558 offset += vcp->diskSize;
560 memset(&vnode, 0, sizeof(vnode));
561 vnode.type = vSymlink;
562 V_nextVnodeUnique(vol)++;
563 vnode.uniquifier = V_nextVnodeUnique(vol);
564 vnode.author = vd->author;
565 vnode.owner = vd->owner;
566 vnode.group = vd->group;
567 vnode.modeBits = 0644;
568 vnode.unixModifyTime = now.tv_sec;
569 vnode.serverModifyTime = now.tv_sec;
570 vnode.dataVersion = 1;
574 newvN = (offset >> (VnodeClassInfo[class].logSize - 1)) - 1 + class;
575 #if defined(NEARINODE_HINT) && !defined(AFS_NAMEI_ENV)
576 V_pref(vol,nearInode)
578 newino = IH_CREATE(V_linkHandle(vol), V_device(vol),
579 VPartitionPath(V_partition(vol)), nearInode,
580 V_parentId(vol), newvN, vnode.uniquifier, 1);
582 IH_INIT(h, V_device(vol), V_parentId(vol), newino);
585 Log("split volume: couldn't open inode for mountpoint %u.%u.%u\n",
586 V_id(vol), newvN, vnode.uniquifier);
589 FDH_SEEK(fdP2, 0, 0);
590 sprintf(symlink, "#%s", V_name(newvol));
591 size = strlen(symlink) + 1;
592 if (FDH_WRITE(fdP2, symlink, size) != size) {
593 Log("split volume: couldn't write mountpoint %u.%u.%u\n",
594 V_id(vol), newvN, vnode.uniquifier);
597 FDH_REALLYCLOSE(fdP2);
599 VNDISK_SET_INO(&vnode, newino);
600 VNDISK_SET_LEN(&vnode, size);
601 #ifndef AFS_RXOSD_SUPPORT
602 vnode.vnodeMagic = SMALLVNODEMAGIC;
604 if (FDH_SEEK(fdP, offset, 0) != offset
605 || FDH_WRITE(fdP, &vnode, vcp->diskSize) != vcp->diskSize) {
606 Log("split volume: couldn't write vnode for mountpoint %u.%u.%u\n",
607 V_id(vol), newvN, vnode.uniquifier);
610 FDH_REALLYCLOSE(fdP);
612 fid.Volume = V_id(vol);
614 fid.Unique = vnode.uniquifier;
617 * Now update the parent directory.
620 ino = VNDISK_GET_INO(parent);
621 SetSalvageDirHandle(&dir, V_id(vol), V_device(vol), ino);
623 code = Delete(&dir, name);
625 Log("splitvolume: couldn't delete directory entry for %s in %u.%u.%u, code = %d\n",
626 name, V_id(vol), vN, parent->uniquifier, code);
629 code = Create(&dir, name, &fid);
633 vcp = &VnodeClassInfo[class];
634 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
635 offset = (vN + 1 - class) << (vcp->logSize -1);
636 parent->dataVersion++;
637 if (FDH_SEEK(fdP, offset, 0) != offset
638 || FDH_WRITE(fdP, parent, vcp->diskSize) != vcp->diskSize) {
639 Log("split volume: couldn't write vnode for parent directory %u.%u.%u\n",
640 V_id(vol), vN, parent->uniquifier);
643 FDH_REALLYCLOSE(fdP);
648 deleteVnodes(Volume *vol, afs_int32 class,
649 struct VnodeExtract *list, afs_int32 length,
652 afs_int32 i, code = 0;
653 char buf[SIZEOF_LARGEDISKVNODE];
654 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)&buf;
656 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
657 struct VnodeExtract *e;
662 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
664 Log("Couldn't open %s Index of volume %u\n",
665 class ? "small":"large", V_id(vol));
669 size = FDH_SIZE(fdP);
671 for (i=0; i<length; i++) {
673 if (e->flag & NEEDED) {
675 offset = (e->vN + 1 - class) << (vcp->logSize -1);
676 if (FDH_SEEK(fdP, offset, 0) != offset) {
677 Log("Couldn't seek in %s Index of volume %u to offset %"
678 AFS_UINT64_FMT "\n", class ? "small":"large", V_id(vol),
683 if (FDH_READ(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
684 Log("Couldn't read in %s Index of volume %u at offset %"
685 AFS_UINT64_FMT "\n", class ? "small":"large", V_id(vol),
690 VNDISK_GET_LEN(size, vnode);
691 *blocks += (size + 0x3ff) >> 10;
692 ino = VNDISK_GET_INO(vnode);
695 IH_INIT(h, vol->device, V_parentId(vol), ino);
696 IH_DEC(h, ino, V_parentId(vol));
697 #ifdef AFS_RXOSD_SUPPORT
699 code = osdRemove(vol, vnode, e->vN);
700 #endif /* AFS_RXOSD_SUPPORT */
702 memset(vnode, 0, vcp->diskSize);
704 if (FDH_SEEK(fdP, offset, 0) != offset
705 || FDH_WRITE(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
706 Log("Couldn't write in %s Index of volume %u to offset %"
707 AFS_UINT64_FMT "\n", class ? "small":"large",
719 split_volume(struct rx_call *call, Volume *vol, Volume *newvol,
720 afs_uint32 where, afs_int32 verbose)
723 struct VnodeExtract *dirList = 0;
724 struct VnodeExtract *fileList = 0;
725 afs_uint64 blocks = 0;
726 afs_uint32 filesNeeded, dirsNeeded;
728 char buf[SIZEOF_LARGEDISKVNODE];
729 char buf2[SIZEOF_LARGEDISKVNODE];
730 struct VnodeDiskObject *rootVnode = (struct VnodeDiskObject *)&buf;
731 struct VnodeDiskObject *parVnode = (struct VnodeDiskObject *)&buf2;
736 m = (struct Msg *) malloc(sizeof(struct Msg));
737 memset(m, 0, sizeof(struct Msg));
739 m->verbose = verbose;
742 * First step: planning
744 * Find out which directories will belong to the new volume
749 "1st step: extract vnode essence from large vnode file\n");
750 rx_Write(m->call, m->line, strlen(m->line));
753 code = ExtractVnodes(m, vol, vLarge, &dirList, &dl, where, rootVnode,
757 "ExtractVnodes failed for %u for directories with code %d\n",
759 rx_Write(m->call, m->line, strlen(m->line));
764 sprintf(m->line, "2nd step: look for name of vnode %u in directory %u.%u.%u\n",
765 where, V_id(vol), parent, parVnode->uniquifier);
766 rx_Write(m->call, m->line, strlen(m->line));
768 code = findName(vol, parVnode, where, rootVnode->uniquifier,
772 "splitvolume: could'nt find name of %u in directory %u.%u.%u.\n",
773 where, V_id(vol), parent, parVnode->uniquifier);
774 rx_Write(m->call, m->line, strlen(m->line));
778 sprintf(m->line, "name of %u is %s\n", where, name);
779 rx_Write(m->call, m->line, strlen(m->line));
783 sprintf(m->line, "3rd step: find all directory vnodes belonging to the subtree under %u \"%s\"\n",
785 rx_Write(m->call, m->line, strlen(m->line));
787 code = FindVnodes(m, where, dirList, dl, dirList, dl, &dirsNeeded, 1);
790 "FindVnodes for directories failed with code %d\n", code);
791 rx_Write(m->call, m->line, strlen(m->line));
796 sprintf(m->line, "4th step extract vnode essence from small vnode file\n");
797 rx_Write(m->call, m->line, strlen(m->line));
799 code = ExtractVnodes(m, vol, vSmall, &fileList, &fl, where, 0, 0, 0);
802 "ExtractVnodes failed for %u for files with code %d\n",
804 rx_Write(m->call, m->line, strlen(m->line));
808 sprintf(m->line, "5th step: find all small vnodes belonging to the subtree under %u \"%s\"\n",
810 rx_Write(m->call, m->line, strlen(m->line));
812 FindVnodes(m, where, fileList, fl, dirList, dl, &filesNeeded, 0);
815 * Third step: create hard links for all files needed
819 V_destroyMe(newvol) = DESTROY_ME;
820 V_inService(newvol) = 0;
822 sprintf(m->line, "6th step: create hard links in the AFSIDat tree between files of the old and new volume\n");
823 rx_Write(m->call, m->line, strlen(m->line));
825 code = copyVnodes(m, vol, newvol, 1, fileList, fl, where, &blocks, 0);
827 sprintf(m->line, "copyVnodes for files failed with code %d\n", code);
828 rx_Write(m->call, m->line, strlen(m->line));
833 * Forth step: create hard links for all directories and copy
834 * split directory to new root directory
838 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",
840 rx_Write(m->call, m->line, strlen(m->line));
842 code = copyVnodes(m, vol, newvol, 0, dirList, dl, where, &blocks, parVnode);
844 sprintf(m->line, "copyVnodes for directories failed with code %d\n", code);
845 rx_Write(m->call, m->line, strlen(m->line));
850 * Finalize new volume
854 sprintf(m->line, "8th step: write new volume's metadata to disk\n");
855 rx_Write(m->call, m->line, strlen(m->line));
858 V_diskused(newvol) = blocks;
859 #ifdef AFS_RXOSD_SUPPORT
860 V_osdFlag(newvol) = V_osdFlag(vol);
862 V_filecount(newvol) = filesNeeded + dirsNeeded;
863 V_destroyMe(newvol) = 0;
864 V_maxquota(newvol) = V_maxquota(vol);
865 V_uniquifier(newvol) = V_uniquifier(vol);
866 V_inService(newvol) = 1;
867 VUpdateVolume(&code, newvol);
870 * Sixth step: change directory entry in old volume:
871 * rename old tree and create mount point for new volume.
874 sprintf(m->line, "9th step: create mountpoint \"%s\" for new volume in old volume's directory %u.\n", name, parent);
875 rx_Write(m->call, m->line, strlen(m->line));
878 code = createMountpoint(vol, newvol, parVnode, parent, rootVnode, name);
880 sprintf(m->line, "createMountpoint failed with code %d\n", code);
881 rx_Write(m->call, m->line, strlen(m->line));
885 * Now both volumes should be ready and consistent, but the old volume
886 * contains still the vnodes and data we transferred into the new one.
887 * Delete orphaned vnodes and data.
892 sprintf(m->line, "10th step: delete large vnodes belonging to subtree in the old volume.\n");
893 rx_Write(m->call, m->line, strlen(m->line));
895 deleteVnodes(vol, vLarge, dirList, dl, &blocks);
897 sprintf(m->line, "11th step: delete small vnodes belonging to subtree in the old volume.\n");
898 rx_Write(m->call, m->line, strlen(m->line));
900 deleteVnodes(vol, vSmall, fileList, fl, &blocks);
901 V_diskused(vol) -= blocks;
902 V_filecount(vol) -= (filesNeeded + dirsNeeded + 1);
903 VUpdateVolume(&code, vol);
905 sprintf(m->line, "Finished!\n");
906 rx_Write(m->call, m->line, strlen(m->line));
911 rx_Write(m->call, m->line, 4);