aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-04-09 12:55:47 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-04-11 22:30:21 -0400
commit3309dd04cbcd2cdad168485af5cf3576b5051e49 (patch)
tree3e01f865306dee01b31f34c9e7e819a5f42a4087 /mm
parent90320251db0fe3d05f2b10686ec936c7d6ecd99a (diff)
switch generic_write_checks() to iocb and iter
... returning -E... upon error and amount of data left in iter after (possible) truncation upon success. Note, that normal case gives a non-zero (positive) return value, so any tests for != 0 _must_ be updated. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Conflicts: fs/ext4/file.c
Diffstat (limited to 'mm')
-rw-r--r--mm/filemap.c44
1 files changed, 19 insertions, 25 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index dfc573c6ec25..243997a26e7c 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2260,36 +2260,38 @@ EXPORT_SYMBOL(read_cache_page_gfp);
2260 * Returns appropriate error code that caller should return or 2260 * Returns appropriate error code that caller should return or
2261 * zero in case that write should be allowed. 2261 * zero in case that write should be allowed.
2262 */ 2262 */
2263inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count) 2263inline ssize_t generic_write_checks(struct kiocb *iocb, struct iov_iter *from)
2264{ 2264{
2265 struct file *file = iocb->ki_filp;
2265 struct inode *inode = file->f_mapping->host; 2266 struct inode *inode = file->f_mapping->host;
2266 unsigned long limit = rlimit(RLIMIT_FSIZE); 2267 unsigned long limit = rlimit(RLIMIT_FSIZE);
2268 loff_t pos;
2267 2269
2268 if (unlikely(*pos < 0)) 2270 if (!iov_iter_count(from))
2269 return -EINVAL; 2271 return 0;
2270 2272
2271 /* FIXME: this is for backwards compatibility with 2.4 */ 2273 /* FIXME: this is for backwards compatibility with 2.4 */
2272 if (file->f_flags & O_APPEND) 2274 if (file->f_flags & O_APPEND)
2273 *pos = i_size_read(inode); 2275 iocb->ki_pos = i_size_read(inode);
2276
2277 pos = iocb->ki_pos;
2274 2278
2275 if (limit != RLIM_INFINITY) { 2279 if (limit != RLIM_INFINITY) {
2276 if (*pos >= limit) { 2280 if (iocb->ki_pos >= limit) {
2277 send_sig(SIGXFSZ, current, 0); 2281 send_sig(SIGXFSZ, current, 0);
2278 return -EFBIG; 2282 return -EFBIG;
2279 } 2283 }
2280 if (*count > limit - (typeof(limit))*pos) 2284 iov_iter_truncate(from, limit - (unsigned long)pos);
2281 *count = limit - (typeof(limit))*pos;
2282 } 2285 }
2283 2286
2284 /* 2287 /*
2285 * LFS rule 2288 * LFS rule
2286 */ 2289 */
2287 if (unlikely(*pos + *count > MAX_NON_LFS && 2290 if (unlikely(pos + iov_iter_count(from) > MAX_NON_LFS &&
2288 !(file->f_flags & O_LARGEFILE))) { 2291 !(file->f_flags & O_LARGEFILE))) {
2289 if (*pos >= MAX_NON_LFS) 2292 if (pos >= MAX_NON_LFS)
2290 return -EFBIG; 2293 return -EFBIG;
2291 if (*count > MAX_NON_LFS - (unsigned long)*pos) 2294 iov_iter_truncate(from, MAX_NON_LFS - (unsigned long)pos);
2292 *count = MAX_NON_LFS - (unsigned long)*pos;
2293 } 2295 }
2294 2296
2295 /* 2297 /*
@@ -2299,16 +2301,11 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count)
2299 * exceeded without writing data we send a signal and return EFBIG. 2301 * exceeded without writing data we send a signal and return EFBIG.
2300 * Linus frestrict idea will clean these up nicely.. 2302 * Linus frestrict idea will clean these up nicely..
2301 */ 2303 */
2302 if (unlikely(*pos >= inode->i_sb->s_maxbytes)) { 2304 if (unlikely(pos >= inode->i_sb->s_maxbytes))
2303 if (*count || *pos > inode->i_sb->s_maxbytes) { 2305 return -EFBIG;
2304 return -EFBIG;
2305 }
2306 /* zero-length writes at ->s_maxbytes are OK */
2307 }
2308 2306
2309 if (unlikely(*pos + *count > inode->i_sb->s_maxbytes)) 2307 iov_iter_truncate(from, inode->i_sb->s_maxbytes - pos);
2310 *count = inode->i_sb->s_maxbytes - *pos; 2308 return iov_iter_count(from);
2311 return 0;
2312} 2309}
2313EXPORT_SYMBOL(generic_write_checks); 2310EXPORT_SYMBOL(generic_write_checks);
2314 2311
@@ -2618,14 +2615,11 @@ ssize_t generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
2618 struct file *file = iocb->ki_filp; 2615 struct file *file = iocb->ki_filp;
2619 struct inode *inode = file->f_mapping->host; 2616 struct inode *inode = file->f_mapping->host;
2620 ssize_t ret; 2617 ssize_t ret;
2621 size_t count = iov_iter_count(from);
2622 2618
2623 mutex_lock(&inode->i_mutex); 2619 mutex_lock(&inode->i_mutex);
2624 ret = generic_write_checks(file, &iocb->ki_pos, &count); 2620 ret = generic_write_checks(iocb, from);
2625 if (!ret && count) { 2621 if (ret > 0)
2626 iov_iter_truncate(from, count);
2627 ret = __generic_file_write_iter(iocb, from); 2622 ret = __generic_file_write_iter(iocb, from);
2628 }
2629 mutex_unlock(&inode->i_mutex); 2623 mutex_unlock(&inode->i_mutex);
2630 2624
2631 if (ret > 0) { 2625 if (ret > 0) {