Merge branch 'master' into gfs2
This commit is contained in:
186
mm/filemap.c
186
mm/filemap.c
@@ -1149,13 +1149,14 @@ success:
|
||||
* that can use the page cache directly.
|
||||
*/
|
||||
ssize_t
|
||||
__generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t *ppos)
|
||||
generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t pos)
|
||||
{
|
||||
struct file *filp = iocb->ki_filp;
|
||||
ssize_t retval;
|
||||
unsigned long seg;
|
||||
size_t count;
|
||||
loff_t *ppos = &iocb->ki_pos;
|
||||
|
||||
count = 0;
|
||||
for (seg = 0; seg < nr_segs; seg++) {
|
||||
@@ -1179,7 +1180,7 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
||||
|
||||
/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
|
||||
if (filp->f_flags & O_DIRECT) {
|
||||
loff_t pos = *ppos, size;
|
||||
loff_t size;
|
||||
struct address_space *mapping;
|
||||
struct inode *inode;
|
||||
|
||||
@@ -1225,33 +1226,8 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL(__generic_file_aio_read);
|
||||
|
||||
ssize_t
|
||||
generic_file_aio_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
|
||||
{
|
||||
struct iovec local_iov = { .iov_base = buf, .iov_len = count };
|
||||
|
||||
BUG_ON(iocb->ki_pos != pos);
|
||||
return __generic_file_aio_read(iocb, &local_iov, 1, &iocb->ki_pos);
|
||||
}
|
||||
EXPORT_SYMBOL(generic_file_aio_read);
|
||||
|
||||
ssize_t
|
||||
generic_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iovec local_iov = { .iov_base = buf, .iov_len = count };
|
||||
struct kiocb kiocb;
|
||||
ssize_t ret;
|
||||
|
||||
init_sync_kiocb(&kiocb, filp);
|
||||
ret = __generic_file_aio_read(&kiocb, &local_iov, 1, ppos);
|
||||
if (-EIOCBQUEUED == ret)
|
||||
ret = wait_on_sync_kiocb(&kiocb);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(generic_file_read);
|
||||
|
||||
int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
|
||||
{
|
||||
ssize_t written;
|
||||
@@ -1473,7 +1449,7 @@ outside_data_content:
|
||||
* accessible..
|
||||
*/
|
||||
if (area->vm_mm == current->mm)
|
||||
return NULL;
|
||||
return NOPAGE_SIGBUS;
|
||||
/* Fall through to the non-read-ahead case */
|
||||
no_cached_page:
|
||||
/*
|
||||
@@ -1498,7 +1474,7 @@ no_cached_page:
|
||||
*/
|
||||
if (error == -ENOMEM)
|
||||
return NOPAGE_OOM;
|
||||
return NULL;
|
||||
return NOPAGE_SIGBUS;
|
||||
|
||||
page_not_uptodate:
|
||||
if (!did_readaround) {
|
||||
@@ -1567,7 +1543,7 @@ page_not_uptodate:
|
||||
*/
|
||||
shrink_readahead_size_eio(file, ra);
|
||||
page_cache_release(page);
|
||||
return NULL;
|
||||
return NOPAGE_SIGBUS;
|
||||
}
|
||||
EXPORT_SYMBOL(filemap_nopage);
|
||||
|
||||
@@ -2022,6 +1998,7 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, i
|
||||
if (unlikely(*pos + *count > inode->i_sb->s_maxbytes))
|
||||
*count = inode->i_sb->s_maxbytes - *pos;
|
||||
} else {
|
||||
#ifdef CONFIG_BLOCK
|
||||
loff_t isize;
|
||||
if (bdev_read_only(I_BDEV(inode)))
|
||||
return -EPERM;
|
||||
@@ -2033,6 +2010,9 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, i
|
||||
|
||||
if (*pos + *count > isize)
|
||||
*count = isize - *pos;
|
||||
#else
|
||||
return -EPERM;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2313,22 +2293,22 @@ out:
|
||||
current->backing_dev_info = NULL;
|
||||
return written ? written : err;
|
||||
}
|
||||
EXPORT_SYMBOL(generic_file_aio_write_nolock);
|
||||
|
||||
ssize_t
|
||||
generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t *ppos)
|
||||
ssize_t generic_file_aio_write_nolock(struct kiocb *iocb,
|
||||
const struct iovec *iov, unsigned long nr_segs, loff_t pos)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct address_space *mapping = file->f_mapping;
|
||||
struct inode *inode = mapping->host;
|
||||
ssize_t ret;
|
||||
loff_t pos = *ppos;
|
||||
|
||||
ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs, ppos);
|
||||
BUG_ON(iocb->ki_pos != pos);
|
||||
|
||||
ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs,
|
||||
&iocb->ki_pos);
|
||||
|
||||
if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
|
||||
int err;
|
||||
ssize_t err;
|
||||
|
||||
err = sync_page_range_nolock(inode, mapping, pos, ret);
|
||||
if (err < 0)
|
||||
@@ -2336,51 +2316,21 @@ generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(generic_file_aio_write_nolock);
|
||||
|
||||
static ssize_t
|
||||
__generic_file_write_nolock(struct file *file, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t *ppos)
|
||||
{
|
||||
struct kiocb kiocb;
|
||||
ssize_t ret;
|
||||
|
||||
init_sync_kiocb(&kiocb, file);
|
||||
ret = __generic_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos);
|
||||
if (ret == -EIOCBQUEUED)
|
||||
ret = wait_on_sync_kiocb(&kiocb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
generic_file_write_nolock(struct file *file, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t *ppos)
|
||||
{
|
||||
struct kiocb kiocb;
|
||||
ssize_t ret;
|
||||
|
||||
init_sync_kiocb(&kiocb, file);
|
||||
ret = generic_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos);
|
||||
if (-EIOCBQUEUED == ret)
|
||||
ret = wait_on_sync_kiocb(&kiocb);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(generic_file_write_nolock);
|
||||
|
||||
ssize_t generic_file_aio_write(struct kiocb *iocb, const char __user *buf,
|
||||
size_t count, loff_t pos)
|
||||
ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t pos)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct address_space *mapping = file->f_mapping;
|
||||
struct inode *inode = mapping->host;
|
||||
ssize_t ret;
|
||||
struct iovec local_iov = { .iov_base = (void __user *)buf,
|
||||
.iov_len = count };
|
||||
|
||||
BUG_ON(iocb->ki_pos != pos);
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
ret = __generic_file_aio_write_nolock(iocb, &local_iov, 1,
|
||||
&iocb->ki_pos);
|
||||
ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs,
|
||||
&iocb->ki_pos);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
|
||||
@@ -2394,66 +2344,6 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const char __user *buf,
|
||||
}
|
||||
EXPORT_SYMBOL(generic_file_aio_write);
|
||||
|
||||
ssize_t generic_file_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct address_space *mapping = file->f_mapping;
|
||||
struct inode *inode = mapping->host;
|
||||
ssize_t ret;
|
||||
struct iovec local_iov = { .iov_base = (void __user *)buf,
|
||||
.iov_len = count };
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
ret = __generic_file_write_nolock(file, &local_iov, 1, ppos);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
|
||||
ssize_t err;
|
||||
|
||||
err = sync_page_range(inode, mapping, *ppos - ret, ret);
|
||||
if (err < 0)
|
||||
ret = err;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(generic_file_write);
|
||||
|
||||
ssize_t generic_file_readv(struct file *filp, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t *ppos)
|
||||
{
|
||||
struct kiocb kiocb;
|
||||
ssize_t ret;
|
||||
|
||||
init_sync_kiocb(&kiocb, filp);
|
||||
ret = __generic_file_aio_read(&kiocb, iov, nr_segs, ppos);
|
||||
if (-EIOCBQUEUED == ret)
|
||||
ret = wait_on_sync_kiocb(&kiocb);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(generic_file_readv);
|
||||
|
||||
ssize_t generic_file_writev(struct file *file, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t *ppos)
|
||||
{
|
||||
struct address_space *mapping = file->f_mapping;
|
||||
struct inode *inode = mapping->host;
|
||||
ssize_t ret;
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
ret = __generic_file_write_nolock(file, iov, nr_segs, ppos);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
|
||||
int err;
|
||||
|
||||
err = sync_page_range(inode, mapping, *ppos - ret, ret);
|
||||
if (err < 0)
|
||||
ret = err;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(generic_file_writev);
|
||||
|
||||
/*
|
||||
* Called under i_mutex for writes to S_ISREG files. Returns -EIO if something
|
||||
* went wrong during pagecache shootdown.
|
||||
@@ -2493,3 +2383,33 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* try_to_release_page() - release old fs-specific metadata on a page
|
||||
*
|
||||
* @page: the page which the kernel is trying to free
|
||||
* @gfp_mask: memory allocation flags (and I/O mode)
|
||||
*
|
||||
* The address_space is to try to release any data against the page
|
||||
* (presumably at page->private). If the release was successful, return `1'.
|
||||
* Otherwise return zero.
|
||||
*
|
||||
* The @gfp_mask argument specifies whether I/O may be performed to release
|
||||
* this page (__GFP_IO), and whether the call may block (__GFP_WAIT).
|
||||
*
|
||||
* NOTE: @gfp_mask may go away, and this function may become non-blocking.
|
||||
*/
|
||||
int try_to_release_page(struct page *page, gfp_t gfp_mask)
|
||||
{
|
||||
struct address_space * const mapping = page->mapping;
|
||||
|
||||
BUG_ON(!PageLocked(page));
|
||||
if (PageWriteback(page))
|
||||
return 0;
|
||||
|
||||
if (mapping && mapping->a_ops->releasepage)
|
||||
return mapping->a_ops->releasepage(page, gfp_mask);
|
||||
return try_to_free_buffers(page);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(try_to_release_page);
|
||||
|
Reference in New Issue
Block a user