Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 923ae0ff authored by Ross Zwisler's avatar Ross Zwisler Committed by Linus Torvalds
Browse files

ext4: add DAX functionality



This is a port of the DAX functionality found in the current version of
ext2.

[matthew.r.wilcox@intel.com: heavily tweaked]
[akpm@linux-foundation.org: remap_pages went away]
Signed-off-by: default avatarRoss Zwisler <ross.zwisler@linux.intel.com>
Reviewed-by: default avatarAndreas Dilger <andreas.dilger@intel.com>
Signed-off-by: default avatarMatthew Wilcox <matthew.r.wilcox@intel.com>
Cc: Boaz Harrosh <boaz@plexistor.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 25726bc1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ or a write()) work correctly.

These filesystems may be used for inspiration:
- ext2: the second extended filesystem, see Documentation/filesystems/ext2.txt
- ext4: the fourth extended filesystem, see Documentation/filesystems/ext4.txt


Shortcomings
+4 −0
Original line number Diff line number Diff line
@@ -386,6 +386,10 @@ max_dir_size_kb=n This limits the size of directories so that any
i_version		Enable 64-bit inode version support. This option is
			off by default.

dax			Use direct access (no page cache).  See
			Documentation/filesystems/dax.txt.  Note that
			this option is incompatible with data=journal.

Data Mode
=========
There are 3 different data modes:
+6 −0
Original line number Diff line number Diff line
@@ -965,6 +965,11 @@ struct ext4_inode_info {
#define EXT4_MOUNT_ERRORS_MASK		0x00070
#define EXT4_MOUNT_MINIX_DF		0x00080	/* Mimics the Minix statfs */
#define EXT4_MOUNT_NOLOAD		0x00100	/* Don't use existing journal*/
#ifdef CONFIG_FS_DAX
#define EXT4_MOUNT_DAX			0x00200	/* Direct Access */
#else
#define EXT4_MOUNT_DAX			0
#endif
#define EXT4_MOUNT_DATA_FLAGS		0x00C00	/* Mode for data writes: */
#define EXT4_MOUNT_JOURNAL_DATA		0x00400	/* Write data to journal */
#define EXT4_MOUNT_ORDERED_DATA		0x00800	/* Flush data before commit */
@@ -2578,6 +2583,7 @@ extern const struct file_operations ext4_dir_operations;
/* file.c */
extern const struct inode_operations ext4_file_inode_operations;
extern const struct file_operations ext4_file_operations;
extern const struct file_operations ext4_dax_file_operations;
extern loff_t ext4_llseek(struct file *file, loff_t offset, int origin);

/* inline.c */
+47 −2
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
	struct inode *inode = file_inode(iocb->ki_filp);
	struct mutex *aio_mutex = NULL;
	struct blk_plug plug;
	int o_direct = file->f_flags & O_DIRECT;
	int o_direct = io_is_direct(file);
	int overwrite = 0;
	size_t length = iov_iter_count(from);
	ssize_t ret;
@@ -191,6 +191,26 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
	return ret;
}

#ifdef CONFIG_FS_DAX
static int ext4_dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
	return dax_fault(vma, vmf, ext4_get_block);
					/* Is this the right get_block? */
}

static int ext4_dax_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
{
	return dax_mkwrite(vma, vmf, ext4_get_block);
}

static const struct vm_operations_struct ext4_dax_vm_ops = {
	.fault		= ext4_dax_fault,
	.page_mkwrite	= ext4_dax_mkwrite,
};
#else
#define ext4_dax_vm_ops	ext4_file_vm_ops
#endif

static const struct vm_operations_struct ext4_file_vm_ops = {
	.fault		= filemap_fault,
	.map_pages	= filemap_map_pages,
@@ -200,7 +220,12 @@ static const struct vm_operations_struct ext4_file_vm_ops = {
static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
{
	file_accessed(file);
	if (IS_DAX(file_inode(file))) {
		vma->vm_ops = &ext4_dax_vm_ops;
		vma->vm_flags |= VM_MIXEDMAP;
	} else {
		vma->vm_ops = &ext4_file_vm_ops;
	}
	return 0;
}

@@ -599,6 +624,26 @@ const struct file_operations ext4_file_operations = {
	.fallocate	= ext4_fallocate,
};

#ifdef CONFIG_FS_DAX
const struct file_operations ext4_dax_file_operations = {
	.llseek		= ext4_llseek,
	.read		= new_sync_read,
	.write		= new_sync_write,
	.read_iter	= generic_file_read_iter,
	.write_iter	= ext4_file_write_iter,
	.unlocked_ioctl = ext4_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl	= ext4_compat_ioctl,
#endif
	.mmap		= ext4_file_mmap,
	.open		= ext4_file_open,
	.release	= ext4_release_file,
	.fsync		= ext4_sync_file,
	/* Splice not yet supported with DAX */
	.fallocate	= ext4_fallocate,
};
#endif

const struct inode_operations ext4_file_inode_operations = {
	.setattr	= ext4_setattr,
	.getattr	= ext4_getattr,
+13 −5
Original line number Diff line number Diff line
@@ -689,12 +689,20 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
			inode_dio_done(inode);
			goto locked;
		}
		if (IS_DAX(inode))
			ret = dax_do_io(rw, iocb, inode, iter, offset,
					ext4_get_block, NULL, 0);
		else
			ret = __blockdev_direct_IO(rw, iocb, inode,
					inode->i_sb->s_bdev, iter, offset,
					ext4_get_block, NULL, NULL, 0);
		inode_dio_done(inode);
	} else {
locked:
		if (IS_DAX(inode))
			ret = dax_do_io(rw, iocb, inode, iter, offset,
					ext4_get_block, NULL, DIO_LOCKING);
		else
			ret = blockdev_direct_IO(rw, iocb, inode, iter,
					offset, ext4_get_block);

Loading