Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b93f911 authored by Al Viro's avatar Al Viro
Browse files

export generic_perform_write(), start getting rid of generic_file_buffer_write()



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 5cb6c6c7
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -48,6 +48,7 @@ struct cred;
struct swap_info_struct;
struct swap_info_struct;
struct seq_file;
struct seq_file;
struct workqueue_struct;
struct workqueue_struct;
struct iov_iter;


extern void __init inode_init(void);
extern void __init inode_init(void);
extern void __init inode_init_early(void);
extern void __init inode_init_early(void);
@@ -2396,6 +2397,7 @@ extern ssize_t __generic_file_aio_write(struct kiocb *, const struct iovec *, un
extern ssize_t generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
extern ssize_t generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
extern ssize_t generic_file_direct_write(struct kiocb *, const struct iovec *,
extern ssize_t generic_file_direct_write(struct kiocb *, const struct iovec *,
		unsigned long *, loff_t, size_t, size_t);
		unsigned long *, loff_t, size_t, size_t);
extern ssize_t generic_perform_write(struct file *, struct iov_iter *, loff_t);
extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *,
extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *,
		unsigned long, loff_t, size_t, ssize_t);
		unsigned long, loff_t, size_t, ssize_t);
extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos);
extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos);
+21 −16
Original line number Original line Diff line number Diff line
@@ -2092,7 +2092,7 @@ found:
}
}
EXPORT_SYMBOL(grab_cache_page_write_begin);
EXPORT_SYMBOL(grab_cache_page_write_begin);


static ssize_t generic_perform_write(struct file *file,
ssize_t generic_perform_write(struct file *file,
				struct iov_iter *i, loff_t pos)
				struct iov_iter *i, loff_t pos)
{
{
	struct address_space *mapping = file->f_mapping;
	struct address_space *mapping = file->f_mapping;
@@ -2180,6 +2180,7 @@ again:


	return written ? written : status;
	return written ? written : status;
}
}
EXPORT_SYMBOL(generic_perform_write);


ssize_t
ssize_t
generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
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,
	size_t count;		/* after file limit checks */
	size_t count;		/* after file limit checks */
	struct inode 	*inode = mapping->host;
	struct inode 	*inode = mapping->host;
	loff_t		pos = iocb->ki_pos;
	loff_t		pos = iocb->ki_pos;
	ssize_t		written;
	ssize_t		written = 0;
	ssize_t		err;
	ssize_t		err;
	ssize_t		status;
	struct iov_iter from;


	ocount = 0;
	ocount = 0;
	err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
	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,


	/* We can write back this queue in page reclaim */
	/* We can write back this queue in page reclaim */
	current->backing_dev_info = mapping->backing_dev_info;
	current->backing_dev_info = mapping->backing_dev_info;
	written = 0;

	err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
	err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
	if (err)
	if (err)
		goto out;
		goto out;
@@ -2259,44 +2260,47 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
	if (err)
	if (err)
		goto out;
		goto out;


	iov_iter_init(&from, iov, nr_segs, count, 0);

	/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
	/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
	if (unlikely(file->f_flags & O_DIRECT)) {
	if (unlikely(file->f_flags & O_DIRECT)) {
		loff_t endbyte;
		loff_t endbyte;
		ssize_t written_buffered;


		written = generic_file_direct_write(iocb, iov, &nr_segs, pos,
		written = generic_file_direct_write(iocb, iov, &from.nr_segs, pos,
							count, ocount);
							count, ocount);
		if (written < 0 || written == count)
		if (written < 0 || written == count)
			goto out;
			goto out;
		iov_iter_advance(&from, written);

		/*
		/*
		 * direct-io write to a hole: fall through to buffered I/O
		 * direct-io write to a hole: fall through to buffered I/O
		 * for completing the rest of the request.
		 * for completing the rest of the request.
		 */
		 */
		pos += written;
		pos += written;
		count -= written;
		count -= written;
		written_buffered = generic_file_buffered_write(iocb, iov,

						nr_segs, pos, count, written);
		status = generic_perform_write(file, &from, pos);
		/*
		/*
		 * If generic_file_buffered_write() retuned a synchronous error
		 * If generic_perform_write() returned a synchronous error
		 * then we want to return the number of bytes which were
		 * then we want to return the number of bytes which were
		 * direct-written, or the error code if that was zero.  Note
		 * direct-written, or the error code if that was zero.  Note
		 * that this differs from normal direct-io semantics, which
		 * that this differs from normal direct-io semantics, which
		 * will return -EFOO even if some bytes were written.
		 * will return -EFOO even if some bytes were written.
		 */
		 */
		if (written_buffered < 0) {
		if (unlikely(status < 0) && !written) {
			err = written_buffered;
			err = status;
			goto out;
			goto out;
		}
		}

		iocb->ki_pos = pos + status;
		/*
		/*
		 * We need to ensure that the page cache pages are written to
		 * We need to ensure that the page cache pages are written to
		 * disk and invalidated to preserve the expected O_DIRECT
		 * disk and invalidated to preserve the expected O_DIRECT
		 * semantics.
		 * semantics.
		 */
		 */
		endbyte = pos + written_buffered - written - 1;
		endbyte = pos + status - 1;
		err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte);
		err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte);
		if (err == 0) {
		if (err == 0) {
			written = written_buffered;
			written += status;
			invalidate_mapping_pages(mapping,
			invalidate_mapping_pages(mapping,
						 pos >> PAGE_CACHE_SHIFT,
						 pos >> PAGE_CACHE_SHIFT,
						 endbyte >> PAGE_CACHE_SHIFT);
						 endbyte >> PAGE_CACHE_SHIFT);
@@ -2307,8 +2311,9 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
			 */
			 */
		}
		}
	} else {
	} else {
		written = generic_file_buffered_write(iocb, iov, nr_segs,
		written = generic_perform_write(file, &from, pos);
				pos, count, written);
		if (likely(written >= 0))
			iocb->ki_pos = pos + written;
	}
	}
out:
out:
	current->backing_dev_info = NULL;
	current->backing_dev_info = NULL;