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 #include <afs/afs_assert.h>
38 #include <afs/afsint.h>
42 #include <afs/afssyscalls.h>
43 #include <afs/ihandle.h>
44 #include <afs/vnode.h>
45 #include <afs/volume.h>
46 #include <afs/partition.h>
47 #include <afs/viceinode.h>
52 #include "volser_internal.h"
53 #ifdef AFS_RXOSD_SUPPORT
56 #include "../vol/vol_osd_prototypes.h"
61 #define CHANGEPARENT 4
63 #define NAMEI_VNODEMASK 0x03ffffff
64 #define NAMEI_TAGMASK 0x7
65 #define NAMEI_TAGSHIFT 26
66 #define NAMEI_UNIQMASK 0xffffffff
67 #define NAMEI_UNIQSHIFT 32
76 struct rx_call * call;
82 ExtractVnodes(struct Msg *m, Volume *vol, afs_int32 class,
83 struct VnodeExtract **list,
84 afs_uint32 *length, afs_uint32 where,
85 struct VnodeDiskObject *vd,
86 afs_uint32 *parent, struct VnodeDiskObject *parentvd)
89 char buf[SIZEOF_LARGEDISKVNODE];
90 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)&buf;
92 StreamHandle_t *stream = 0;
93 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
94 struct VnodeExtract *e;
102 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
104 sprintf(m->line, "Couldn't 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 size = FDH_SIZE(fdP);
111 *list = (struct VnodeExtract *) malloc(size / vcp->diskSize
112 * sizeof(struct VnodeExtract));
117 memset(*list, 0, size / vcp->diskSize * sizeof(struct VnodeExtract));
118 stream = FDH_FDOPEN(fdP, "r");
120 sprintf(m->line, "Couldn't stream open %s Index of volume %u\n",
121 class ? "small":"large", V_id(vol));
122 rx_Write(m->call, m->line, strlen(m->line));
126 code = STREAM_ASEEK(stream, vcp->diskSize);
130 offset = vcp->diskSize;
132 while (!STREAM_EOF(stream)) {
133 afs_int32 vN = (offset >> (vcp->logSize -1)) - 1 + class;
134 if (STREAM_READ(vnode, vcp->diskSize, 1, stream) == 1) {
135 if (vnode->type != vNull) {
137 e->parent = vnode->parent;
138 if (vN == where && class == vLarge) {
139 memcpy(vd, vnode, vcp->diskSize);
140 *parent = vnode->parent;
144 offset += vcp->diskSize;
147 *length = (e - *list);
148 if (class == vLarge) {
150 offset = (*parent + 1 - class) << (vcp->logSize -1);
151 code = STREAM_ASEEK(stream, offset);
152 if (STREAM_READ(vnode, vcp->diskSize, 1, stream) == 1)
153 memcpy(parentvd, vnode, vcp->diskSize);
157 sprintf(m->line, "SplitVolume: extract didn't see directory %u\n", where);
158 rx_Write(m->call, m->line, strlen(m->line));
163 sprintf(m->line, "Volume %u has %u %s vnodes in volume %u\n",
164 V_parentId(vol), *length, class? "small":"large",
166 rx_Write(m->call, m->line, strlen(m->line));
171 STREAM_CLOSE(stream);
182 FindVnodes(struct Msg *m, afs_uint32 where,
183 struct VnodeExtract *list, afs_int32 length,
184 struct VnodeExtract *dlist, afs_int32 dlength,
185 afs_uint32 *needed, afs_int32 class)
187 afs_int32 i, j, found = 0;
188 afs_int32 parent = 0;
191 for (i=0; i<length; i++) {
192 if (list[i].vN == where) { /* dir to be replaced by mount point */
193 list[i].flag |= NEEDED;
194 parent = list[i].parent;
198 if (list[i].parent == where) { /* all 1st generation children */
199 list[i].flag |= (NEEDED + CHANGEPARENT);
203 if (list[0].vN & 1) { /* only for directories */
206 "SplitVolume: directory %u where to start new volume not found\n",
208 rx_Write(m->call, m->line, strlen(m->line));
212 for (i=0; i<length; i++) {
213 if (list[i].vN == parent) { /* dir where to create mount point */
214 list[i].flag |= PARENT;
220 sprintf(m->line, "SplitVolume: parent directory %u not found\n",
222 rx_Write(m->call, m->line, strlen(m->line));
229 for (i=0; i<dlength; i++) {
230 if (!(dlist[i].flag & NEEDED)) /* dirs to remain in old volume */
232 for (j=0; j<length; j++) {
233 if (list[j].parent == dlist[i].vN && !(list[j].flag & NEEDED)) {
234 list[j].flag |= NEEDED;
242 sprintf(m->line, "%u %s vnodes will go into the new volume\n",
243 *needed, class ? "small" : "large");
244 rx_Write(m->call, m->line, strlen(m->line));
250 copyDir(struct Msg *m, IHandle_t *inh, IHandle_t *outh)
252 FdHandle_t *infdP, *outfdP;
257 infdP = IH_OPEN(inh);
259 sprintf(m->line, "Couldn't open input directory %u.%u.%u\n",
260 infdP->fd_ih->ih_vid,
261 (afs_uint32)(infdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
262 (afs_uint32)(infdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
263 rx_Write(m->call, m->line, strlen(m->line));
266 outfdP = IH_OPEN(outh);
268 sprintf(m->line, "Couldn't open output directory %u.%u.%u\n",
269 outfdP->fd_ih->ih_vid,
270 (afs_uint32)(outfdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
271 (afs_uint32)(outfdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
272 rx_Write(m->call, m->line, strlen(m->line));
273 FDH_REALLYCLOSE(infdP);
278 size = FDH_SIZE(infdP);
281 tlen = size > 2048 ? 2048 : size;
282 if (FDH_PREAD(infdP, tbuf, tlen, offset) != tlen) {
283 sprintf(m->line, "Couldn't read directory %u.%u.%u\n",
284 infdP->fd_ih->ih_vid,
285 (afs_uint32)(infdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
286 (afs_uint32)(infdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
287 rx_Write(m->call, m->line, strlen(m->line));
288 FDH_REALLYCLOSE(infdP);
289 FDH_REALLYCLOSE(outfdP);
293 if (FDH_PWRITE(outfdP, tbuf, tlen, offset) != tlen) {
294 sprintf(m->line, "Couldn't write directory %u.%u.%u\n",
295 outfdP->fd_ih->ih_vid,
296 (afs_uint32)(outfdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
297 (afs_uint32)(outfdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
298 rx_Write(m->call, m->line, strlen(m->line));
299 FDH_REALLYCLOSE(infdP);
300 FDH_REALLYCLOSE(outfdP);
309 FDH_REALLYCLOSE(infdP);
313 afs_int32 copyVnodes(struct Msg *m, Volume *vol, Volume *newvol,
315 struct VnodeExtract *list, afs_int32 length,
316 afs_int32 where, afs_uint64 *blocks,
317 struct VnodeDiskObject *parVnode)
319 afs_int32 i, code = 0;
320 char buf[SIZEOF_LARGEDISKVNODE];
321 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)&buf;
323 FdHandle_t *newfdP = 0;
324 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
325 struct VnodeExtract *e;
330 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
332 Log("Couldn't open %s Index of volume %u\n",
333 class ? "small":"large", V_id(vol));
337 newfdP = IH_OPEN(newvol->vnodeIndex[class].handle);
339 Log("Couldn't open %s Index of volume %u\n",
340 class ? "small":"large", V_id(newvol));
344 size = FDH_SIZE(fdP);
346 for (i=0; i<length; i++) {
350 offset = (e->vN + 1 - class) << (vcp->logSize -1);
351 if (FDH_PREAD(fdP, vnode, vcp->diskSize, offset) != vcp->diskSize) {
352 Log("Couldn't read in %s Index of volume %u at offset %llu\n",
353 class ? "small":"large", V_id(vol), offset);
357 if (e->flag & PARENT) {
359 * do a preventive copy on write for later update
363 #if defined(NEARINODE_HINT) && !defined(AFS_NAMEI_ENV)
365 V_pref(vol,nearInode)
368 newino = IH_CREATE(V_linkHandle(vol), V_device(vol),
369 VPartitionPath(V_partition(vol)),
370 nearInode, V_parentId(vol),
371 e->vN, vnode->uniquifier,
373 IH_INIT(newh, V_device(vol), V_parentId(vol), newino);
374 ino = VNDISK_GET_INO(vnode);
375 IH_INIT(h, V_device(vol), V_parentId(vol), ino);
376 code = copyDir(m, h, newh);
379 /* Now update the vnode and write it back to disk */
380 VNDISK_SET_INO(vnode, newino);
382 if (FDH_PWRITE(fdP, vnode, vcp->diskSize, offset) != vcp->diskSize) {
383 Log("Couldn't write in %s Index of volume %u at offset %llu\n",
384 class ? "small":"large", V_id(vol), offset);
388 memcpy(parVnode, vnode, sizeof(struct VnodeDiskObject));
390 if (e->flag & NEEDED && e->vN != where) {
391 VNDISK_GET_LEN(size, vnode);
392 *blocks += (size + 0x3ff) >> 10;
393 ino = VNDISK_GET_INO(vnode);
397 #if defined(NEARINODE_HINT) && !defined(AFS_NAMEI_ENV)
398 V_pref(vol,nearInode)
400 IH_INIT(h, vol->device, V_parentId(vol), ino);
401 if (e->parent == where)
403 newino = IH_CREATE(V_linkHandle(newvol), V_device(newvol),
404 VPartitionPath(V_partition(newvol)),
405 nearInode, V_parentId(newvol),
406 e->vN, vnode->uniquifier,
408 if (!VALID_INO(newino)) {
409 Log("IH_CREATE failed for %u.%u.%u\n",
410 V_id(newvol), e->vN, vnode->uniquifier);
415 IH_INIT(newh, newvol->device, V_parentId(newvol), newino);
416 code = namei_replace_file_by_hardlink(newh, h);
417 VNDISK_SET_INO(vnode, newino);
418 #ifdef AFS_RXOSD_SUPPORT
420 code = osd_split_objects(vol, newvol, vnode, e->vN);
421 #endif /* AFS_RXOSD_SUPPORT */
425 if (e->flag & CHANGEPARENT)
426 vnode->parent = 1; /* in new root-directory */
428 if (FDH_PWRITE(newfdP, vnode, vcp->diskSize, offset) != vcp->diskSize) {
429 Log("Couldn't write in %s Index of volume %u to offset %llu\n",
430 class ? "small":"large", V_id(newvol), offset);
438 * Now copy the root directory from old to new volume
440 if (class == vLarge) {
442 char buf2[SIZEOF_LARGEDISKVNODE];
443 struct VnodeDiskObject *vnode2 = (struct VnodeDiskObject *)&buf2;
444 afs_uint64 newoffset;
446 newoffset = vcp->diskSize;
447 if (FDH_PREAD(newfdP, vnode2, vcp->diskSize, newoffset) != vcp->diskSize) {
448 Log("splitvolume: couldn't read in large Index of new volume %u at offset %u\n",
449 V_id(newvol), vcp->diskSize);
453 offset = (where + 1 - class) << (vcp->logSize -1);
454 if (FDH_PREAD(fdP, vnode, vcp->diskSize, offset) != vcp->diskSize) {
455 Log("Couldn't read in large Index of old volume %u at offset %llu\n",
460 VNDISK_GET_LEN(size, vnode);
461 *blocks += (size + 0x3ff) >> 10;
462 ino = VNDISK_GET_INO(vnode);
463 IH_INIT(h, vol->device, V_parentId(vol), ino);
464 newino = VNDISK_GET_INO(vnode2);
465 IH_INIT(newh, newvol->device, V_parentId(newvol), newino);
466 code = copyDir(m, h, newh);
468 Log("splitvolume: copyDir failed for new root from "
469 "%u.%u.%u to %u.1.1\n",
470 V_id(vol), where, vnode->uniquifier, V_id(newvol));
474 VNDISK_SET_INO(vnode, newino);
475 vnode->uniquifier = 1;
477 vnode->parent = vnode2->parent;
478 vnode->serverModifyTime = vnode2->serverModifyTime;
479 if (FDH_PWRITE(newfdP, vnode, vcp->diskSize, newoffset) != vcp->diskSize) {
480 Log("splitvolume: couldn't write in large Index of %u at offset %u\n",
481 V_id(newvol), vcp->diskSize);
494 findName(Volume *vol, struct VnodeDiskObject *vd, afs_uint32 vN,
495 afs_uint32 un, char *name,afs_int32 length)
501 ino = VNDISK_GET_INO(vd);
502 SetSalvageDirHandle(&dir, V_id(vol), V_device(vol), ino);
504 code = InverseLookup(&dir, vN, un, name, length);
510 createMountpoint(Volume *vol, Volume *newvol, struct VnodeDiskObject *parent,
511 afs_uint32 vN, struct VnodeDiskObject *vd, char *name)
517 struct VnodeDiskObject vnode;
518 FdHandle_t *fdP, *fdP2;
521 afs_int32 class = vSmall;
522 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
523 #if defined(NEARINODE_HINT) && !defined(AFS_NAMEI_ENV)
532 FT_GetTimeOfDay(&now, 0);
533 fdP = IH_OPEN(vol->vnodeIndex[vSmall].handle);
535 Log("split volume: error opening small vnode index of %u\n", V_id(vol));
538 offset = vcp->diskSize;
540 rc = FDH_PREAD(fdP, &vnode, vcp->diskSize, offset);
541 if (rc != vcp->diskSize) {
543 Log("split volume: error reading small vnode index of %u\n", V_id(vol));
548 if (rc < vcp->diskSize)
551 if (vnode.type == vNull)
553 offset += vcp->diskSize;
555 memset(&vnode, 0, sizeof(vnode));
556 vnode.type = vSymlink;
557 V_nextVnodeUnique(vol)++;
558 vnode.uniquifier = V_nextVnodeUnique(vol);
559 vnode.author = vd->author;
560 vnode.owner = vd->owner;
561 vnode.group = vd->group;
562 vnode.modeBits = 0644;
563 vnode.unixModifyTime = now.tv_sec;
564 vnode.serverModifyTime = now.tv_sec;
565 vnode.dataVersion = 1;
569 newvN = (offset >> (VnodeClassInfo[class].logSize - 1)) - 1 + class;
570 #if defined(NEARINODE_HINT) && !defined(AFS_NAMEI_ENV)
571 V_pref(vol,nearInode)
573 newino = IH_CREATE(V_linkHandle(vol), V_device(vol),
574 VPartitionPath(V_partition(vol)), nearInode,
575 V_parentId(vol), newvN, vnode.uniquifier, 1);
577 IH_INIT(h, V_device(vol), V_parentId(vol), newino);
580 Log("split volume: couldn't open inode for mountpoint %u.%u.%u\n",
581 V_id(vol), newvN, vnode.uniquifier);
584 sprintf(symlink, "#%s", V_name(newvol));
585 size = strlen(symlink) + 1;
586 if (FDH_PWRITE(fdP2, symlink, size, 0) != size) {
587 Log("split volume: couldn't write mountpoint %u.%u.%u\n",
588 V_id(vol), newvN, vnode.uniquifier);
591 FDH_REALLYCLOSE(fdP2);
593 VNDISK_SET_INO(&vnode, newino);
594 VNDISK_SET_LEN(&vnode, size);
595 #ifndef AFS_RXOSD_SUPPORT
596 vnode.vnodeMagic = SMALLVNODEMAGIC;
598 if (FDH_PWRITE(fdP, &vnode, vcp->diskSize, offset) != vcp->diskSize) {
599 Log("split volume: couldn't write vnode for mountpoint %u.%u.%u\n",
600 V_id(vol), newvN, vnode.uniquifier);
603 FDH_REALLYCLOSE(fdP);
605 fid.Volume = V_id(vol);
607 fid.Unique = vnode.uniquifier;
610 * Now update the parent directory.
613 ino = VNDISK_GET_INO(parent);
614 SetSalvageDirHandle(&dir, V_id(vol), V_device(vol), ino);
616 code = Delete(&dir, name);
618 Log("splitvolume: couldn't delete directory entry for %s in %u.%u.%u, code = %d\n",
619 name, V_id(vol), vN, parent->uniquifier, code);
622 code = Create(&dir, name, &fid);
626 vcp = &VnodeClassInfo[class];
627 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
628 offset = (vN + 1 - class) << (vcp->logSize -1);
629 parent->dataVersion++;
630 if (FDH_PWRITE(fdP, parent, vcp->diskSize, offset) != 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));
662 for (i=0; i<length; i++) {
664 if (e->flag & NEEDED) {
665 offset = (e->vN + 1 - class) << (vcp->logSize -1);
666 if (FDH_PREAD(fdP, vnode, vcp->diskSize, offset) != vcp->diskSize) {
667 Log("Couldn't read in %s Index of volume %u at offset %llu\n",
668 class ? "small":"large", V_id(vol), offset);
672 VNDISK_GET_LEN(size, vnode);
673 *blocks += (size + 0x3ff) >> 10;
674 ino = VNDISK_GET_INO(vnode);
677 IH_INIT(h, vol->device, V_parentId(vol), ino);
678 IH_DEC(h, ino, V_parentId(vol));
679 #ifdef AFS_RXOSD_SUPPORT
681 code = osdRemove(vol, vnode, e->vN);
682 #endif /* AFS_RXOSD_SUPPORT */
684 memset(vnode, 0, vcp->diskSize);
686 if (FDH_PWRITE(fdP, vnode, vcp->diskSize, offset) != vcp->diskSize) {
687 Log("Couldn't write in %s Index of volume %u to offset %llu\n",
688 class ? "small":"large", V_id(vol), offset);
699 split_volume(struct rx_call *call, Volume *vol, Volume *newvol,
700 afs_uint32 where, afs_int32 verbose)
703 struct VnodeExtract *dirList = 0;
704 struct VnodeExtract *fileList = 0;
705 afs_uint64 blocks = 0;
706 afs_uint32 filesNeeded, dirsNeeded;
708 char buf[SIZEOF_LARGEDISKVNODE];
709 char buf2[SIZEOF_LARGEDISKVNODE];
710 struct VnodeDiskObject *rootVnode = (struct VnodeDiskObject *)&buf;
711 struct VnodeDiskObject *parVnode = (struct VnodeDiskObject *)&buf2;
716 m = (struct Msg *) malloc(sizeof(struct Msg));
717 memset(m, 0, sizeof(struct Msg));
719 m->verbose = verbose;
722 * First step: planning
724 * Find out which directories will belong to the new volume
729 "1st step: extract vnode essence from large vnode file\n");
730 rx_Write(m->call, m->line, strlen(m->line));
733 code = ExtractVnodes(m, vol, vLarge, &dirList, &dl, where, rootVnode,
737 "ExtractVnodes failed for %u for directories with code %d\n",
739 rx_Write(m->call, m->line, strlen(m->line));
744 sprintf(m->line, "2nd step: look for name of vnode %u in directory %u.%u.%u\n",
745 where, V_id(vol), parent, parVnode->uniquifier);
746 rx_Write(m->call, m->line, strlen(m->line));
748 code = findName(vol, parVnode, where, rootVnode->uniquifier,
752 "splitvolume: could'nt find name of %u in directory %u.%u.%u.\n",
753 where, V_id(vol), parent, parVnode->uniquifier);
754 rx_Write(m->call, m->line, strlen(m->line));
758 sprintf(m->line, "name of %u is %s\n", where, name);
759 rx_Write(m->call, m->line, strlen(m->line));
763 sprintf(m->line, "3rd step: find all directory vnodes belonging to the subtree under %u \"%s\"\n",
765 rx_Write(m->call, m->line, strlen(m->line));
767 code = FindVnodes(m, where, dirList, dl, dirList, dl, &dirsNeeded, 1);
770 "FindVnodes for directories failed with code %d\n", code);
771 rx_Write(m->call, m->line, strlen(m->line));
776 sprintf(m->line, "4th step extract vnode essence from small vnode file\n");
777 rx_Write(m->call, m->line, strlen(m->line));
779 code = ExtractVnodes(m, vol, vSmall, &fileList, &fl, where, 0, 0, 0);
782 "ExtractVnodes failed for %u for files with code %d\n",
784 rx_Write(m->call, m->line, strlen(m->line));
788 sprintf(m->line, "5th step: find all small vnodes belonging to the subtree under %u \"%s\"\n",
790 rx_Write(m->call, m->line, strlen(m->line));
792 FindVnodes(m, where, fileList, fl, dirList, dl, &filesNeeded, 0);
795 * Third step: create hard links for all files needed
799 V_destroyMe(newvol) = DESTROY_ME;
800 V_inService(newvol) = 0;
802 sprintf(m->line, "6th step: create hard links in the AFSIDat tree between files of the old and new volume\n");
803 rx_Write(m->call, m->line, strlen(m->line));
805 code = copyVnodes(m, vol, newvol, 1, fileList, fl, where, &blocks, 0);
807 sprintf(m->line, "copyVnodes for files failed with code %d\n", code);
808 rx_Write(m->call, m->line, strlen(m->line));
813 * Forth step: create hard links for all directories and copy
814 * split directory to new root directory
818 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",
820 rx_Write(m->call, m->line, strlen(m->line));
822 code = copyVnodes(m, vol, newvol, 0, dirList, dl, where, &blocks, parVnode);
824 sprintf(m->line, "copyVnodes for directories failed with code %d\n", code);
825 rx_Write(m->call, m->line, strlen(m->line));
830 * Finalize new volume
834 sprintf(m->line, "8th step: write new volume's metadata to disk\n");
835 rx_Write(m->call, m->line, strlen(m->line));
838 V_diskused(newvol) = blocks;
839 #ifdef AFS_RXOSD_SUPPORT
840 V_osdFlag(newvol) = V_osdFlag(vol);
842 V_filecount(newvol) = filesNeeded + dirsNeeded;
843 V_destroyMe(newvol) = 0;
844 V_maxquota(newvol) = V_maxquota(vol);
845 V_uniquifier(newvol) = V_uniquifier(vol);
846 V_inService(newvol) = 1;
847 VUpdateVolume(&code, newvol);
850 * Sixth step: change directory entry in old volume:
851 * rename old tree and create mount point for new volume.
854 sprintf(m->line, "9th step: create mountpoint \"%s\" for new volume in old volume's directory %u.\n", name, parent);
855 rx_Write(m->call, m->line, strlen(m->line));
858 code = createMountpoint(vol, newvol, parVnode, parent, rootVnode, name);
860 sprintf(m->line, "createMountpoint failed with code %d\n", code);
861 rx_Write(m->call, m->line, strlen(m->line));
865 * Now both volumes should be ready and consistent, but the old volume
866 * contains still the vnodes and data we transferred into the new one.
867 * Delete orphaned vnodes and data.
872 sprintf(m->line, "10th step: delete large vnodes belonging to subtree in the old volume.\n");
873 rx_Write(m->call, m->line, strlen(m->line));
875 deleteVnodes(vol, vLarge, dirList, dl, &blocks);
877 sprintf(m->line, "11th step: delete small vnodes belonging to subtree in the old volume.\n");
878 rx_Write(m->call, m->line, strlen(m->line));
880 deleteVnodes(vol, vSmall, fileList, fl, &blocks);
881 V_diskused(vol) -= blocks;
882 V_filecount(vol) -= (filesNeeded + dirsNeeded + 1);
883 VUpdateVolume(&code, vol);
885 sprintf(m->line, "Finished!\n");
886 rx_Write(m->call, m->line, strlen(m->line));
891 rx_Write(m->call, m->line, 4);