Esempio n. 1
0
// background routine for BlockReader to read the blocks in the
// background into the channel
//
// It uses triple buffering with chan of length 1. One block being
// filled, one block in the channel, and one block being used by the
// client.
func (br *BlockReader) background() {
	defer br.wg.Done()
	defer close(br.out)
	br.spare <- directio.AlignedBlock(BlockSize)
	br.spare <- directio.AlignedBlock(BlockSize)
	br.spare <- directio.AlignedBlock(BlockSize)
	for {
		block := <-br.spare
		_, err := io.ReadFull(br.in, block)
		if err != nil {
			if err == io.EOF {
				return
			}
			log.Fatalf("Error while reading %q: %s\n", br.file, err)
		}
		// FIXME bodge - don't account for reading from the random number
		if br.file != "random" {
			stats.Read(BlockSize)
		}
		select {
		case br.out <- block:
		case <-br.quit:
			return
		}
	}
}
Esempio n. 2
0
func TestDirectIo(t *testing.T) {
	// Make a temporary file name
	fd, err := ioutil.TempFile("", "direct_io_test")
	if err != nil {
		t.Fatal("Failed to make temp file", err)
	}
	path := fd.Name()
	fd.Close()

	// starting block
	block1 := directio.AlignedBlock(directio.BlockSize)
	for i := 0; i < len(block1); i++ {
		block1[i] = 'A'
	}

	// Write the file
	out, err := directio.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		t.Fatal("Failed to directio.OpenFile for read", err)
	}
	_, err = out.Write(block1)
	if err != nil {
		t.Fatal("Failed to write", err)
	}
	err = out.Close()
	if err != nil {
		t.Fatal("Failed to close writer", err)
	}

	// Read the file
	block2 := directio.AlignedBlock(directio.BlockSize)
	in, err := directio.OpenFile(path, os.O_RDONLY, 0666)
	if err != nil {
		t.Fatal("Failed to directio.OpenFile for write", err)
	}
	_, err = io.ReadFull(in, block2)
	if err != nil {
		t.Fatal("Failed to read", err)
	}
	err = in.Close()
	if err != nil {
		t.Fatal("Failed to close reader", err)
	}

	// Tidy
	err = os.Remove(path)
	if err != nil {
		t.Fatal("Failed to remove temp file", path, err)
	}

	// Compare
	if !bytes.Equal(block1, block2) {
		t.Fatal("Read not the same as written")
	}
}
Esempio n. 3
0
func (s *streamSender) Run() error {
	if err := s.prepare(); err != nil {
		return err
	}

	if err := s.putHeader(&s.header); err != nil {
		return err
	}

	if len(s.srcname) > 0 {
		// always activate original lv so that target lv can be activated later
		if err := lvmutil.ActivateLv(s.vgname, s.srcname); err != nil {
			return err
		}
		defer lvmutil.DeactivateLv(s.vgname, s.srcname)
	}

	if err := lvmutil.ActivateLv(s.vgname, s.lvname); err != nil {
		return err
	}
	defer lvmutil.DeactivateLv(s.vgname, s.lvname)

	devpath := lvmutil.LvDevicePath(s.vgname, s.lvname)
	devFile, err := directio.OpenFile(devpath, os.O_RDONLY, 0644)
	if err != nil {
		return err
	}
	defer devFile.Close()

	buf := directio.AlignedBlock(int(s.header.BlockSize))

	blockSize := int64(s.header.BlockSize)
	for _, e := range s.blocks {
		if e.OpType == thindump.DeltaOpDelete {
			for i := 0; i < len(buf); i++ {
				buf[i] = 0
			}
		} else {
			if _, err := devFile.Seek(e.OriginBlock*blockSize, os.SEEK_SET); err != nil {
				return err
			}

			if _, err := io.ReadFull(devFile, buf); err != nil {
				return err
			}
		}
		if err := s.putBlock(e.OriginBlock, buf); err != nil {
			return err
		}
	}

	return nil
}
Esempio n. 4
0
func (constor *Constor) Write(input *fuse.WriteIn, data []byte) (written uint32, code fuse.Status) {
	constor.log("%d %d", input.Fh, len(data))
	ptr := uintptr(input.Fh)
	offset := input.Offset
	wdata := data

	F := constor.getfd(ptr)
	if F == nil {
		constor.error("F == nil")
		return 0, fuse.EIO
	}
	if F.flags&syscall.O_DIRECT != 0 {
		wdata = directio.AlignedBlock(len(data))
		copy(wdata, data)
	}
	inode := constor.inodemap.findInodePtr(input.NodeId)
	if inode == nil {
		return 0, fuse.ENOENT
	}
	if F.layer != 0 && inode.layer != 0 {
		err := constor.copyup(inode)
		if err != nil {
			constor.error("%s", err)
			return 0, fuse.ToStatus(err)
		}
		path := constor.getPath(0, inode.id)
		syscall.Close(F.fd)
		fd, err := syscall.Open(path, F.flags, 0)
		if err != nil {
			constor.error("%s", err)
			return 0, fuse.ToStatus(err)
		}
		F.fd = fd
		F.layer = 0
		constor.log("reset fd for %s", path)
	} else if F.layer != 0 && inode.layer == 0 {
		syscall.Close(F.fd)
		path := constor.getPath(0, inode.id)
		fd, err := syscall.Open(path, F.flags, 0)
		if err != nil {
			constor.error("%s", err)
			return 0, fuse.ToStatus(err)
		}
		F.fd = fd
		F.layer = 0
		constor.log("reset fd for %s", path)
	}

	fd := F.fd
	n, err := syscall.Pwrite(fd, wdata, int64(offset))
	return uint32(n), fuse.ToStatus(err)
}
Esempio n. 5
0
func copyN(dst io.Writer, src io.Reader, amount int64) (int, error) {
	block := directio.AlignedBlock(int(amount))
	if _, err := src.Read(block); err != nil {
		return 0, err
	}

	s, err := dst.Write(block)
	if err != nil {
		return s, err
	}

	return s, nil
}
Esempio n. 6
0
func main() {
	// Get hold of the current working dir
	cwd, err := os.Getwd()
	fatalIfErr(err)

	// Create a temporary file
	fd, err := ioutil.TempFile(cwd, "sleepless")
	fatalIfErr(err)
	// We just need the file name, we're going to reopen it with the right flags
	path := fd.Name()
	fd.Close()

	// Allocate a block which will be filled with garbage on each iteration
	garbage := directio.AlignedBlock(directio.BlockSize)

	// Get ready
	out, err := directio.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_SYNC, 0600)
	fatalIfErr(err)

	// Setup signal handling
	sigint := make(chan os.Signal, 1)
	signal.Notify(sigint, os.Interrupt)
	go func() {
		<-sigint
		cleanup(out, path)
		os.Exit(0)
	}()

	// Start the main loop
	for {
		// Garbage in...
		if _, err = rand.Read(garbage); err != nil {
			cleanup(out, path)
			log.Fatal(err)
		}
		// ... garbage out
		if _, err = out.Write(garbage); err != nil {
			cleanup(out, path)
			log.Fatal(err)
		}
		// Rewind the file to the start so that it does not grow
		// indefintely
		if _, err = out.Seek(0, os.SEEK_SET); err != nil {
			cleanup(out, path)
			log.Fatal(err)
		}
		// Take a nap
		time.Sleep(10 * time.Second)
	}
}
Esempio n. 7
0
func (sr *streamRecver) recvNextStream() error {
	if err := sr.prepare(); err != nil {
		return err
	}

	devpath := lvmutil.LvDevicePath(sr.vgname, sr.lvname)
	devFile, err := directio.OpenFile(devpath, os.O_WRONLY, 0644)
	if err != nil {
		return err
	}
	defer devFile.Close()

	n := 8 + sr.header.BlockSize
	b := make([]byte, n+md5.Size)

	buf := directio.AlignedBlock(int(sr.header.BlockSize))

	for i := uint64(0); i < sr.header.BlockCount; i++ {
		if _, err := io.ReadFull(sr.r, b); err != nil {
			return err
		}

		sr.h.Reset()
		sr.h.Write(b[:n])
		if !bytes.Equal(sr.h.Sum(nil), b[n:n+md5.Size]) {
			return fmt.Errorf("check sum mismatch for %dst block", i)
		}

		index := int64(binary.BigEndian.Uint64(b))
		copy(buf, b[8:n])

		if _, err := devFile.Seek(int64(sr.header.BlockSize)*index, os.SEEK_SET); err != nil {
			return err
		}

		if _, err := devFile.Write(buf); err != nil {
			return err
		}
	}

	sr.prevUUID = string(sr.header.VolumeUUID[:])
	return nil
}
Esempio n. 8
0
func TestZeroSizedBlock(t *testing.T) {
	// This should not panic!
	directio.AlignedBlock(0)
}
Esempio n. 9
0
func AlignedBlock(size int) []byte {
	return directio.AlignedBlock(size)
}