2 * Copyright (c) 2007, Hartmut Reuter,
3 * RZG, Max-Planck-Institut f. Plasmaphysik.
13 #ifdef HAVE_SYS_FILE_H
17 #if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
18 #include <afs/afs_assert.h>
21 #include <afs/afsint.h>
25 #include <afs/afssyscalls.h>
26 #include <afs/ihandle.h>
27 #include <afs/vnode.h>
28 #include <afs/volume.h>
29 #include <afs/partition.h>
30 #include <afs/viceinode.h>
36 #include "volser_internal.h"
37 #ifdef AFS_RXOSD_SUPPORT
40 #include "../vol/vol_osd_prototypes.h"
45 #define CHANGEPARENT 4
47 #define NAMEI_VNODEMASK 0x03ffffff
48 #define NAMEI_TAGMASK 0x7
49 #define NAMEI_TAGSHIFT 26
50 #define NAMEI_UNIQMASK 0xffffffff
51 #define NAMEI_UNIQSHIFT 32
60 struct rx_call * call;
66 ExtractVnodes(struct Msg *m, Volume *vol, afs_int32 class,
67 struct VnodeExtract **list,
68 afs_uint32 *length, afs_uint32 where,
69 struct VnodeDiskObject *vd,
70 afs_uint32 *parent, struct VnodeDiskObject *parentvd)
73 char buf[SIZEOF_LARGEDISKVNODE];
74 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)&buf;
76 StreamHandle_t *stream = 0;
77 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
78 struct VnodeExtract *e;
86 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
88 sprintf(m->line, "Couldn't open %s Index of volume %u\n",
89 class ? "small":"large", V_id(vol));
90 rx_Write(m->call, m->line, strlen(m->line));
95 *list = (struct VnodeExtract *) malloc(size / vcp->diskSize
96 * sizeof(struct VnodeExtract));
101 memset(*list, 0, size / vcp->diskSize * sizeof(struct VnodeExtract));
102 stream = FDH_FDOPEN(fdP, "r");
104 sprintf(m->line, "Couldn't stream open %s Index of volume %u\n",
105 class ? "small":"large", V_id(vol));
106 rx_Write(m->call, m->line, strlen(m->line));
110 code = STREAM_ASEEK(stream, vcp->diskSize);
114 offset = vcp->diskSize;
116 while (!STREAM_EOF(stream)) {
117 afs_int32 vN = (offset >> (vcp->logSize -1)) - 1 + class;
118 if (STREAM_READ(vnode, vcp->diskSize, 1, stream) == 1) {
119 if (vnode->type != vNull) {
121 e->parent = vnode->parent;
122 if (vN == where && class == vLarge) {
123 memcpy(vd, vnode, vcp->diskSize);
124 *parent = vnode->parent;
128 offset += vcp->diskSize;
131 *length = (e - *list);
132 if (class == vLarge) {
134 offset = (*parent + 1 - class) << (vcp->logSize -1);
135 code = STREAM_ASEEK(stream, offset);
136 if (STREAM_READ(vnode, vcp->diskSize, 1, stream) == 1)
137 memcpy(parentvd, vnode, vcp->diskSize);
141 sprintf(m->line, "SplitVolume: extract didn't see directory %u\n", where);
142 rx_Write(m->call, m->line, strlen(m->line));
147 sprintf(m->line, "Volume %u has %u %s vnodes in volume %u\n",
148 V_parentId(vol), *length, class? "small":"large",
150 rx_Write(m->call, m->line, strlen(m->line));
155 STREAM_CLOSE(stream);
166 FindVnodes(struct Msg *m, afs_uint32 where,
167 struct VnodeExtract *list, afs_int32 length,
168 struct VnodeExtract *dlist, afs_int32 dlength,
169 afs_uint32 *needed, afs_int32 class)
171 afs_int32 i, j, found = 0;
172 afs_int32 parent = 0;
175 for (i=0; i<length; i++) {
176 if (list[i].vN == where) { /* dir to be replaced by mount point */
177 list[i].flag |= NEEDED;
178 parent = list[i].parent;
182 if (list[i].parent == where) { /* all 1st generation children */
183 list[i].flag |= (NEEDED + CHANGEPARENT);
187 if (list[0].vN & 1) { /* only for directories */
190 "SplitVolume: directory %u where to start new volume not found\n",
192 rx_Write(m->call, m->line, strlen(m->line));
196 for (i=0; i<length; i++) {
197 if (list[i].vN == parent) { /* dir where to create mount point */
198 list[i].flag |= PARENT;
204 sprintf(m->line, "SplitVolume: parent directory %u not found\n",
206 rx_Write(m->call, m->line, strlen(m->line));
213 for (i=0; i<dlength; i++) {
214 if (!(dlist[i].flag & NEEDED)) /* dirs to remain in old volume */
216 for (j=0; j<length; j++) {
217 if (list[j].parent == dlist[i].vN && !(list[j].flag & NEEDED)) {
218 list[j].flag |= NEEDED;
226 sprintf(m->line, "%u %s vnodes will go into the new volume\n",
227 *needed, class ? "small" : "large");
228 rx_Write(m->call, m->line, strlen(m->line));
234 copyDir(struct Msg *m, IHandle_t *inh, IHandle_t *outh)
236 FdHandle_t *infdP, *outfdP;
241 infdP = IH_OPEN(inh);
243 sprintf(m->line, "Couldn't open input directory %u.%u.%u\n",
244 infdP->fd_ih->ih_vid,
245 (afs_uint32)(infdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
246 (afs_uint32)(infdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
247 rx_Write(m->call, m->line, strlen(m->line));
250 outfdP = IH_OPEN(outh);
252 sprintf(m->line, "Couldn't open output directory %u.%u.%u\n",
253 outfdP->fd_ih->ih_vid,
254 (afs_uint32)(outfdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
255 (afs_uint32)(outfdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
256 rx_Write(m->call, m->line, strlen(m->line));
257 FDH_REALLYCLOSE(infdP);
262 size = FDH_SIZE(infdP);
265 tlen = size > 2048 ? 2048 : size;
266 if (FDH_PREAD(infdP, tbuf, tlen, offset) != tlen) {
267 sprintf(m->line, "Couldn't read directory %u.%u.%u\n",
268 infdP->fd_ih->ih_vid,
269 (afs_uint32)(infdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
270 (afs_uint32)(infdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
271 rx_Write(m->call, m->line, strlen(m->line));
272 FDH_REALLYCLOSE(infdP);
273 FDH_REALLYCLOSE(outfdP);
277 if (FDH_PWRITE(outfdP, tbuf, tlen, offset) != tlen) {
278 sprintf(m->line, "Couldn't write directory %u.%u.%u\n",
279 outfdP->fd_ih->ih_vid,
280 (afs_uint32)(outfdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
281 (afs_uint32)(outfdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
282 rx_Write(m->call, m->line, strlen(m->line));
283 FDH_REALLYCLOSE(infdP);
284 FDH_REALLYCLOSE(outfdP);
293 FDH_REALLYCLOSE(infdP);
297 afs_int32 copyVnodes(struct Msg *m, Volume *vol, Volume *newvol,
299 struct VnodeExtract *list, afs_int32 length,
300 afs_int32 where, afs_uint64 *blocks,
301 struct VnodeDiskObject *parVnode)
303 afs_int32 i, code = 0;
304 char buf[SIZEOF_LARGEDISKVNODE];
305 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)&buf;
307 FdHandle_t *newfdP = 0;
308 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
309 struct VnodeExtract *e;
314 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
316 Log("Couldn't open %s Index of volume %u\n",
317 class ? "small":"large", V_id(vol));
321 newfdP = IH_OPEN(newvol->vnodeIndex[class].handle);
323 Log("Couldn't open %s Index of volume %u\n",
324 class ? "small":"large", V_id(newvol));
328 size = FDH_SIZE(fdP);
330 for (i=0; i<length; i++) {
334 offset = (e->vN + 1 - class) << (vcp->logSize -1);
335 if (FDH_PREAD(fdP, vnode, vcp->diskSize, offset) != vcp->diskSize) {
336 Log("Couldn't read in %s Index of volume %u at offset %llu\n",
337 class ? "small":"large", V_id(vol), offset);
341 if (e->flag & PARENT) {
343 * do a preventive copy on write for later update
347 #if defined(NEARINODE_HINT) && !defined(AFS_NAMEI_ENV)
349 V_pref(vol,nearInode)
352 newino = IH_CREATE(V_linkHandle(vol), V_device(vol),
353 VPartitionPath(V_partition(vol)),
354 nearInode, V_parentId(vol),
355 e->vN, vnode->uniquifier,
357 IH_INIT(newh, V_device(vol), V_parentId(vol), newino);
358 ino = VNDISK_GET_INO(vnode);
359 IH_INIT(h, V_device(vol), V_parentId(vol), ino);
360 code = copyDir(m, h, newh);
363 /* Now update the vnode and write it back to disk */
364 VNDISK_SET_INO(vnode, newino);
366 if (FDH_PWRITE(fdP, vnode, vcp->diskSize, offset) != vcp->diskSize) {
367 Log("Couldn't write in %s Index of volume %u at offset %llu\n",
368 class ? "small":"large", V_id(vol), offset);
372 memcpy(parVnode, vnode, sizeof(struct VnodeDiskObject));
374 if (e->flag & NEEDED && e->vN != where) {
375 VNDISK_GET_LEN(size, vnode);
376 *blocks += (size + 0x3ff) >> 10;
377 ino = VNDISK_GET_INO(vnode);
381 #if defined(NEARINODE_HINT) && !defined(AFS_NAMEI_ENV)
382 V_pref(vol,nearInode)
384 IH_INIT(h, vol->device, V_parentId(vol), ino);
385 if (e->parent == where)
387 newino = IH_CREATE(V_linkHandle(newvol), V_device(newvol),
388 VPartitionPath(V_partition(newvol)),
389 nearInode, V_parentId(newvol),
390 e->vN, vnode->uniquifier,
392 if (!VALID_INO(newino)) {
393 Log("IH_CREATE failed for %u.%u.%u\n",
394 V_id(newvol), e->vN, vnode->uniquifier);
399 IH_INIT(newh, newvol->device, V_parentId(newvol), newino);
400 code = namei_replace_file_by_hardlink(newh, h);
401 VNDISK_SET_INO(vnode, newino);
402 #ifdef AFS_RXOSD_SUPPORT
404 code = osd_split_objects(vol, newvol, vnode, e->vN);
405 #endif /* AFS_RXOSD_SUPPORT */
409 if (e->flag & CHANGEPARENT)
410 vnode->parent = 1; /* in new root-directory */
412 if (FDH_PWRITE(newfdP, vnode, vcp->diskSize, offset) != vcp->diskSize) {
413 Log("Couldn't write in %s Index of volume %u to offset %llu\n",
414 class ? "small":"large", V_id(newvol), offset);
422 * Now copy the root directory from old to new volume
424 if (class == vLarge) {
426 char buf2[SIZEOF_LARGEDISKVNODE];
427 struct VnodeDiskObject *vnode2 = (struct VnodeDiskObject *)&buf2;
428 afs_uint64 newoffset;
430 newoffset = vcp->diskSize;
431 if (FDH_PREAD(newfdP, vnode2, vcp->diskSize, newoffset) != vcp->diskSize) {
432 Log("splitvolume: couldn't read in large Index of new volume %u at offset %u\n",
433 V_id(newvol), vcp->diskSize);
437 offset = (where + 1 - class) << (vcp->logSize -1);
438 if (FDH_PREAD(fdP, vnode, vcp->diskSize, offset) != vcp->diskSize) {
439 Log("Couldn't read in large Index of old volume %u at offset %llu\n",
444 VNDISK_GET_LEN(size, vnode);
445 *blocks += (size + 0x3ff) >> 10;
446 ino = VNDISK_GET_INO(vnode);
447 IH_INIT(h, vol->device, V_parentId(vol), ino);
448 newino = VNDISK_GET_INO(vnode2);
449 IH_INIT(newh, newvol->device, V_parentId(newvol), newino);
450 code = copyDir(m, h, newh);
452 Log("splitvolume: copyDir failed for new root from "
453 "%u.%u.%u to %u.1.1\n",
454 V_id(vol), where, vnode->uniquifier, V_id(newvol));
458 VNDISK_SET_INO(vnode, newino);
459 vnode->uniquifier = 1;
461 vnode->parent = vnode2->parent;
462 vnode->serverModifyTime = vnode2->serverModifyTime;
463 if (FDH_PWRITE(newfdP, vnode, vcp->diskSize, newoffset) != vcp->diskSize) {
464 Log("splitvolume: couldn't write in large Index of %u at offset %u\n",
465 V_id(newvol), vcp->diskSize);
478 findName(Volume *vol, struct VnodeDiskObject *vd, afs_uint32 vN,
479 afs_uint32 un, char *name,afs_int32 length)
485 ino = VNDISK_GET_INO(vd);
486 SetSalvageDirHandle(&dir, V_id(vol), V_device(vol), ino);
488 code = InverseLookup(&dir, vN, un, name, length);
494 createMountpoint(Volume *vol, Volume *newvol, struct VnodeDiskObject *parent,
495 afs_uint32 vN, struct VnodeDiskObject *vd, char *name)
501 struct VnodeDiskObject vnode;
502 FdHandle_t *fdP, *fdP2;
505 afs_int32 class = vSmall;
506 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
507 #if defined(NEARINODE_HINT) && !defined(AFS_NAMEI_ENV)
516 FT_GetTimeOfDay(&now, 0);
517 fdP = IH_OPEN(vol->vnodeIndex[vSmall].handle);
519 Log("split volume: error opening small vnode index of %u\n", V_id(vol));
522 offset = vcp->diskSize;
524 rc = FDH_PREAD(fdP, &vnode, vcp->diskSize, offset);
525 if (rc != vcp->diskSize) {
527 Log("split volume: error reading small vnode index of %u\n", V_id(vol));
532 if (rc < vcp->diskSize)
535 if (vnode.type == vNull)
537 offset += vcp->diskSize;
539 memset(&vnode, 0, sizeof(vnode));
540 vnode.type = vSymlink;
541 V_nextVnodeUnique(vol)++;
542 vnode.uniquifier = V_nextVnodeUnique(vol);
543 vnode.author = vd->author;
544 vnode.owner = vd->owner;
545 vnode.group = vd->group;
546 vnode.modeBits = 0644;
547 vnode.unixModifyTime = now.tv_sec;
548 vnode.serverModifyTime = now.tv_sec;
549 vnode.dataVersion = 1;
553 newvN = (offset >> (VnodeClassInfo[class].logSize - 1)) - 1 + class;
554 #if defined(NEARINODE_HINT) && !defined(AFS_NAMEI_ENV)
555 V_pref(vol,nearInode)
557 newino = IH_CREATE(V_linkHandle(vol), V_device(vol),
558 VPartitionPath(V_partition(vol)), nearInode,
559 V_parentId(vol), newvN, vnode.uniquifier, 1);
561 IH_INIT(h, V_device(vol), V_parentId(vol), newino);
564 Log("split volume: couldn't open inode for mountpoint %u.%u.%u\n",
565 V_id(vol), newvN, vnode.uniquifier);
568 sprintf(symlink, "#%s", V_name(newvol));
569 size = strlen(symlink) + 1;
570 if (FDH_PWRITE(fdP2, symlink, size, 0) != size) {
571 Log("split volume: couldn't write mountpoint %u.%u.%u\n",
572 V_id(vol), newvN, vnode.uniquifier);
575 FDH_REALLYCLOSE(fdP2);
577 VNDISK_SET_INO(&vnode, newino);
578 VNDISK_SET_LEN(&vnode, size);
579 #ifndef AFS_RXOSD_SUPPORT
580 vnode.vnodeMagic = SMALLVNODEMAGIC;
582 if (FDH_PWRITE(fdP, &vnode, vcp->diskSize, offset) != vcp->diskSize) {
583 Log("split volume: couldn't write vnode for mountpoint %u.%u.%u\n",
584 V_id(vol), newvN, vnode.uniquifier);
587 FDH_REALLYCLOSE(fdP);
589 fid.Volume = V_id(vol);
591 fid.Unique = vnode.uniquifier;
594 * Now update the parent directory.
597 ino = VNDISK_GET_INO(parent);
598 SetSalvageDirHandle(&dir, V_id(vol), V_device(vol), ino);
600 code = Delete(&dir, name);
602 Log("splitvolume: couldn't delete directory entry for %s in %u.%u.%u, code = %d\n",
603 name, V_id(vol), vN, parent->uniquifier, code);
606 code = Create(&dir, name, &fid);
610 vcp = &VnodeClassInfo[class];
611 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
612 offset = (vN + 1 - class) << (vcp->logSize -1);
613 parent->dataVersion++;
614 if (FDH_PWRITE(fdP, parent, vcp->diskSize, offset) != vcp->diskSize) {
615 Log("split volume: couldn't write vnode for parent directory %u.%u.%u\n",
616 V_id(vol), vN, parent->uniquifier);
619 FDH_REALLYCLOSE(fdP);
624 deleteVnodes(Volume *vol, afs_int32 class,
625 struct VnodeExtract *list, afs_int32 length,
628 afs_int32 i, code = 0;
629 char buf[SIZEOF_LARGEDISKVNODE];
630 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)&buf;
632 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
633 struct VnodeExtract *e;
638 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
640 Log("Couldn't open %s Index of volume %u\n",
641 class ? "small":"large", V_id(vol));
646 for (i=0; i<length; i++) {
648 if (e->flag & NEEDED) {
649 offset = (e->vN + 1 - class) << (vcp->logSize -1);
650 if (FDH_PREAD(fdP, vnode, vcp->diskSize, offset) != vcp->diskSize) {
651 Log("Couldn't read in %s Index of volume %u at offset %llu\n",
652 class ? "small":"large", V_id(vol), offset);
656 VNDISK_GET_LEN(size, vnode);
657 *blocks += (size + 0x3ff) >> 10;
658 ino = VNDISK_GET_INO(vnode);
661 IH_INIT(h, vol->device, V_parentId(vol), ino);
662 IH_DEC(h, ino, V_parentId(vol));
663 #ifdef AFS_RXOSD_SUPPORT
665 code = osdRemove(vol, vnode, e->vN);
666 #endif /* AFS_RXOSD_SUPPORT */
668 memset(vnode, 0, vcp->diskSize);
670 if (FDH_PWRITE(fdP, vnode, vcp->diskSize, offset) != vcp->diskSize) {
671 Log("Couldn't write in %s Index of volume %u to offset %llu\n",
672 class ? "small":"large", V_id(vol), offset);
683 split_volume(struct rx_call *call, Volume *vol, Volume *newvol,
684 afs_uint32 where, afs_int32 verbose)
687 struct VnodeExtract *dirList = 0;
688 struct VnodeExtract *fileList = 0;
689 afs_uint64 blocks = 0;
690 afs_uint32 filesNeeded, dirsNeeded;
692 char buf[SIZEOF_LARGEDISKVNODE];
693 char buf2[SIZEOF_LARGEDISKVNODE];
694 struct VnodeDiskObject *rootVnode = (struct VnodeDiskObject *)&buf;
695 struct VnodeDiskObject *parVnode = (struct VnodeDiskObject *)&buf2;
700 m = (struct Msg *) malloc(sizeof(struct Msg));
701 memset(m, 0, sizeof(struct Msg));
703 m->verbose = verbose;
706 * First step: planning
708 * Find out which directories will belong to the new volume
713 "1st step: extract vnode essence from large vnode file\n");
714 rx_Write(m->call, m->line, strlen(m->line));
717 code = ExtractVnodes(m, vol, vLarge, &dirList, &dl, where, rootVnode,
721 "ExtractVnodes failed for %u for directories with code %d\n",
723 rx_Write(m->call, m->line, strlen(m->line));
728 sprintf(m->line, "2nd step: look for name of vnode %u in directory %u.%u.%u\n",
729 where, V_id(vol), parent, parVnode->uniquifier);
730 rx_Write(m->call, m->line, strlen(m->line));
732 code = findName(vol, parVnode, where, rootVnode->uniquifier,
736 "splitvolume: could'nt find name of %u in directory %u.%u.%u.\n",
737 where, V_id(vol), parent, parVnode->uniquifier);
738 rx_Write(m->call, m->line, strlen(m->line));
742 sprintf(m->line, "name of %u is %s\n", where, name);
743 rx_Write(m->call, m->line, strlen(m->line));
747 sprintf(m->line, "3rd step: find all directory vnodes belonging to the subtree under %u \"%s\"\n",
749 rx_Write(m->call, m->line, strlen(m->line));
751 code = FindVnodes(m, where, dirList, dl, dirList, dl, &dirsNeeded, 1);
754 "FindVnodes for directories failed with code %d\n", code);
755 rx_Write(m->call, m->line, strlen(m->line));
760 sprintf(m->line, "4th step extract vnode essence from small vnode file\n");
761 rx_Write(m->call, m->line, strlen(m->line));
763 code = ExtractVnodes(m, vol, vSmall, &fileList, &fl, where, 0, 0, 0);
766 "ExtractVnodes failed for %u for files with code %d\n",
768 rx_Write(m->call, m->line, strlen(m->line));
772 sprintf(m->line, "5th step: find all small vnodes belonging to the subtree under %u \"%s\"\n",
774 rx_Write(m->call, m->line, strlen(m->line));
776 FindVnodes(m, where, fileList, fl, dirList, dl, &filesNeeded, 0);
779 * Third step: create hard links for all files needed
783 V_destroyMe(newvol) = DESTROY_ME;
784 V_inService(newvol) = 0;
786 sprintf(m->line, "6th step: create hard links in the AFSIDat tree between files of the old and new volume\n");
787 rx_Write(m->call, m->line, strlen(m->line));
789 code = copyVnodes(m, vol, newvol, 1, fileList, fl, where, &blocks, 0);
791 sprintf(m->line, "copyVnodes for files failed with code %d\n", code);
792 rx_Write(m->call, m->line, strlen(m->line));
797 * Forth step: create hard links for all directories and copy
798 * split directory to new root directory
802 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",
804 rx_Write(m->call, m->line, strlen(m->line));
806 code = copyVnodes(m, vol, newvol, 0, dirList, dl, where, &blocks, parVnode);
808 sprintf(m->line, "copyVnodes for directories failed with code %d\n", code);
809 rx_Write(m->call, m->line, strlen(m->line));
814 * Finalize new volume
818 sprintf(m->line, "8th step: write new volume's metadata to disk\n");
819 rx_Write(m->call, m->line, strlen(m->line));
822 V_diskused(newvol) = blocks;
823 #ifdef AFS_RXOSD_SUPPORT
824 V_osdFlag(newvol) = V_osdFlag(vol);
826 V_filecount(newvol) = filesNeeded + dirsNeeded;
827 V_destroyMe(newvol) = 0;
828 V_maxquota(newvol) = V_maxquota(vol);
829 V_uniquifier(newvol) = V_uniquifier(vol);
830 V_inService(newvol) = 1;
831 VUpdateVolume(&code, newvol);
834 * Sixth step: change directory entry in old volume:
835 * rename old tree and create mount point for new volume.
838 sprintf(m->line, "9th step: create mountpoint \"%s\" for new volume in old volume's directory %u.\n", name, parent);
839 rx_Write(m->call, m->line, strlen(m->line));
842 code = createMountpoint(vol, newvol, parVnode, parent, rootVnode, name);
844 sprintf(m->line, "createMountpoint failed with code %d\n", code);
845 rx_Write(m->call, m->line, strlen(m->line));
849 * Now both volumes should be ready and consistent, but the old volume
850 * contains still the vnodes and data we transferred into the new one.
851 * Delete orphaned vnodes and data.
856 sprintf(m->line, "10th step: delete large vnodes belonging to subtree in the old volume.\n");
857 rx_Write(m->call, m->line, strlen(m->line));
859 deleteVnodes(vol, vLarge, dirList, dl, &blocks);
861 sprintf(m->line, "11th step: delete small vnodes belonging to subtree in the old volume.\n");
862 rx_Write(m->call, m->line, strlen(m->line));
864 deleteVnodes(vol, vSmall, fileList, fl, &blocks);
865 V_diskused(vol) -= blocks;
866 V_filecount(vol) -= (filesNeeded + dirsNeeded + 1);
867 VUpdateVolume(&code, vol);
869 sprintf(m->line, "Finished!\n");
870 rx_Write(m->call, m->line, strlen(m->line));
875 rx_Write(m->call, m->line, 4);