diff options
Diffstat (limited to 'fs/ext4/file.c')
-rw-r--r-- | fs/ext4/file.c | 150 |
1 files changed, 75 insertions, 75 deletions
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 881394280d5f..86a13a514e4a 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -92,58 +92,91 @@ ext4_unaligned_aio(struct inode *inode, const struct iovec *iov, | |||
92 | } | 92 | } |
93 | 93 | ||
94 | static ssize_t | 94 | static ssize_t |
95 | ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, | 95 | ext4_file_write(struct kiocb *iocb, const struct iovec *iov, |
96 | unsigned long nr_segs, loff_t pos) | 96 | unsigned long nr_segs, loff_t pos) |
97 | { | 97 | { |
98 | struct file *file = iocb->ki_filp; | 98 | struct file *file = iocb->ki_filp; |
99 | struct inode *inode = file->f_mapping->host; | 99 | struct inode *inode = file_inode(iocb->ki_filp); |
100 | struct mutex *aio_mutex = NULL; | ||
100 | struct blk_plug plug; | 101 | struct blk_plug plug; |
101 | int unaligned_aio = 0; | 102 | int o_direct = file->f_flags & O_DIRECT; |
102 | ssize_t ret; | ||
103 | int overwrite = 0; | 103 | int overwrite = 0; |
104 | size_t length = iov_length(iov, nr_segs); | 104 | size_t length = iov_length(iov, nr_segs); |
105 | ssize_t ret; | ||
105 | 106 | ||
106 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) && | 107 | BUG_ON(iocb->ki_pos != pos); |
107 | !is_sync_kiocb(iocb)) | ||
108 | unaligned_aio = ext4_unaligned_aio(inode, iov, nr_segs, pos); | ||
109 | 108 | ||
110 | /* Unaligned direct AIO must be serialized; see comment above */ | 109 | /* |
111 | if (unaligned_aio) { | 110 | * Unaligned direct AIO must be serialized; see comment above |
112 | mutex_lock(ext4_aio_mutex(inode)); | 111 | * In the case of O_APPEND, assume that we must always serialize |
112 | */ | ||
113 | if (o_direct && | ||
114 | ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) && | ||
115 | !is_sync_kiocb(iocb) && | ||
116 | (file->f_flags & O_APPEND || | ||
117 | ext4_unaligned_aio(inode, iov, nr_segs, pos))) { | ||
118 | aio_mutex = ext4_aio_mutex(inode); | ||
119 | mutex_lock(aio_mutex); | ||
113 | ext4_unwritten_wait(inode); | 120 | ext4_unwritten_wait(inode); |
114 | } | 121 | } |
115 | 122 | ||
116 | BUG_ON(iocb->ki_pos != pos); | ||
117 | |||
118 | mutex_lock(&inode->i_mutex); | 123 | mutex_lock(&inode->i_mutex); |
119 | blk_start_plug(&plug); | 124 | if (file->f_flags & O_APPEND) |
125 | iocb->ki_pos = pos = i_size_read(inode); | ||
126 | |||
127 | /* | ||
128 | * If we have encountered a bitmap-format file, the size limit | ||
129 | * is smaller than s_maxbytes, which is for extent-mapped files. | ||
130 | */ | ||
131 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { | ||
132 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | ||
120 | 133 | ||
121 | iocb->private = &overwrite; | 134 | if ((pos > sbi->s_bitmap_maxbytes) || |
135 | (pos == sbi->s_bitmap_maxbytes && length > 0)) { | ||
136 | mutex_unlock(&inode->i_mutex); | ||
137 | ret = -EFBIG; | ||
138 | goto errout; | ||
139 | } | ||
122 | 140 | ||
123 | /* check whether we do a DIO overwrite or not */ | 141 | if (pos + length > sbi->s_bitmap_maxbytes) { |
124 | if (ext4_should_dioread_nolock(inode) && !unaligned_aio && | 142 | nr_segs = iov_shorten((struct iovec *)iov, nr_segs, |
125 | !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) { | 143 | sbi->s_bitmap_maxbytes - pos); |
126 | struct ext4_map_blocks map; | 144 | } |
127 | unsigned int blkbits = inode->i_blkbits; | 145 | } |
128 | int err, len; | ||
129 | 146 | ||
130 | map.m_lblk = pos >> blkbits; | 147 | if (o_direct) { |
131 | map.m_len = (EXT4_BLOCK_ALIGN(pos + length, blkbits) >> blkbits) | 148 | blk_start_plug(&plug); |
132 | - map.m_lblk; | ||
133 | len = map.m_len; | ||
134 | 149 | ||
135 | err = ext4_map_blocks(NULL, inode, &map, 0); | 150 | iocb->private = &overwrite; |
136 | /* | 151 | |
137 | * 'err==len' means that all of blocks has been preallocated no | 152 | /* check whether we do a DIO overwrite or not */ |
138 | * matter they are initialized or not. For excluding | 153 | if (ext4_should_dioread_nolock(inode) && !aio_mutex && |
139 | * uninitialized extents, we need to check m_flags. There are | 154 | !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) { |
140 | * two conditions that indicate for initialized extents. | 155 | struct ext4_map_blocks map; |
141 | * 1) If we hit extent cache, EXT4_MAP_MAPPED flag is returned; | 156 | unsigned int blkbits = inode->i_blkbits; |
142 | * 2) If we do a real lookup, non-flags are returned. | 157 | int err, len; |
143 | * So we should check these two conditions. | 158 | |
144 | */ | 159 | map.m_lblk = pos >> blkbits; |
145 | if (err == len && (map.m_flags & EXT4_MAP_MAPPED)) | 160 | map.m_len = (EXT4_BLOCK_ALIGN(pos + length, blkbits) >> blkbits) |
146 | overwrite = 1; | 161 | - map.m_lblk; |
162 | len = map.m_len; | ||
163 | |||
164 | err = ext4_map_blocks(NULL, inode, &map, 0); | ||
165 | /* | ||
166 | * 'err==len' means that all of blocks has | ||
167 | * been preallocated no matter they are | ||
168 | * initialized or not. For excluding | ||
169 | * unwritten extents, we need to check | ||
170 | * m_flags. There are two conditions that | ||
171 | * indicate for initialized extents. 1) If we | ||
172 | * hit extent cache, EXT4_MAP_MAPPED flag is | ||
173 | * returned; 2) If we do a real lookup, | ||
174 | * non-flags are returned. So we should check | ||
175 | * these two conditions. | ||
176 | */ | ||
177 | if (err == len && (map.m_flags & EXT4_MAP_MAPPED)) | ||
178 | overwrite = 1; | ||
179 | } | ||
147 | } | 180 | } |
148 | 181 | ||
149 | ret = __generic_file_aio_write(iocb, iov, nr_segs); | 182 | ret = __generic_file_aio_write(iocb, iov, nr_segs); |
@@ -156,45 +189,12 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, | |||
156 | if (err < 0) | 189 | if (err < 0) |
157 | ret = err; | 190 | ret = err; |
158 | } | 191 | } |
159 | blk_finish_plug(&plug); | 192 | if (o_direct) |
160 | 193 | blk_finish_plug(&plug); | |
161 | if (unaligned_aio) | ||
162 | mutex_unlock(ext4_aio_mutex(inode)); | ||
163 | |||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | static ssize_t | ||
168 | ext4_file_write(struct kiocb *iocb, const struct iovec *iov, | ||
169 | unsigned long nr_segs, loff_t pos) | ||
170 | { | ||
171 | struct inode *inode = file_inode(iocb->ki_filp); | ||
172 | ssize_t ret; | ||
173 | |||
174 | /* | ||
175 | * If we have encountered a bitmap-format file, the size limit | ||
176 | * is smaller than s_maxbytes, which is for extent-mapped files. | ||
177 | */ | ||
178 | |||
179 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { | ||
180 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | ||
181 | size_t length = iov_length(iov, nr_segs); | ||
182 | |||
183 | if ((pos > sbi->s_bitmap_maxbytes || | ||
184 | (pos == sbi->s_bitmap_maxbytes && length > 0))) | ||
185 | return -EFBIG; | ||
186 | |||
187 | if (pos + length > sbi->s_bitmap_maxbytes) { | ||
188 | nr_segs = iov_shorten((struct iovec *)iov, nr_segs, | ||
189 | sbi->s_bitmap_maxbytes - pos); | ||
190 | } | ||
191 | } | ||
192 | |||
193 | if (unlikely(iocb->ki_filp->f_flags & O_DIRECT)) | ||
194 | ret = ext4_file_dio_write(iocb, iov, nr_segs, pos); | ||
195 | else | ||
196 | ret = generic_file_aio_write(iocb, iov, nr_segs, pos); | ||
197 | 194 | ||
195 | errout: | ||
196 | if (aio_mutex) | ||
197 | mutex_unlock(aio_mutex); | ||
198 | return ret; | 198 | return ret; |
199 | } | 199 | } |
200 | 200 | ||