Blame view
fs/ext4/file.c
7.27 KB
ac27a0ec1 [PATCH] ext4: ini... |
1 |
/* |
617ba13b3 [PATCH] ext4: ren... |
2 |
* linux/fs/ext4/file.c |
ac27a0ec1 [PATCH] ext4: ini... |
3 4 5 6 7 8 9 10 11 12 13 14 |
* * Copyright (C) 1992, 1993, 1994, 1995 * Remy Card (card@masi.ibp.fr) * Laboratoire MASI - Institut Blaise Pascal * Universite Pierre et Marie Curie (Paris VI) * * from * * linux/fs/minix/file.c * * Copyright (C) 1991, 1992 Linus Torvalds * |
617ba13b3 [PATCH] ext4: ren... |
15 |
* ext4 fs regular file handling primitives |
ac27a0ec1 [PATCH] ext4: ini... |
16 17 18 19 20 21 22 |
* * 64-bit file support on 64-bit platforms by Jakub Jelinek * (jj@sunsite.ms.mff.cuni.cz) */ #include <linux/time.h> #include <linux/fs.h> |
dab291af8 [PATCH] jbd2: ena... |
23 |
#include <linux/jbd2.h> |
bc0b0d6d6 ext4: update the ... |
24 25 |
#include <linux/mount.h> #include <linux/path.h> |
871a29315 dquot: cleanup dq... |
26 |
#include <linux/quotaops.h> |
3dcf54515 ext4: move header... |
27 28 |
#include "ext4.h" #include "ext4_jbd2.h" |
ac27a0ec1 [PATCH] ext4: ini... |
29 30 31 32 33 |
#include "xattr.h" #include "acl.h" /* * Called when an inode is released. Note that this is different |
617ba13b3 [PATCH] ext4: ren... |
34 |
* from ext4_file_open: open gets called at every open, but release |
ac27a0ec1 [PATCH] ext4: ini... |
35 36 |
* gets called only when /all/ the files are closed. */ |
af5bc92dd ext4: Fix whitesp... |
37 |
static int ext4_release_file(struct inode *inode, struct file *filp) |
ac27a0ec1 [PATCH] ext4: ini... |
38 |
{ |
19f5fb7ad ext4: Use bitops ... |
39 |
if (ext4_test_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE)) { |
7d8f9f7d1 ext4: Automatical... |
40 |
ext4_alloc_da_blocks(inode); |
19f5fb7ad ext4: Use bitops ... |
41 |
ext4_clear_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE); |
7d8f9f7d1 ext4: Automatical... |
42 |
} |
ac27a0ec1 [PATCH] ext4: ini... |
43 44 |
/* if we are the last writer on the inode, drop the block reservation */ if ((filp->f_mode & FMODE_WRITE) && |
d6014301b ext4: Fix discard... |
45 46 |
(atomic_read(&inode->i_writecount) == 1) && !EXT4_I(inode)->i_reserved_data_blocks) |
ac27a0ec1 [PATCH] ext4: ini... |
47 |
{ |
0e855ac8b ext4: Convert tru... |
48 |
down_write(&EXT4_I(inode)->i_data_sem); |
c2ea3fde6 ext4: Remove old ... |
49 |
ext4_discard_preallocations(inode); |
0e855ac8b ext4: Convert tru... |
50 |
up_write(&EXT4_I(inode)->i_data_sem); |
ac27a0ec1 [PATCH] ext4: ini... |
51 52 |
} if (is_dx(inode) && filp->private_data) |
617ba13b3 [PATCH] ext4: ren... |
53 |
ext4_htree_free_dir_info(filp->private_data); |
ac27a0ec1 [PATCH] ext4: ini... |
54 55 56 |
return 0; } |
e9e3bcecf ext4: serialize u... |
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
static void ext4_aiodio_wait(struct inode *inode) { wait_queue_head_t *wq = ext4_ioend_wq(inode); wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_aiodio_unwritten) == 0)); } /* * This tests whether the IO in question is block-aligned or not. * Ext4 utilizes unwritten extents when hole-filling during direct IO, and they * are converted to written only after the IO is complete. Until they are * mapped, these blocks appear as holes, so dio_zero_block() will assume that * it needs to zero out portions of the start and/or end block. If 2 AIO * threads are at work on the same unwritten block, they must be synchronized * or one thread will zero the other's data, causing corruption. */ static int ext4_unaligned_aio(struct inode *inode, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { struct super_block *sb = inode->i_sb; int blockmask = sb->s_blocksize - 1; size_t count = iov_length(iov, nr_segs); loff_t final_size = pos + count; if (pos >= inode->i_size) return 0; if ((pos & blockmask) || (final_size & blockmask)) return 1; return 0; } |
ac27a0ec1 [PATCH] ext4: ini... |
90 |
static ssize_t |
617ba13b3 [PATCH] ext4: ren... |
91 |
ext4_file_write(struct kiocb *iocb, const struct iovec *iov, |
ac27a0ec1 [PATCH] ext4: ini... |
92 93 |
unsigned long nr_segs, loff_t pos) { |
0d34ec62e ext4: Remove sync... |
94 |
struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; |
e9e3bcecf ext4: serialize u... |
95 96 |
int unaligned_aio = 0; int ret; |
ac27a0ec1 [PATCH] ext4: ini... |
97 |
|
e2b465745 ext4: store maxby... |
98 99 100 101 |
/* * If we have encountered a bitmap-format file, the size limit * is smaller than s_maxbytes, which is for extent-mapped files. */ |
12e9b8920 ext4: Use bitops ... |
102 |
if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { |
e2b465745 ext4: store maxby... |
103 104 |
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); size_t length = iov_length(iov, nr_segs); |
ac27a0ec1 [PATCH] ext4: ini... |
105 |
|
d889dc838 ext4: fix EFBIG e... |
106 107 |
if ((pos > sbi->s_bitmap_maxbytes || (pos == sbi->s_bitmap_maxbytes && length > 0))) |
e2b465745 ext4: store maxby... |
108 109 110 111 112 113 |
return -EFBIG; if (pos + length > sbi->s_bitmap_maxbytes) { nr_segs = iov_shorten((struct iovec *)iov, nr_segs, sbi->s_bitmap_maxbytes - pos); } |
e9e3bcecf ext4: serialize u... |
114 115 116 |
} else if (unlikely((iocb->ki_filp->f_flags & O_DIRECT) && !is_sync_kiocb(iocb))) { unaligned_aio = ext4_unaligned_aio(inode, iov, nr_segs, pos); |
e2b465745 ext4: store maxby... |
117 |
} |
e9e3bcecf ext4: serialize u... |
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
/* Unaligned direct AIO must be serialized; see comment above */ if (unaligned_aio) { static unsigned long unaligned_warn_time; /* Warn about this once per day */ if (printk_timed_ratelimit(&unaligned_warn_time, 60*60*24*HZ)) ext4_msg(inode->i_sb, KERN_WARNING, "Unaligned AIO/DIO on inode %ld by %s; " "performance will be poor.", inode->i_ino, current->comm); mutex_lock(ext4_aio_mutex(inode)); ext4_aiodio_wait(inode); } ret = generic_file_aio_write(iocb, iov, nr_segs, pos); if (unaligned_aio) mutex_unlock(ext4_aio_mutex(inode)); return ret; |
ac27a0ec1 [PATCH] ext4: ini... |
138 |
} |
f0f37e2f7 const: mark struc... |
139 |
static const struct vm_operations_struct ext4_file_vm_ops = { |
2e9ee8503 ext4: Use page_mk... |
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
.fault = filemap_fault, .page_mkwrite = ext4_page_mkwrite, }; static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma) { struct address_space *mapping = file->f_mapping; if (!mapping->a_ops->readpage) return -ENOEXEC; file_accessed(file); vma->vm_ops = &ext4_file_vm_ops; vma->vm_flags |= VM_CAN_NONLINEAR; return 0; } |
bc0b0d6d6 ext4: update the ... |
155 156 157 158 |
static int ext4_file_open(struct inode * inode, struct file * filp) { struct super_block *sb = inode->i_sb; struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
8aefcd557 ext4: dynamically... |
159 |
struct ext4_inode_info *ei = EXT4_I(inode); |
bc0b0d6d6 ext4: update the ... |
160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
struct vfsmount *mnt = filp->f_path.mnt; struct path path; char buf[64], *cp; if (unlikely(!(sbi->s_mount_flags & EXT4_MF_MNTDIR_SAMPLED) && !(sb->s_flags & MS_RDONLY))) { sbi->s_mount_flags |= EXT4_MF_MNTDIR_SAMPLED; /* * Sample where the filesystem has been mounted and * store it in the superblock for sysadmin convenience * when trying to sort through large numbers of block * devices or filesystem images. */ memset(buf, 0, sizeof(buf)); |
3899167db Get rid of mnt_mo... |
174 175 |
path.mnt = mnt; path.dentry = mnt->mnt_root; |
bc0b0d6d6 ext4: update the ... |
176 |
cp = d_path(&path, buf, sizeof(buf)); |
bc0b0d6d6 ext4: update the ... |
177 |
if (!IS_ERR(cp)) { |
cf8039036 ext4: prevent sta... |
178 179 |
strlcpy(sbi->s_es->s_last_mounted, cp, sizeof(sbi->s_es->s_last_mounted)); |
a0375156c ext4: Clean up s_... |
180 |
ext4_mark_super_dirty(sb); |
bc0b0d6d6 ext4: update the ... |
181 182 |
} } |
8aefcd557 ext4: dynamically... |
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
/* * Set up the jbd2_inode if we are opening the inode for * writing and the journal is present */ if (sbi->s_journal && !ei->jinode && (filp->f_mode & FMODE_WRITE)) { struct jbd2_inode *jinode = jbd2_alloc_inode(GFP_KERNEL); spin_lock(&inode->i_lock); if (!ei->jinode) { if (!jinode) { spin_unlock(&inode->i_lock); return -ENOMEM; } ei->jinode = jinode; jbd2_journal_init_jbd_inode(ei->jinode, inode); jinode = NULL; } spin_unlock(&inode->i_lock); if (unlikely(jinode != NULL)) jbd2_free_inode(jinode); } |
907f4554e dquot: move dquot... |
204 |
return dquot_file_open(inode, filp); |
bc0b0d6d6 ext4: update the ... |
205 |
} |
e0d10bfa9 ext4: improve lls... |
206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
/* * ext4_llseek() copied from generic_file_llseek() to handle both * block-mapped and extent-mapped maxbytes values. This should * otherwise be identical with generic_file_llseek(). */ loff_t ext4_llseek(struct file *file, loff_t offset, int origin) { struct inode *inode = file->f_mapping->host; loff_t maxbytes; if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) maxbytes = EXT4_SB(inode->i_sb)->s_bitmap_maxbytes; else maxbytes = inode->i_sb->s_maxbytes; |
e0d10bfa9 ext4: improve lls... |
220 |
|
4cce0e28b ext4: replace cut... |
221 |
return generic_file_llseek_size(file, offset, origin, maxbytes); |
e0d10bfa9 ext4: improve lls... |
222 |
} |
617ba13b3 [PATCH] ext4: ren... |
223 |
const struct file_operations ext4_file_operations = { |
e0d10bfa9 ext4: improve lls... |
224 |
.llseek = ext4_llseek, |
ac27a0ec1 [PATCH] ext4: ini... |
225 226 227 |
.read = do_sync_read, .write = do_sync_write, .aio_read = generic_file_aio_read, |
617ba13b3 [PATCH] ext4: ren... |
228 |
.aio_write = ext4_file_write, |
5cdd7b2d7 Convert ext4 to u... |
229 |
.unlocked_ioctl = ext4_ioctl, |
ac27a0ec1 [PATCH] ext4: ini... |
230 |
#ifdef CONFIG_COMPAT |
617ba13b3 [PATCH] ext4: ren... |
231 |
.compat_ioctl = ext4_compat_ioctl, |
ac27a0ec1 [PATCH] ext4: ini... |
232 |
#endif |
2e9ee8503 ext4: Use page_mk... |
233 |
.mmap = ext4_file_mmap, |
bc0b0d6d6 ext4: update the ... |
234 |
.open = ext4_file_open, |
617ba13b3 [PATCH] ext4: ren... |
235 236 |
.release = ext4_release_file, .fsync = ext4_sync_file, |
ac27a0ec1 [PATCH] ext4: ini... |
237 238 |
.splice_read = generic_file_splice_read, .splice_write = generic_file_splice_write, |
2fe17c107 fallocate should ... |
239 |
.fallocate = ext4_fallocate, |
ac27a0ec1 [PATCH] ext4: ini... |
240 |
}; |
754661f14 [PATCH] mark stru... |
241 |
const struct inode_operations ext4_file_inode_operations = { |
617ba13b3 [PATCH] ext4: ren... |
242 |
.setattr = ext4_setattr, |
3e3398a08 ext4: delayed all... |
243 |
.getattr = ext4_getattr, |
03010a335 ext4: Rename ext4... |
244 |
#ifdef CONFIG_EXT4_FS_XATTR |
ac27a0ec1 [PATCH] ext4: ini... |
245 246 |
.setxattr = generic_setxattr, .getxattr = generic_getxattr, |
617ba13b3 [PATCH] ext4: ren... |
247 |
.listxattr = ext4_listxattr, |
ac27a0ec1 [PATCH] ext4: ini... |
248 249 |
.removexattr = generic_removexattr, #endif |
4e34e719e fs: take the ACL ... |
250 |
.get_acl = ext4_get_acl, |
6873fa0de Hook ext4 to the ... |
251 |
.fiemap = ext4_fiemap, |
ac27a0ec1 [PATCH] ext4: ini... |
252 |
}; |