int buffer_file_initw (buffer_file_t* bf, bd_t bd) { bf->bd = bd; bf->bd_size = buffer_size (bd); if (bf->bd_size == -1) { return -1; } bf->capacity = bf->bd_size * pagesize (); if (bf->bd_size != 0) { bf->ptr = buffer_map (bd); if (bf->ptr == 0) { return -1; } } else { bf->ptr = 0; } bf->size = sizeof (size_t); bf->position = sizeof (size_t); bf->can_update = true; return 0; }
T *setup(GLsizeiptr size) { glGenBuffers(1, &handle); bind(); glBufferData(target, size * sizeof(T), 0, GL_STATIC_DRAW); return (T *)buffer_map(target); }
static gboolean make_appbuf (AppBuf *appbuf, Device *device, int w, int h) { appbuf->buffer.device = device; appbuf->buffer.width = w; appbuf->buffer.height = h; if (!buffer_new (&appbuf->buffer) || !buffer_map(&appbuf->buffer)) return FALSE; appbuf->surface = cairo_image_surface_create_for_data (appbuf->buffer.pixels, CAIRO_FORMAT_ARGB32, appbuf->buffer.width, appbuf->buffer.height, appbuf->buffer.stride); appbuf->cr = cairo_create (appbuf->surface); return TRUE; }
int vga_op_list_initr (vga_op_list_t* vol, bd_t bda, bd_t bdb) { if (buffer_file_initr (&vol->bf, bda) != 0) { return -1; } if (buffer_file_read (&vol->bf, &vol->count, sizeof (size_t)) != 0) { return -1; } vol->bdb = bdb; vol->bdb_size = buffer_size (bdb); vol->ptr = buffer_map (bdb); return 0; }
int buffer_file_initr (buffer_file_t* bf, bd_t bd) { bf->bd = bd; bf->bd_size = buffer_size (bd); if (bf->bd_size == -1) { return -1; } bf->capacity = bf->bd_size * pagesize (); bf->ptr = buffer_map (bd); if (bf->ptr == 0) { return -1; } bf->size = *((size_t*)bf->ptr); bf->position = sizeof (size_t); bf->can_update = false; return 0; }
int buffer_file_write (buffer_file_t* bf, const void* ptr, size_t size) { if (!bf->can_update) { return -1; } size_t new_position = bf->position + size; if (new_position < bf->position) { /* Overflow. */ return -1; } /* Resize if necessary. */ if (bf->capacity < new_position) { buffer_unmap (bf->bd); bf->capacity = ALIGN_UP (new_position, pagesize ()); bf->bd_size = bf->capacity / pagesize (); if (buffer_resize (bf->bd, bf->bd_size) != 0) { return -1; } bf->ptr = buffer_map (bf->bd); if (bf->ptr == 0) { return -1; } } memcpy (bf->ptr + bf->position, ptr, size); bf->position = new_position; if (bf->position > bf->size) { bf->size = bf->position; *((size_t*)bf->ptr) = bf->size; } return 0; }
int buffer_file_put (buffer_file_t* bf, char c) { if (!bf->can_update) { return -1; } size_t new_position = bf->position + 1; if (new_position < bf->position) { /* Overflow. */ return -1; } /* Resize if necessary. */ if (bf->capacity < new_position) { buffer_unmap (bf->bd); bf->capacity = ALIGN_UP (new_position, pagesize ()); bf->bd_size = bf->capacity / pagesize (); if (buffer_resize (bf->bd, bf->bd_size) != 0) { return -1; } bf->ptr = buffer_map (bf->bd); if (bf->ptr == 0) { return -1; } } *((char*)(bf->ptr + bf->position)) = c; bf->position = new_position; if (bf->position > bf->size) { bf->size = bf->position; *((size_t*)bf->ptr) = bf->size; } return 0; }
T *map() { bind(); return (T *)buffer_map(target); }
/* * This is much the same as sfs_partialio, but intended for use with * metadata (e.g. directory entries). It assumes the objects being * handled are smaller than whole blocks, do not cross block * boundaries, and originate in the kernel. * * It is separate from sfs_partialio because, although there is no * such code in this version of SFS, it is often desirable when doing * more advanced things to handle metadata and user data I/O * differently. */ int sfs_metaio(struct sfs_vnode *sv, off_t actualpos, void *data, size_t len, enum uio_rw rw) { struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data; struct sfs_dinode *dino; off_t endpos; uint32_t vnblock; uint32_t blockoffset; daddr_t diskblock; struct buf *iobuf; char *ioptr; bool doalloc; int result; KASSERT(lock_do_i_hold(sv->sv_lock)); /* Figure out which block of the vnode (directory, whatever) this is */ vnblock = actualpos / SFS_BLOCKSIZE; blockoffset = actualpos % SFS_BLOCKSIZE; result = sfs_dinode_load(sv); if (result) { return result; } dino = sfs_dinode_map(sv); /* Get the disk block number */ doalloc = (rw == UIO_WRITE); result = sfs_bmap(sv, vnblock, doalloc, &diskblock); if (result) { sfs_dinode_unload(sv); return result; } if (diskblock == 0) { /* Should only get block 0 back if doalloc is false */ KASSERT(rw == UIO_READ); /* Sparse file, read as zeros. */ bzero(data, len); sfs_dinode_unload(sv); return 0; } /* Read the block */ result = buffer_read(&sfs->sfs_absfs, diskblock, SFS_BLOCKSIZE, &iobuf); if (result) { /* * XXX: if we allocated, do we need to discard * the block we allocated? urgh... */ sfs_dinode_unload(sv); return result; } ioptr = buffer_map(iobuf); if (rw == UIO_READ) { /* Copy out the selected region */ memcpy(data, ioptr + blockoffset, len); } else { // Journal this!!! ioptr = buffer_map(iobuf); void *old_data = ioptr + blockoffset; sfs_jphys_write_wrapper(sfs, /*context*/ NULL, jentry_meta_update( diskblock, blockoffset, len, old_data, data)); /* Update the selected region */ memcpy(ioptr + blockoffset, data, len); buffer_mark_dirty(iobuf); // Journalled (meta_update) /* Update the vnode size if needed */ endpos = actualpos + len; if (endpos > (off_t)dino->sfi_size) { sfs_jphys_write_wrapper(sfs, NULL, jentry_resize( sv->sv_ino, // disk_addr dino->sfi_size, // old_size endpos)); // new_size dino->sfi_size = endpos; sfs_dinode_mark_dirty(sv); } } buffer_release(iobuf); sfs_dinode_unload(sv); /* Done */ return 0; }
/* * Do I/O (either read or write) of a single whole block. * * Locking: must hold vnode lock. May get/release sfs_freemaplock. * * Requires up to 2 buffers. */ static int sfs_blockio(struct sfs_vnode *sv, struct uio *uio) { struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data; struct buf *iobuf; void *ioptr; daddr_t diskblock; uint32_t fileblock; int result; bool doalloc = (uio->uio_rw==UIO_WRITE); unsigned new_checksum = 0; KASSERT(lock_do_i_hold(sv->sv_lock)); /* Get the block number within the file */ fileblock = uio->uio_offset / SFS_BLOCKSIZE; /* Look up the disk block number */ result = sfs_bmap(sv, fileblock, doalloc, &diskblock); if (result) { return result; } if (diskblock == 0) { /* * No block - fill with zeros. * * We must be reading, or sfs_bmap would have * allocated a block for us. */ KASSERT(uio->uio_rw == UIO_READ); return uiomovezeros(SFS_BLOCKSIZE, uio); } if (uio->uio_rw == UIO_READ) { result = buffer_read(&sfs->sfs_absfs, diskblock, SFS_BLOCKSIZE, &iobuf); } else { result = buffer_get(&sfs->sfs_absfs, diskblock, SFS_BLOCKSIZE, &iobuf); } if (result) { return result; } /* * Do the I/O into the buffer. */ ioptr = buffer_map(iobuf); result = uiomove(ioptr, SFS_BLOCKSIZE, uio); if (result) { buffer_release(iobuf); return result; } if (uio->uio_rw == UIO_WRITE) { new_checksum = checksum(ioptr); sfs_jphys_write_wrapper(sfs, NULL, jentry_block_write(diskblock, new_checksum, false)); buffer_mark_valid(iobuf); buffer_mark_dirty(iobuf); // Journalled } buffer_release(iobuf); return 0; }
/* * Do I/O to a block of a file that doesn't cover the whole block. We * need to read in the original block first, even if we're writing, so * we don't clobber the portion of the block we're not intending to * write over. * * SKIPSTART is the number of bytes to skip past at the beginning of * the sector; LEN is the number of bytes to actually read or write. * UIO is the area to do the I/O into. * * Requires up to 2 buffers. */ static int sfs_partialio(struct sfs_vnode *sv, struct uio *uio, uint32_t skipstart, uint32_t len) { struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data; struct buf *iobuffer; unsigned char *ioptr; daddr_t diskblock; uint32_t fileblock; int result; unsigned new_checksum = 0; /* Allocate missing blocks if and only if we're writing */ bool doalloc = (uio->uio_rw==UIO_WRITE); KASSERT(lock_do_i_hold(sv->sv_lock)); KASSERT(skipstart + len <= SFS_BLOCKSIZE); /* Compute the block offset of this block in the file */ fileblock = uio->uio_offset / SFS_BLOCKSIZE; /* Get the disk block number */ result = sfs_bmap(sv, fileblock, doalloc, &diskblock); if (result) { return result; } if (diskblock == 0) { /* * There was no block mapped at this point in the file. * * We must be reading, or sfs_bmap would have * allocated a block for us. */ KASSERT(uio->uio_rw == UIO_READ); return uiomovezeros(len, uio); } else { /* * Read the block. */ result = buffer_read(&sfs->sfs_absfs, diskblock, SFS_BLOCKSIZE, &iobuffer); if (result) { return result; } } /* * Now perform the requested operation into/out of the buffer. */ ioptr = buffer_map(iobuffer); result = uiomove(ioptr+skipstart, len, uio); if (result) { buffer_release(iobuffer); return result; } /* * If it was a write, mark the modified block dirty and journal */ if (uio->uio_rw == UIO_WRITE) { // Compute checksum and journal new_checksum = checksum(ioptr); sfs_jphys_write_wrapper(sfs, NULL, jentry_block_write(diskblock, new_checksum, false)); buffer_mark_dirty(iobuffer); // Journalled } buffer_release(iobuffer); return 0; }