Skip to content

Commit 3b93f91

Browse files
author
Al Viro
committed
export generic_perform_write(), start getting rid of generic_file_buffer_write()
Signed-off-by: Al Viro <[email protected]>
1 parent 5cb6c6c commit 3b93f91

File tree

2 files changed

+23
-16
lines changed

2 files changed

+23
-16
lines changed

include/linux/fs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct cred;
4848
struct swap_info_struct;
4949
struct seq_file;
5050
struct workqueue_struct;
51+
struct iov_iter;
5152

5253
extern void __init inode_init(void);
5354
extern void __init inode_init_early(void);
@@ -2396,6 +2397,7 @@ extern ssize_t __generic_file_aio_write(struct kiocb *, const struct iovec *, un
23962397
extern ssize_t generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
23972398
extern ssize_t generic_file_direct_write(struct kiocb *, const struct iovec *,
23982399
unsigned long *, loff_t, size_t, size_t);
2400+
extern ssize_t generic_perform_write(struct file *, struct iov_iter *, loff_t);
23992401
extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *,
24002402
unsigned long, loff_t, size_t, ssize_t);
24012403
extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos);

mm/filemap.c

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,7 +2092,7 @@ struct page *grab_cache_page_write_begin(struct address_space *mapping,
20922092
}
20932093
EXPORT_SYMBOL(grab_cache_page_write_begin);
20942094

2095-
static ssize_t generic_perform_write(struct file *file,
2095+
ssize_t generic_perform_write(struct file *file,
20962096
struct iov_iter *i, loff_t pos)
20972097
{
20982098
struct address_space *mapping = file->f_mapping;
@@ -2180,6 +2180,7 @@ static ssize_t generic_perform_write(struct file *file,
21802180

21812181
return written ? written : status;
21822182
}
2183+
EXPORT_SYMBOL(generic_perform_write);
21832184

21842185
ssize_t
21852186
generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
@@ -2230,8 +2231,10 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
22302231
size_t count; /* after file limit checks */
22312232
struct inode *inode = mapping->host;
22322233
loff_t pos = iocb->ki_pos;
2233-
ssize_t written;
2234+
ssize_t written = 0;
22342235
ssize_t err;
2236+
ssize_t status;
2237+
struct iov_iter from;
22352238

22362239
ocount = 0;
22372240
err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
@@ -2242,8 +2245,6 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
22422245

22432246
/* We can write back this queue in page reclaim */
22442247
current->backing_dev_info = mapping->backing_dev_info;
2245-
written = 0;
2246-
22472248
err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
22482249
if (err)
22492250
goto out;
@@ -2259,44 +2260,47 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
22592260
if (err)
22602261
goto out;
22612262

2263+
iov_iter_init(&from, iov, nr_segs, count, 0);
2264+
22622265
/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
22632266
if (unlikely(file->f_flags & O_DIRECT)) {
22642267
loff_t endbyte;
2265-
ssize_t written_buffered;
22662268

2267-
written = generic_file_direct_write(iocb, iov, &nr_segs, pos,
2269+
written = generic_file_direct_write(iocb, iov, &from.nr_segs, pos,
22682270
count, ocount);
22692271
if (written < 0 || written == count)
22702272
goto out;
2273+
iov_iter_advance(&from, written);
2274+
22712275
/*
22722276
* direct-io write to a hole: fall through to buffered I/O
22732277
* for completing the rest of the request.
22742278
*/
22752279
pos += written;
22762280
count -= written;
2277-
written_buffered = generic_file_buffered_write(iocb, iov,
2278-
nr_segs, pos, count, written);
2281+
2282+
status = generic_perform_write(file, &from, pos);
22792283
/*
2280-
* If generic_file_buffered_write() retuned a synchronous error
2284+
* If generic_perform_write() returned a synchronous error
22812285
* then we want to return the number of bytes which were
22822286
* direct-written, or the error code if that was zero. Note
22832287
* that this differs from normal direct-io semantics, which
22842288
* will return -EFOO even if some bytes were written.
22852289
*/
2286-
if (written_buffered < 0) {
2287-
err = written_buffered;
2290+
if (unlikely(status < 0) && !written) {
2291+
err = status;
22882292
goto out;
22892293
}
2290-
2294+
iocb->ki_pos = pos + status;
22912295
/*
22922296
* We need to ensure that the page cache pages are written to
22932297
* disk and invalidated to preserve the expected O_DIRECT
22942298
* semantics.
22952299
*/
2296-
endbyte = pos + written_buffered - written - 1;
2300+
endbyte = pos + status - 1;
22972301
err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte);
22982302
if (err == 0) {
2299-
written = written_buffered;
2303+
written += status;
23002304
invalidate_mapping_pages(mapping,
23012305
pos >> PAGE_CACHE_SHIFT,
23022306
endbyte >> PAGE_CACHE_SHIFT);
@@ -2307,8 +2311,9 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
23072311
*/
23082312
}
23092313
} else {
2310-
written = generic_file_buffered_write(iocb, iov, nr_segs,
2311-
pos, count, written);
2314+
written = generic_perform_write(file, &from, pos);
2315+
if (likely(written >= 0))
2316+
iocb->ki_pos = pos + written;
23122317
}
23132318
out:
23142319
current->backing_dev_info = NULL;

0 commit comments

Comments
 (0)