Whamcloud - gitweb
git://git.whamcloud.com
/
tools
/
e2fsprogs.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
| inline |
side by side
libext2fs: force DIO alignment FreeBSD when operating on a block device
[tools/e2fsprogs.git]
/
lib
/
ext2fs
/
fileio.c
diff --git
a/lib/ext2fs/fileio.c
b/lib/ext2fs/fileio.c
index
5a39c32
..
810a7fd
100644
(file)
--- a/
lib/ext2fs/fileio.c
+++ b/
lib/ext2fs/fileio.c
@@
-123,6
+123,8
@@
errcode_t ext2fs_file_flush(ext2_file_t file)
{
errcode_t retval;
ext2_filsys fs;
+ int ret_flags;
+ blk64_t dontcare;
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
fs = file->fs;
@@
-131,6
+133,22
@@
errcode_t ext2fs_file_flush(ext2_file_t file)
!(file->flags & EXT2_FILE_BUF_DIRTY))
return 0;
+ /* Is this an uninit block? */
+ if (file->physblock && file->inode.i_flags & EXT4_EXTENTS_FL) {
+ retval = ext2fs_bmap2(fs, file->ino, &file->inode, BMAP_BUFFER,
+ 0, file->blockno, &ret_flags, &dontcare);
+ if (retval)
+ return retval;
+ if (ret_flags & BMAP_RET_UNINIT) {
+ retval = ext2fs_bmap2(fs, file->ino, &file->inode,
+ BMAP_BUFFER, BMAP_SET,
+ file->blockno, 0,
+ &file->physblock);
+ if (retval)
+ return retval;
+ }
+ }
+
/*
* OK, the physical block hasn't been allocated yet.
* Allocate it.
@@
-185,15
+203,17
@@
static errcode_t load_buffer(ext2_file_t file, int dontfill)
{
ext2_filsys fs = file->fs;
errcode_t retval;
+ int ret_flags;
if (!(file->flags & EXT2_FILE_BUF_VALID)) {
retval = ext2fs_bmap2(fs, file->ino, &file->inode,
- BMAP_BUFFER, 0, file->blockno,
0
,
+ BMAP_BUFFER, 0, file->blockno,
&ret_flags
,
&file->physblock);
if (retval)
return retval;
if (!dontfill) {
- if (file->physblock) {
+ if (file->physblock &&
+ !(ret_flags & BMAP_RET_UNINIT)) {
retval = io_channel_read_blk64(fs->io,
file->physblock,
1, file->buf);
@@
-224,6
+244,38
@@
errcode_t ext2fs_file_close(ext2_file_t file)
}
+static errcode_t
+ext2fs_file_read_inline_data(ext2_file_t file, void *buf,
+ unsigned int wanted, unsigned int *got)
+{
+ ext2_filsys fs;
+ errcode_t retval;
+ unsigned int count = 0;
+ size_t size;
+
+ fs = file->fs;
+ retval = ext2fs_inline_data_get(fs, file->ino, &file->inode,
+ file->buf, &size);
+ if (retval)
+ return retval;
+
+ if (file->pos >= size)
+ goto out;
+
+ count = size - file->pos;
+ if (count > wanted)
+ count = wanted;
+ memcpy(buf, file->buf + file->pos, count);
+ file->pos += count;
+ buf = (char *) buf + count;
+
+out:
+ if (got)
+ *got = count;
+ return retval;
+}
+
+
errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
unsigned int wanted, unsigned int *got)
{
@@
-236,6
+288,10
@@
errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
fs = file->fs;
+ /* If an inode has inline data, things get complicated. */
+ if (file->inode.i_flags & EXT4_INLINE_DATA_FL)
+ return ext2fs_file_read_inline_data(file, buf, wanted, got);
+
while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) {
retval = sync_buffer_position(file);
if (retval)
@@
-266,6
+322,66
@@
fail:
}
+static errcode_t
+ext2fs_file_write_inline_data(ext2_file_t file, const void *buf,
+ unsigned int nbytes, unsigned int *written)
+{
+ ext2_filsys fs;
+ errcode_t retval;
+ unsigned int count = 0;
+ size_t size;
+
+ fs = file->fs;
+ retval = ext2fs_inline_data_get(fs, file->ino, &file->inode,
+ file->buf, &size);
+ if (retval)
+ return retval;
+
+ if (file->pos < size) {
+ count = nbytes - file->pos;
+ memcpy(file->buf + file->pos, buf, count);
+
+ retval = ext2fs_inline_data_set(fs, file->ino, &file->inode,
+ file->buf, count);
+ if (retval == EXT2_ET_INLINE_DATA_NO_SPACE)
+ goto expand;
+ if (retval)
+ return retval;
+
+ file->pos += count;
+
+ /* Update inode size */
+ if (count != 0 && EXT2_I_SIZE(&file->inode) < file->pos) {
+ errcode_t rc;
+
+ rc = ext2fs_file_set_size2(file, file->pos);
+ if (retval == 0)
+ retval = rc;
+ }
+
+ if (written)
+ *written = count;
+ return 0;
+ }
+
+expand:
+ retval = ext2fs_inline_data_expand(fs, file->ino);
+ if (retval)
+ return retval;
+ /*
+ * reload inode and return no space error
+ *
+ * XXX: file->inode could be copied from the outside
+ * in ext2fs_file_open2(). We have no way to modify
+ * the outside inode.
+ */
+ retval = ext2fs_read_inode(fs, file->ino, &file->inode);
+ if (retval)
+ return retval;
+ return EXT2_ET_INLINE_DATA_NO_SPACE;
+}
+
+
errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
unsigned int nbytes, unsigned int *written)
{
@@
-280,6
+396,16
@@
errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
if (!(file->flags & EXT2_FILE_WRITE))
return EXT2_ET_FILE_RO;
+ /* If an inode has inline data, things get complicated. */
+ if (file->inode.i_flags & EXT4_INLINE_DATA_FL) {
+ retval = ext2fs_file_write_inline_data(file, buf, nbytes,
+ written);
+ if (retval != EXT2_ET_INLINE_DATA_NO_SPACE)
+ return retval;
+ /* fall through to read data from the block */
+ retval = 0;
+ }
+
while (nbytes > 0) {
retval = sync_buffer_position(file);
if (retval)
@@
-358,7
+484,7
@@
errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
int whence, ext2_off_t *ret_pos)
{
- __u64 loffset, ret_loffset;
+ __u64 loffset, ret_loffset
= 0
;
errcode_t retval;
loffset = offset;
@@
-462,20
+588,10
@@
errcode_t ext2fs_file_set_size2(ext2_file_t file, ext2_off64_t size)
old_truncate = ((old_size + file->fs->blocksize - 1) >>
EXT2_BLOCK_SIZE_BITS(file->fs->super));
- /* If we're writing a large file, set the large_file flag */
- if (LINUX_S_ISREG(file->inode.i_mode) &&
- ext2fs_needs_large_file_feature(EXT2_I_SIZE(&file->inode)) &&
- (!EXT2_HAS_RO_COMPAT_FEATURE(file->fs->super,
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE) ||
- file->fs->super->s_rev_level == EXT2_GOOD_OLD_REV)) {
- file->fs->super->s_feature_ro_compat |=
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
- ext2fs_update_dynamic_rev(file->fs);
- ext2fs_mark_super_dirty(file->fs);
- }
+ retval = ext2fs_inode_size_set(file->fs, &file->inode, size);
+ if (retval)
+ return retval;
- file->inode.i_size = size & 0xffffffff;
- file->inode.i_size_high = (size >> 32);
if (file->ino) {
retval = ext2fs_write_inode(file->fs, file->ino, &file->inode);
if (retval)