2 * Copyright (c) 2007, Hartmut Reuter,
3 * RZG, Max-Planck-Institut f. Plasmaphysik.
11 #include <sys/types.h>
13 #ifdef AFS_PTHREAD_ENV
15 #else /* AFS_PTHREAD_ENV */
16 #include <afs/assert.h>
17 #endif /* AFS_PTHREAD_ENV */
39 #include <afs/afsint.h>
43 #include <afs/afssyscalls.h>
47 #include "partition.h"
48 #include "viceinode.h"
50 #ifdef AFS_RXOSD_SUPPORT
53 #include "../vol/vol_osd_prototypes.h"
58 #define CHANGEPARENT 4
60 #define NAMEI_VNODEMASK 0x03ffffff
61 #define NAMEI_TAGMASK 0x7
62 #define NAMEI_TAGSHIFT 26
63 #define NAMEI_UNIQMASK 0xffffffff
64 #define NAMEI_UNIQSHIFT 32
73 struct rx_call * call;
78 afs_int32 ExtractVnodes(struct Msg *m, Volume *vol, afs_int32 class,
79 struct VnodeExtract **list,
80 afs_int32 *length, afs_uint32 where,
81 struct VnodeDiskObject *vd,
82 afs_int32 *parent, struct VnodeDiskObject *parentvd)
85 char buf[SIZEOF_LARGEDISKVNODE];
86 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)&buf;
88 StreamHandle_t *stream = 0;
89 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
90 struct VnodeExtract *e;
99 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
101 sprintf(m->line, "Couldn't open %s Index of volume %u\n",
102 class ? "small":"large", V_id(vol));
103 rx_Write(m->call, m->line, strlen(m->line));
107 size = FDH_SIZE(fdP);
108 *list = (struct VnodeExtract *) malloc(size / vcp->diskSize
109 * sizeof(struct VnodeExtract));
114 memset(*list, 0, size / vcp->diskSize * sizeof(struct VnodeExtract));
115 stream = FDH_FDOPEN(fdP, "r");
117 sprintf(m->line, "Couldn't stream open %s Index of volume %u\n",
118 class ? "small":"large", V_id(vol));
119 rx_Write(m->call, m->line, strlen(m->line));
123 code = STREAM_SEEK(stream, vcp->diskSize, 0);
127 offset = vcp->diskSize;
129 while (!STREAM_EOF(stream)) {
130 afs_int32 vN = (offset >> (vcp->logSize -1)) - 1 + class;
131 if (STREAM_READ(vnode, vcp->diskSize, 1, stream) == 1) {
132 if (vnode->type != vNull) {
134 e->parent = vnode->parent;
135 if (vN == where && class == vLarge) {
136 memcpy(vd, vnode, vcp->diskSize);
137 *parent = vnode->parent;
141 offset += vcp->diskSize;
144 *length = (e - *list);
145 if (class == vLarge) {
147 offset = (*parent + 1 - class) << (vcp->logSize -1);
148 code = STREAM_SEEK(stream, offset, 0);
149 if (STREAM_READ(vnode, vcp->diskSize, 1, stream) == 1)
150 memcpy(parentvd, vnode, vcp->diskSize);
154 sprintf(m->line, "SplitVolume: extract didn't see directory %u\n", where);
155 rx_Write(m->call, m->line, strlen(m->line));
160 sprintf(m->line, "Volume %u has %u %s vnodes in volume %uu\n",
161 V_parentId(vol), *length, class? "small":"large");
162 rx_Write(m->call, m->line, strlen(m->line));
167 STREAM_CLOSE(stream);
177 afs_int32 FindVnodes(struct Msg *m, afs_uint32 where,
178 struct VnodeExtract *list, afs_int32 length,
179 struct VnodeExtract *dlist, afs_int32 dlength,
180 afs_int32 *needed, afs_int32 class)
182 afs_int32 i, j, found = 0;
183 afs_int32 parent = 0;
186 for (i=0; i<length; i++) {
187 if (list[i].vN == where) { /* dir to be replaced by mount point */
188 list[i].flag |= NEEDED;
189 parent = list[i].parent;
193 if (list[i].parent == where) { /* all 1st generation children */
194 list[i].flag |= (NEEDED + CHANGEPARENT);
198 if (list[0].vN & 1) { /* only for directories */
201 "SplitVolume: directory %u where to start new volume not found\n",
203 rx_Write(m->call, m->line, strlen(m->line));
207 for (i=0; i<length; i++) {
208 if (list[i].vN == parent) { /* dir where to create mount point */
209 list[i].flag |= PARENT;
215 sprintf(m->line, "SplitVolume: parent directory %u not found\n",
217 rx_Write(m->call, m->line, strlen(m->line));
224 for (i=0; i<dlength; i++) {
225 if (!(dlist[i].flag & NEEDED)) /* dirs to remain in old volume */
227 for (j=0; j<length; j++) {
228 if (list[j].parent == dlist[i].vN && !(list[j].flag & NEEDED)) {
229 list[j].flag |= NEEDED;
237 sprintf(m->line, "%u %s vnodes will go into the new volume\n",
238 *needed, class ? "small" : "large");
239 rx_Write(m->call, m->line, strlen(m->line));
244 afs_int32 copyDir(struct Msg *m, IHandle_t *inh, IHandle_t *outh)
247 FdHandle_t *infdP, *outfdP;
251 infdP = IH_OPEN(inh);
253 sprintf(m->line, "Couldn't open input directory %u.%u.%u\n",
254 infdP->fd_ih->ih_vid,
255 (afs_uint32)(infdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
256 (afs_uint32)(infdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
257 rx_Write(m->call, m->line, strlen(m->line));
260 outfdP = IH_OPEN(outh);
262 sprintf(m->line, "Couldn't open output directory %u.%u.%u\n",
263 outfdP->fd_ih->ih_vid,
264 (afs_uint32)(outfdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
265 (afs_uint32)(outfdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
266 rx_Write(m->call, m->line, strlen(m->line));
267 FDH_REALLYCLOSE(infdP);
271 FDH_SEEK(infdP, 0, 0);
272 FDH_SEEK(outfdP, 0, 0);
273 size = FDH_SIZE(infdP);
276 tlen = size > 2048 ? 2048 : size;
277 if (FDH_READ(infdP, tbuf, tlen) != tlen) {
278 sprintf(m->line, "Couldn't read directory %u.%u.%u\n",
279 infdP->fd_ih->ih_vid,
280 (afs_uint32)(infdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
281 (afs_uint32)(infdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
282 rx_Write(m->call, m->line, strlen(m->line));
283 FDH_REALLYCLOSE(infdP);
284 FDH_REALLYCLOSE(outfdP);
288 if (FDH_WRITE(outfdP, tbuf, tlen) != tlen) {
289 sprintf(m->line, "Couldn't write directory %u.%u.%u\n",
290 outfdP->fd_ih->ih_vid,
291 (afs_uint32)(outfdP->fd_ih->ih_ino & NAMEI_VNODEMASK),
292 (afs_uint32)(outfdP->fd_ih->ih_ino >> NAMEI_UNIQSHIFT));
293 rx_Write(m->call, m->line, strlen(m->line));
294 FDH_REALLYCLOSE(infdP);
295 FDH_REALLYCLOSE(outfdP);
303 FDH_REALLYCLOSE(infdP);
307 afs_int32 copyVnodes(struct Msg *m, Volume *vol, Volume *newvol,
309 struct VnodeExtract *list, afs_int32 length,
310 afs_int32 where, afs_uint64 *blocks,
311 struct VnodeDiskObject *parVnode)
313 afs_int32 i, code = 0;
314 char buf[SIZEOF_LARGEDISKVNODE];
315 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)&buf;
317 FdHandle_t *newfdP = 0;
318 StreamHandle_t *newstream = 0;
319 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
320 struct VnodeExtract *e;
323 Inode ino, newino, nearInode;
326 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
328 Log("Couldn't open %s Index of volume %u\n",
329 class ? "small":"large", V_id(vol));
333 newfdP = IH_OPEN(newvol->vnodeIndex[class].handle);
335 Log("Couldn't open %s Index of volume %u\n",
336 class ? "small":"large", V_id(newvol));
340 size = FDH_SIZE(fdP);
342 for (i=0; i<length; i++) {
346 offset = (e->vN + 1 - class) << (vcp->logSize -1);
347 if (FDH_SEEK(fdP, offset, 0) != offset
348 || FDH_READ(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
349 Log("Couldn't read in %s Index of volume %u at offset\n",
350 class ? "small":"large", V_id(vol), offset);
354 if (e->flag & PARENT) {
356 * do a preventive copy on write for later update
360 FdHandle_t *infdP = 0;
361 FdHandle_t *outfdP = 0;
362 char *tbuf = malloc(2048);
363 newino = IH_CREATE(V_linkHandle(vol), V_device(vol),
364 VPartitionPath(V_partition(vol)),
365 nearInode, V_parentId(vol),
366 e->vN, vnode->uniquifier,
368 IH_INIT(newh, V_device(vol), V_parentId(vol), newino);
369 ino = VNDISK_GET_INO(vnode);
370 IH_INIT(h, V_device(vol), V_parentId(vol), ino);
371 code = copyDir(m, h, newh);
374 /* Now update the vnode and write it back to disk */
375 VNDISK_SET_INO(vnode, newino);
377 if (FDH_SEEK(fdP, offset, 0) != offset
378 || FDH_WRITE(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
379 Log("Couldn't write in %s Index of volume %u at offset\n",
380 class ? "small":"large", V_id(vol), offset);
384 memcpy(parVnode, vnode, sizeof(struct VnodeDiskObject));
386 if (e->flag & NEEDED && e->vN != where) {
387 VNDISK_GET_LEN(size, vnode);
388 *blocks += (size + 0x3ff) >> 10;
389 ino = VNDISK_GET_INO(vnode);
392 IH_INIT(h, vol->device, V_parentId(vol), ino);
393 if (e->parent == where)
395 newino = IH_CREATE(V_linkHandle(newvol), V_device(newvol),
396 VPartitionPath(V_partition(newvol)),
397 nearInode, V_parentId(newvol),
398 e->vN, vnode->uniquifier,
400 if (!VALID_INO(newino)) {
401 Log("IH_CREATE failed for %u.%u.%u\n",
402 V_id(newvol), e->vN, vnode->uniquifier);
407 IH_INIT(newh, newvol->device, V_parentId(newvol), newino);
408 code = namei_replace_file_by_hardlink(newh, h);
409 VNDISK_SET_INO(vnode, newino);
410 #ifdef AFS_RXOSD_SUPPORT
412 code = osd_split_objects(vol, newvol, vnode, e->vN);
413 #endif /* AFS_RXOSD_SUPPORT */
417 if (e->flag & CHANGEPARENT)
418 vnode->parent = 1; /* in new root-directory */
420 if (FDH_SEEK(newfdP, offset, 0) != offset
421 || FDH_WRITE(newfdP, vnode, vcp->diskSize) != vcp->diskSize) {
422 Log("Couldn't write in %s Index of volume %u to offset\n",
423 class ? "small":"large", V_id(newvol),
432 * Now copy the root directory from old to new volume
434 if (class == vLarge) {
436 char buf2[SIZEOF_LARGEDISKVNODE];
437 struct VnodeDiskObject *vnode2 = (struct VnodeDiskObject *)&buf2;
438 afs_uint64 newoffset;
440 newoffset = vcp->diskSize;
441 if (FDH_SEEK(newfdP, newoffset, 0) != newoffset
442 || FDH_READ(newfdP, vnode2, vcp->diskSize) != vcp->diskSize) {
443 Log("splitvolume: couldn't read in large Index of new volume %u at offset %u\n",
444 V_id(newvol), vcp->diskSize);
448 offset = (where + 1 - class) << (vcp->logSize -1);
449 if (FDH_SEEK(fdP, offset, 0) != offset
450 || FDH_READ(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
451 Log("Couldn't read in large Index of old volume %u at offset\n",
456 VNDISK_GET_LEN(size, vnode);
457 *blocks += (size + 0x3ff) >> 10;
458 ino = VNDISK_GET_INO(vnode);
459 IH_INIT(h, vol->device, V_parentId(vol), ino);
460 newino = VNDISK_GET_INO(vnode2);
461 IH_INIT(newh, newvol->device, V_parentId(newvol), newino);
462 code = copyDir(m, h, newh);
464 Log("splitvolume: copyDir failed for new root from %u.u.u to %u.1.1\n",
465 V_id(vol), where, vnode->uniquifier, V_id(newvol));
469 VNDISK_SET_INO(vnode, newino);
470 vnode->uniquifier = 1;
472 vnode->parent = vnode2->parent;
473 vnode->serverModifyTime = vnode2->serverModifyTime;
474 if (FDH_SEEK(newfdP, newoffset, 0) != newoffset
475 || FDH_WRITE(newfdP, vnode, vcp->diskSize) != vcp->diskSize) {
476 Log("splitvolume: couldn't write in large Index of %u at offset %u\n",
477 V_id(newvol), vcp->diskSize);
490 findName(Volume *vol, struct VnodeDiskObject *vd, afs_uint32 vN, afs_uint32 un,
491 char *name,afs_int32 length)
497 ino = VNDISK_GET_INO(vd);
498 SetSalvageDirHandle(&dir, V_id(vol), V_device(vol), ino);
500 code = InverseLookup(&dir, vN, un, name, length);
506 createMountpoint(Volume *vol, Volume *newvol, struct VnodeDiskObject *parent,
507 afs_uint32 vN, struct VnodeDiskObject *vd, char *name)
513 struct VnodeDiskObject vnode;
514 FdHandle_t *fdP, *fdP2;
515 afs_uint64 offset, size;
516 afs_int32 class = vSmall;
517 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
523 TM_GetTimeOfDay(&now, 0);
524 fdP = IH_OPEN(vol->vnodeIndex[vSmall].handle);
526 Log("split volume: error opening small vnode index of %u\n", V_id(vol));
529 offset = vcp->diskSize;
530 if (FDH_SEEK(fdP, offset, 0) != offset) {
531 Log("split volume: error seeking in small vnode index of %u\n", V_id(vol));
535 if (FDH_READ(fdP, &vnode, vcp->diskSize) != vcp->diskSize)
537 if (vnode.type == vNull)
539 offset += vcp->diskSize;
541 memset(&vnode, 0, sizeof(vnode));
542 vnode.type = vSymlink;
543 V_nextVnodeUnique(vol)++;
544 vnode.uniquifier = V_nextVnodeUnique(vol);
545 vnode.author = vd->author;
546 vnode.owner = vd->owner;
547 vnode.group = vd->group;
548 vnode.modeBits = 0644;
549 vnode.unixModifyTime = now.tv_sec;
550 vnode.serverModifyTime = now.tv_sec;
551 vnode.dataVersion = 1;
555 newvN = (offset >> (VnodeClassInfo[class].logSize - 1)) - 1 + class;
556 newino = IH_CREATE(V_linkHandle(vol), V_device(vol),
557 VPartitionPath(V_partition(vol)), nearInode,
558 V_parentId(vol), newvN, vnode.uniquifier, 1);
560 IH_INIT(h, V_device(vol), V_parentId(vol), newino);
563 Log("split volume: couldn't open inode for mountpoint %u.%u.%u\n",
564 V_id(vol), newvN, vnode.uniquifier);
567 FDH_SEEK(fdP2, 0, 0);
568 sprintf(&symlink, "#%s", V_name(newvol));
569 size = strlen(symlink) + 1;
570 if (FDH_WRITE(fdP2, &symlink, size) != 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_SEEK(fdP, offset, 0) != offset
583 || FDH_WRITE(fdP, &vnode, vcp->diskSize) != vcp->diskSize) {
584 Log("split volume: couldn't write vnode for mountpoint %u.%u.%u\n",
585 V_id(vol), newvN, vnode.uniquifier);
588 FDH_REALLYCLOSE(fdP);
590 fid.Volume = V_id(vol);
592 fid.Unique = vnode.uniquifier;
595 * Now update the parent directory.
598 ino = VNDISK_GET_INO(parent);
599 SetSalvageDirHandle(&dir, V_id(vol), V_device(vol), ino);
601 code = Delete(&dir, name);
603 Log("splitvolume: couldn't delete directory entry for %s in %u.%u.%u, code = %d\n",
604 name, V_id(vol), vN, parent->uniquifier, code);
607 code = Create(&dir, name, &fid);
611 vcp = &VnodeClassInfo[class];
612 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
613 offset = (vN + 1 - class) << (vcp->logSize -1);
614 parent->dataVersion++;
615 if (FDH_SEEK(fdP, offset, 0) != offset
616 || FDH_WRITE(fdP, parent, vcp->diskSize) != vcp->diskSize) {
617 Log("split volume: couldn't write vnode for parent directory %u.%u.%u\n",
618 V_id(vol), vN, parent->uniquifier);
621 FDH_REALLYCLOSE(fdP);
625 afs_int32 deleteVnodes(Volume *vol, afs_int32 class,
626 struct VnodeExtract *list, afs_int32 length,
629 afs_int32 i, code = 0;
630 char buf[SIZEOF_LARGEDISKVNODE];
631 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)&buf;
633 struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
634 struct VnodeExtract *e;
639 fdP = IH_OPEN(vol->vnodeIndex[class].handle);
641 Log("Couldn't open %s Index of volume %u\n",
642 class ? "small":"large", V_id(vol));
646 size = FDH_SIZE(fdP);
648 for (i=0; i<length; i++) {
650 if (e->flag & NEEDED) {
652 offset = (e->vN + 1 - class) << (vcp->logSize -1);
653 if (FDH_SEEK(fdP, offset, 0) != offset) {
654 Log("Couldn't seek in %s Index of volume %u to offset\n",
655 class ? "small":"large", V_id(vol), offset);
659 if (FDH_READ(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
660 Log("Couldn't read in %s Index of volume %u at offset\n",
661 class ? "small":"large", V_id(vol), offset);
665 VNDISK_GET_LEN(size, vnode);
666 *blocks += (size + 0x3ff) >> 10;
667 ino = VNDISK_GET_INO(vnode);
670 IH_INIT(h, vol->device, V_parentId(vol), ino);
671 IH_DEC(h, ino, V_parentId(vol));
672 #ifdef AFS_RXOSD_SUPPORT
674 code = osdRemove(vol, vnode, e->vN);
675 #endif /* AFS_RXOSD_SUPPORT */
677 memset(vnode, 0, vcp->diskSize);
679 if (FDH_SEEK(fdP, offset, 0) != offset
680 || FDH_WRITE(fdP, vnode, vcp->diskSize) != vcp->diskSize) {
681 Log("Couldn't write in %s Index of volume %u to offset\n",
682 class ? "small":"large", V_id(vol),
693 split_volume(struct rx_call *call, Volume *vol, Volume *newvol,
694 afs_uint32 where, afs_int32 verbose)
697 struct VnodeExtract *dirList = 0;
698 struct VnodeExtract *fileList = 0;
699 afs_uint64 blocks = 0;
700 afs_uint32 filesNeeded, dirsNeeded;
702 char buf[SIZEOF_LARGEDISKVNODE];
703 char buf2[SIZEOF_LARGEDISKVNODE];
704 struct VnodeDiskObject *rootVnode = (struct VnodeDiskObject *)&buf;
705 struct VnodeDiskObject *parVnode = (struct VnodeDiskObject *)&buf2;
710 m = (struct Msg *) malloc(sizeof(struct Msg));
711 memset(m, 0, sizeof(struct Msg));
713 m->verbose = verbose;
716 * First step: planning
718 * Find out which directories will belong to the new volume
723 "1st step: extract vnode essence from large vnode file\n");
724 rx_Write(m->call, m->line, strlen(m->line));
727 code = ExtractVnodes(m, vol, vLarge, &dirList, &dl, where, rootVnode,
731 "ExtractVnodes failed for %u for directories with code %d\n",
733 rx_Write(m->call, m->line, strlen(m->line));
738 sprintf(m->line, "2nd step: look for name of vnode %u in directory %u.%u.%u\n",
739 where, V_id(vol), parent, parVnode->uniquifier);
740 rx_Write(m->call, m->line, strlen(m->line));
742 code = findName(vol, parVnode, where, rootVnode->uniquifier,
743 &name, sizeof(name));
746 "splitvolume: could'nt find name of %u in directory %u.%u.%u.\n",
747 where, V_id(vol), parent, parVnode->uniquifier);
748 rx_Write(m->call, m->line, strlen(m->line));
752 sprintf(m->line, "name of %u is %s\n", where, name);
753 rx_Write(m->call, m->line, strlen(m->line));
757 sprintf(m->line, "3rd step: find all directory vnodes belonging to the subtree under %u \"%s\"\n",
759 rx_Write(m->call, m->line, strlen(m->line));
761 code = FindVnodes(m, where, dirList, dl, dirList, dl, &dirsNeeded, 1);
764 "FindVnodes for directories failed with code %d\n", code);
765 rx_Write(m->call, m->line, strlen(m->line));
770 sprintf(m->line, "4th step extract vnode essence from small vnode file\n");
771 rx_Write(m->call, m->line, strlen(m->line));
773 code = ExtractVnodes(m, vol, vSmall, &fileList, &fl, where, 0, 0, 0);
776 "ExtractVnodes failed for %u for files with code %d\n",
778 rx_Write(m->call, m->line, strlen(m->line));
782 sprintf(m->line, "5th step: find all small vnodes belonging to the subtree under %u \"%s\"\n",
784 rx_Write(m->call, m->line, strlen(m->line));
786 FindVnodes(m, where, fileList, fl, dirList, dl, &filesNeeded, 0);
789 * Third step: create hard links for all files needed
793 V_destroyMe(newvol) = DESTROY_ME;
794 V_inService(newvol) = 0;
796 sprintf(m->line, "6th step: create hard links in the AFSIDat tree between files of the old and new volume\n");
797 rx_Write(m->call, m->line, strlen(m->line));
799 code = copyVnodes(m, vol, newvol, 1, fileList, fl, where, &blocks, 0);
801 sprintf(m->line, "copyVnodes for files failed with code %d\n", code);
802 rx_Write(m->call, m->line, strlen(m->line));
807 * Forth step: create hard links for all directories and copy
808 * split directory to new root directory
812 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",
814 rx_Write(m->call, m->line, strlen(m->line));
816 code = copyVnodes(m, vol, newvol, 0, dirList, dl, where, &blocks, parVnode);
818 sprintf(m->line, "copyVnodes for directories failed with code %d\n", code);
819 rx_Write(m->call, m->line, strlen(m->line));
824 * Finalize new volume
828 sprintf(m->line, "8th step: write new volume's metadata to disk\n");
829 rx_Write(m->call, m->line, strlen(m->line));
832 V_diskused(newvol) = blocks;
833 /*V_osdFlag(newvol) = V_osdFlag(vol);*/
834 V_filecount(newvol) = filesNeeded + dirsNeeded;
835 V_destroyMe(newvol) = 0;
836 V_maxquota(newvol) = V_maxquota(vol);
837 V_uniquifier(newvol) = V_uniquifier(vol);
838 V_inService(newvol) = 1;
839 VUpdateVolume(&code, newvol);
842 * Sixth step: change directory entry in old volume:
843 * rename old tree and create mount point for new volume.
846 sprintf(m->line, "9th step: create mountpoint \"%s\" for new volume in old volume's directory %u.\n", name, parent);
847 rx_Write(m->call, m->line, strlen(m->line));
850 code = createMountpoint(vol, newvol, parVnode, parent, rootVnode, name);
852 sprintf(m->line, "createMountpoint failed with code %d\n", code);
853 rx_Write(m->call, m->line, strlen(m->line));
857 * Now both volumes should be ready and consistent, but the old volume
858 * contains still the vnodes and data we transferred into the new one.
859 * Delete orphaned vnodes and data.
864 sprintf(m->line, "10th step: delete large vnodes belonging to subtree in the old volume.\n");
865 rx_Write(m->call, m->line, strlen(m->line));
867 deleteVnodes(vol, vLarge, dirList, dl, &blocks);
869 sprintf(m->line, "11th step: delete small vnodes belonging to subtree in the old volume.\n");
870 rx_Write(m->call, m->line, strlen(m->line));
872 deleteVnodes(vol, vSmall, fileList, fl, &blocks);
873 V_diskused(vol) -= blocks;
874 V_filecount(vol) -= (filesNeeded + dirsNeeded + 1);
875 VUpdateVolume(&code, vol);
877 sprintf(m->line, "Finished!\n");
878 rx_Write(m->call, m->line, strlen(m->line));
883 rx_Write(m->call, m->line, 4);