| 1 | |
| 2 | |
| 3 | * linux/fs/ext2/file.c
|
| 4 | *
|
| 5 | * Copyright (C) 1992, 1993, 1994, 1995
|
| 6 | * Remy Card ([email protected])
|
| 7 | * Laboratoire MASI - Institut Blaise Pascal
|
| 8 | * Universite Pierre et Marie Curie (Paris VI)
|
| 9 | *
|
| 10 | * from
|
| 11 | *
|
| 12 | * linux/fs/minix/file.c
|
| 13 | *
|
| 14 | * Copyright (C) 1991, 1992 Linus Torvalds
|
| 15 | *
|
| 16 | * ext2 fs regular file handling primitives
|
| 17 | *
|
| 18 | * 64-bit file support on 64-bit platforms by Jakub Jelinek
|
| 19 | * ([email protected])
|
| 20 |
|
| 21 |
|
| 22 | #include <linux/time.h>
|
| 23 | #include <linux/pagemap.h>
|
| 24 | #include <linux/filelock.h>
|
| 25 | #include <linux/quotaops.h>
|
| 26 | #include <linux/iomap.h>
|
| 27 | #include <linux/uio.h>
|
| 28 | #include <linux/buffer_head.h>
|
| 29 | #include "ext2.h"
|
| 30 | #include "xattr.h"
|
| 31 | #include "acl.h"
|
| 32 | #include "trace.h"
|
| 33 |
|
| 34 |
|
| 35 | |
| 36 | * Called when filp is released. This happens when all file descriptors
|
| 37 | * for a single struct file are closed. Note that different open() calls
|
| 38 | * for the same file yield different struct file structures.
|
| 39 |
|
| 40 | static int ext2_release_file (struct inode * inode, struct file * filp)
|
| 41 | {
|
| 42 | if (filp->f_mode & FMODE_WRITE) {
|
| 43 | mutex_lock(&EXT2_I(inode)->truncate_mutex);
|
| 44 | ext2_discard_reservation(inode);
|
| 45 | mutex_unlock(&EXT2_I(inode)->truncate_mutex);
|
| 46 | }
|
| 47 | return 0;
|
| 48 | }
|
| 49 |
|
| 50 | static ssize_t ext2_dio_read_iter(struct kiocb *iocb, struct iov_iter *to)
|
| 51 | {
|
| 52 | struct file *file = iocb->ki_filp;
|
| 53 | struct inode *inode = file->f_mapping->host;
|
| 54 | ssize_t ret;
|
| 55 |
|
| 56 | trace_ext2_dio_read_begin(iocb, to, 0);
|
| 57 | inode_lock_shared(inode);
|
| 58 | ret = iomap_dio_rw(iocb, to, &ext2_iomap_ops, NULL, 0, NULL, 0);
|
| 59 | inode_unlock_shared(inode);
|
| 60 | trace_ext2_dio_read_end(iocb, to, ret);
|
| 61 |
|
| 62 | return ret;
|
| 63 | }
|
| 64 |
|
| 65 | static int ext2_dio_write_end_io(struct kiocb *iocb, ssize_t size,
|
| 66 | int error, unsigned int flags)
|
| 67 | {
|
| 68 | loff_t pos = iocb->ki_pos;
|
| 69 | struct inode *inode = file_inode(iocb->ki_filp);
|
| 70 |
|
| 71 | if (error)
|
| 72 | goto out;
|
| 73 |
|
| 74 | |
| 75 | * If we are extending the file, we have to update i_size here before
|
| 76 | * page cache gets invalidated in iomap_dio_rw(). This prevents racing
|
| 77 | * buffered reads from zeroing out too much from page cache pages.
|
| 78 | * Note that all extending writes always happens synchronously with
|
| 79 | * inode lock held by ext2_dio_write_iter(). So it is safe to update
|
| 80 | * inode size here for extending file writes.
|
| 81 |
|
| 82 | pos += size;
|
| 83 | if (pos > i_size_read(inode)) {
|
| 84 | i_size_write(inode, pos);
|
| 85 | mark_inode_dirty(inode);
|
| 86 | }
|
| 87 | out:
|
| 88 | trace_ext2_dio_write_endio(iocb, size, error);
|
| 89 | return error;
|
| 90 | }
|
| 91 |
|
| 92 | static const struct iomap_dio_ops ext2_dio_write_ops = {
|
| 93 | .end_io = ext2_dio_write_end_io,
|
| 94 | };
|
| 95 |
|
| 96 | static ssize_t ext2_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
| 97 | {
|
| 98 | struct file *file = iocb->ki_filp;
|
| 99 | struct inode *inode = file->f_mapping->host;
|
| 100 | ssize_t ret;
|
| 101 | unsigned int flags = 0;
|
| 102 | unsigned long blocksize = inode->i_sb->s_blocksize;
|
| 103 | loff_t offset = iocb->ki_pos;
|
| 104 | loff_t count = iov_iter_count(from);
|
| 105 | ssize_t status = 0;
|
| 106 |
|
| 107 | trace_ext2_dio_write_begin(iocb, from, 0);
|
| 108 | inode_lock(inode);
|
| 109 | ret = generic_write_checks(iocb, from);
|
| 110 | if (ret <= 0)
|
| 111 | goto out_unlock;
|
| 112 |
|
| 113 | ret = kiocb_modified(iocb);
|
| 114 | if (ret)
|
| 115 | goto out_unlock;
|
| 116 |
|
| 117 |
|
| 118 | if (iocb->ki_pos + iov_iter_count(from) > i_size_read(inode) ||
|
| 119 | (!IS_ALIGNED(iocb->ki_pos | iov_iter_alignment(from), blocksize)))
|
| 120 | flags |= IOMAP_DIO_FORCE_WAIT;
|
| 121 |
|
| 122 | ret = iomap_dio_rw(iocb, from, &ext2_iomap_ops, &ext2_dio_write_ops,
|
| 123 | flags, NULL, 0);
|
| 124 |
|
| 125 |
|
| 126 | if (ret == -ENOTBLK)
|
| 127 | ret = 0;
|
| 128 |
|
| 129 | if (ret < 0 && ret != -EIOCBQUEUED)
|
| 130 | ext2_write_failed(inode->i_mapping, offset + count);
|
| 131 |
|
| 132 |
|
| 133 | if (ret >= 0 && iov_iter_count(from)) {
|
| 134 | loff_t pos, endbyte;
|
| 135 | int ret2;
|
| 136 |
|
| 137 | iocb->ki_flags &= ~IOCB_DIRECT;
|
| 138 |
|
| 139 | |
| 140 | * Prevent concurrent direct I/O and buffered I/O to the same file
|
| 141 | * range. Wait for in-flight DIO to finish before dirtying pages.
|
| 142 |
|
| 143 | inode_dio_wait(inode);
|
| 144 |
|
| 145 | pos = iocb->ki_pos;
|
| 146 | status = generic_perform_write(iocb, from);
|
| 147 | if (unlikely(status < 0)) {
|
| 148 | ret = status;
|
| 149 | goto out_unlock;
|
| 150 | }
|
| 151 |
|
| 152 | ret += status;
|
| 153 | endbyte = pos + status - 1;
|
| 154 | ret2 = filemap_write_and_wait_range(inode->i_mapping, pos,
|
| 155 | endbyte);
|
| 156 | if (!ret2) {
|
| 157 | invalidate_mapping_pages(inode->i_mapping,
|
| 158 | pos >> PAGE_SHIFT,
|
| 159 | endbyte >> PAGE_SHIFT);
|
| 160 | if (ret > 0)
|
| 161 | ret = generic_write_sync(iocb, ret);
|
| 162 | } else {
|
| 163 | ret = ret2;
|
| 164 | }
|
| 165 | }
|
| 166 |
|
| 167 | out_unlock:
|
| 168 | inode_unlock(inode);
|
| 169 | if (status)
|
| 170 | trace_ext2_dio_write_buff_end(iocb, from, status);
|
| 171 | trace_ext2_dio_write_end(iocb, from, ret);
|
| 172 | return ret;
|
| 173 | }
|
| 174 |
|
| 175 | static ssize_t ext2_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
|
| 176 | {
|
| 177 | if (iocb->ki_flags & IOCB_DIRECT)
|
| 178 | return ext2_dio_read_iter(iocb, to);
|
| 179 |
|
| 180 | return generic_file_read_iter(iocb, to);
|
| 181 | }
|
| 182 |
|
| 183 | static ssize_t ext2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
| 184 | {
|
| 185 | if (iocb->ki_flags & IOCB_DIRECT)
|
| 186 | return ext2_dio_write_iter(iocb, from);
|
| 187 |
|
| 188 | return generic_file_write_iter(iocb, from);
|
| 189 | }
|
| 190 |
|
| 191 | static int ext2_file_open(struct inode *inode, struct file *filp)
|
| 192 | {
|
| 193 | filp->f_mode |= FMODE_CAN_ODIRECT;
|
| 194 | return dquot_file_open(inode, filp);
|
| 195 | }
|
| 196 |
|
| 197 | const struct file_operations ext2_file_operations = {
|
| 198 | .llseek = generic_file_llseek,
|
| 199 | .read_iter = ext2_file_read_iter,
|
| 200 | .write_iter = ext2_file_write_iter,
|
| 201 | .unlocked_ioctl = ext2_ioctl,
|
| 202 | #ifdef CONFIG_COMPAT
|
| 203 | .compat_ioctl = ext2_compat_ioctl,
|
| 204 | #endif
|
| 205 | .mmap_prepare = generic_file_mmap_prepare,
|
| 206 | .open = ext2_file_open,
|
| 207 | .release = ext2_release_file,
|
| 208 | .fsync = simple_fsync,
|
| 209 | .get_unmapped_area = thp_get_unmapped_area,
|
| 210 | .splice_read = filemap_splice_read,
|
| 211 | .splice_write = iter_file_splice_write,
|
| 212 | .setlease = generic_setlease,
|
| 213 | };
|
| 214 |
|
| 215 | const struct inode_operations ext2_file_inode_operations = {
|
| 216 | .listxattr = ext2_listxattr,
|
| 217 | .getattr = ext2_getattr,
|
| 218 | .setattr = ext2_setattr,
|
| 219 | .get_inode_acl = ext2_get_acl,
|
| 220 | .set_acl = ext2_set_acl,
|
| 221 | .fiemap = ext2_fiemap,
|
| 222 | .fileattr_get = ext2_fileattr_get,
|
| 223 | .fileattr_set = ext2_fileattr_set,
|
| 224 | };
|