Example #1
2
func coalesce(parentFile *os.File, childFile *os.File) error {
	blockSize, err := getFileSystemBlockSize(childFile)
	if err != nil {
		panic("can't get FS block size, error: " + err.Error())
	}
	var data, hole int64
	for {
		data, err = syscall.Seek(int(childFile.Fd()), hole, seekData)
		if err != nil {
			// reaches EOF
			errno := err.(syscall.Errno)
			if errno == syscall.ENXIO {
				break
			} else {
				// unexpected errors
				log.Fatal("Failed to syscall.Seek SEEK_DATA")
				return err
			}
		}
		hole, err = syscall.Seek(int(childFile.Fd()), data, seekHole)
		if err != nil {
			log.Fatal("Failed to syscall.Seek SEEK_HOLE")
			return err
		}

		// now we have a data start offset and length(hole - data)
		// let's read from child and write to parent file block by block
		_, err = parentFile.Seek(data, os.SEEK_SET)
		if err != nil {
			log.Fatal("Failed to os.Seek os.SEEK_SET")
			return err
		}

		offset := data
		buffer := fio.AllocateAligned(blockSize)
		for offset != hole {
			// read a block from child, maybe use bufio or Reader stream
			n, err := fio.ReadAt(childFile, buffer, offset)
			if n != len(buffer) || err != nil {
				log.Fatal("Failed to read from childFile")
				return err
			}
			// write a block to parent
			n, err = fio.WriteAt(parentFile, buffer, offset)
			if n != len(buffer) || err != nil {
				log.Fatal("Failed to write to parentFile")
				return err
			}
			offset += int64(n)
		}
	}

	return nil
}
Example #2
0
func (d *directFile) WriteAt(buf []byte, offset int64) (int, error) {
	return directfio.WriteAt(d.File, buf, offset)
}