Updated from Linux LTS 3.10.25 to 3.10.26
This commit is contained in:
@@ -213,9 +213,13 @@ static int readpage_nounlock(struct file *filp, struct page *page)
|
||||
if (err < 0) {
|
||||
SetPageError(page);
|
||||
goto out;
|
||||
} else if (err < PAGE_CACHE_SIZE) {
|
||||
} else {
|
||||
if (err < PAGE_CACHE_SIZE) {
|
||||
/* zero fill remainder of page */
|
||||
zero_user_segment(page, err, PAGE_CACHE_SIZE);
|
||||
zero_user_segment(page, err, PAGE_CACHE_SIZE);
|
||||
} else {
|
||||
flush_dcache_page(page);
|
||||
}
|
||||
}
|
||||
SetPageUptodate(page);
|
||||
|
||||
|
||||
@@ -313,9 +313,9 @@ static int striped_read(struct inode *inode,
|
||||
{
|
||||
struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
|
||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
u64 pos, this_len;
|
||||
u64 pos, this_len, left;
|
||||
int io_align, page_align;
|
||||
int left, pages_left;
|
||||
int pages_left;
|
||||
int read;
|
||||
struct page **page_pos;
|
||||
int ret;
|
||||
@@ -346,47 +346,40 @@ more:
|
||||
ret = 0;
|
||||
hit_stripe = this_len < left;
|
||||
was_short = ret >= 0 && ret < this_len;
|
||||
dout("striped_read %llu~%u (read %u) got %d%s%s\n", pos, left, read,
|
||||
dout("striped_read %llu~%llu (read %u) got %d%s%s\n", pos, left, read,
|
||||
ret, hit_stripe ? " HITSTRIPE" : "", was_short ? " SHORT" : "");
|
||||
|
||||
if (ret > 0) {
|
||||
int didpages = (page_align + ret) >> PAGE_CACHE_SHIFT;
|
||||
|
||||
if (read < pos - off) {
|
||||
dout(" zero gap %llu to %llu\n", off + read, pos);
|
||||
ceph_zero_page_vector_range(page_align + read,
|
||||
pos - off - read, pages);
|
||||
if (ret >= 0) {
|
||||
int didpages;
|
||||
if (was_short && (pos + ret < inode->i_size)) {
|
||||
u64 tmp = min(this_len - ret,
|
||||
inode->i_size - pos - ret);
|
||||
dout(" zero gap %llu to %llu\n",
|
||||
pos + ret, pos + ret + tmp);
|
||||
ceph_zero_page_vector_range(page_align + read + ret,
|
||||
tmp, pages);
|
||||
ret += tmp;
|
||||
}
|
||||
|
||||
didpages = (page_align + ret) >> PAGE_CACHE_SHIFT;
|
||||
pos += ret;
|
||||
read = pos - off;
|
||||
left -= ret;
|
||||
page_pos += didpages;
|
||||
pages_left -= didpages;
|
||||
|
||||
/* hit stripe? */
|
||||
if (left && hit_stripe)
|
||||
/* hit stripe and need continue*/
|
||||
if (left && hit_stripe && pos < inode->i_size)
|
||||
goto more;
|
||||
}
|
||||
|
||||
if (was_short) {
|
||||
if (read > 0) {
|
||||
ret = read;
|
||||
/* did we bounce off eof? */
|
||||
if (pos + left > inode->i_size)
|
||||
*checkeof = 1;
|
||||
|
||||
/* zero trailing bytes (inside i_size) */
|
||||
if (left > 0 && pos < inode->i_size) {
|
||||
if (pos + left > inode->i_size)
|
||||
left = inode->i_size - pos;
|
||||
|
||||
dout("zero tail %d\n", left);
|
||||
ceph_zero_page_vector_range(page_align + read, left,
|
||||
pages);
|
||||
read += left;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret >= 0)
|
||||
ret = read;
|
||||
dout("striped_read returns %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -618,6 +611,8 @@ out:
|
||||
if (check_caps)
|
||||
ceph_check_caps(ceph_inode(inode), CHECK_CAPS_AUTHONLY,
|
||||
NULL);
|
||||
} else if (ret != -EOLDSNAPC && written > 0) {
|
||||
ret = written;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -211,8 +211,12 @@ static long ceph_ioctl_get_dataloc(struct file *file, void __user *arg)
|
||||
snprintf(dl.object_name, sizeof(dl.object_name), "%llx.%08llx",
|
||||
ceph_ino(inode), dl.object_no);
|
||||
|
||||
ceph_calc_ceph_pg(&pgid, dl.object_name, osdc->osdmap,
|
||||
ceph_file_layout_pg_pool(ci->i_layout));
|
||||
r = ceph_calc_ceph_pg(&pgid, dl.object_name, osdc->osdmap,
|
||||
ceph_file_layout_pg_pool(ci->i_layout));
|
||||
if (r < 0) {
|
||||
up_read(&osdc->map_sem);
|
||||
return r;
|
||||
}
|
||||
|
||||
dl.osd = ceph_calc_pg_primary(osdc->osdmap, pgid);
|
||||
if (dl.osd >= 0) {
|
||||
|
||||
@@ -414,6 +414,9 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
|
||||
{
|
||||
struct ceph_mds_session *s;
|
||||
|
||||
if (mds >= mdsc->mdsmap->m_max_mds)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
s = kzalloc(sizeof(*s), GFP_NOFS);
|
||||
if (!s)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
@@ -639,6 +642,8 @@ static void __unregister_request(struct ceph_mds_client *mdsc,
|
||||
req->r_unsafe_dir = NULL;
|
||||
}
|
||||
|
||||
complete_all(&req->r_safe_completion);
|
||||
|
||||
ceph_mdsc_put_request(req);
|
||||
}
|
||||
|
||||
@@ -1840,8 +1845,11 @@ static int __do_request(struct ceph_mds_client *mdsc,
|
||||
int mds = -1;
|
||||
int err = -EAGAIN;
|
||||
|
||||
if (req->r_err || req->r_got_result)
|
||||
if (req->r_err || req->r_got_result) {
|
||||
if (req->r_aborted)
|
||||
__unregister_request(mdsc, req);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (req->r_timeout &&
|
||||
time_after_eq(jiffies, req->r_started + req->r_timeout)) {
|
||||
@@ -2151,7 +2159,6 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
|
||||
if (head->safe) {
|
||||
req->r_got_safe = true;
|
||||
__unregister_request(mdsc, req);
|
||||
complete_all(&req->r_safe_completion);
|
||||
|
||||
if (req->r_got_unsafe) {
|
||||
/*
|
||||
@@ -3040,8 +3047,10 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
|
||||
fsc->mdsc = mdsc;
|
||||
mutex_init(&mdsc->mutex);
|
||||
mdsc->mdsmap = kzalloc(sizeof(*mdsc->mdsmap), GFP_NOFS);
|
||||
if (mdsc->mdsmap == NULL)
|
||||
if (mdsc->mdsmap == NULL) {
|
||||
kfree(mdsc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
init_completion(&mdsc->safe_umount_waiters);
|
||||
init_waitqueue_head(&mdsc->session_close_wq);
|
||||
|
||||
@@ -138,6 +138,8 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
|
||||
m->m_info[mds].export_targets =
|
||||
kcalloc(num_export_targets, sizeof(u32),
|
||||
GFP_NOFS);
|
||||
if (m->m_info[mds].export_targets == NULL)
|
||||
goto badmem;
|
||||
for (j = 0; j < num_export_targets; j++)
|
||||
m->m_info[mds].export_targets[j] =
|
||||
ceph_decode_32(&pexport_targets);
|
||||
@@ -170,7 +172,7 @@ bad:
|
||||
DUMP_PREFIX_OFFSET, 16, 1,
|
||||
start, end - start, true);
|
||||
ceph_mdsmap_destroy(m);
|
||||
return ERR_PTR(-EINVAL);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
void ceph_mdsmap_destroy(struct ceph_mdsmap *m)
|
||||
|
||||
@@ -357,7 +357,7 @@ static int parse_mount_options(struct ceph_mount_options **pfsopt,
|
||||
}
|
||||
err = -EINVAL;
|
||||
dev_name_end--; /* back up to ':' separator */
|
||||
if (*dev_name_end != ':') {
|
||||
if (dev_name_end < dev_name || *dev_name_end != ':') {
|
||||
pr_err("device name is missing path (no : separator in %s)\n",
|
||||
dev_name);
|
||||
goto out;
|
||||
|
||||
@@ -999,6 +999,7 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct inode *inode = file->f_mapping->host;
|
||||
struct address_space *mapping = inode->i_mapping;
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_holder gh;
|
||||
int rv;
|
||||
@@ -1019,6 +1020,35 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
|
||||
if (rv != 1)
|
||||
goto out; /* dio not valid, fall back to buffered i/o */
|
||||
|
||||
/*
|
||||
* Now since we are holding a deferred (CW) lock at this point, you
|
||||
* might be wondering why this is ever needed. There is a case however
|
||||
* where we've granted a deferred local lock against a cached exclusive
|
||||
* glock. That is ok provided all granted local locks are deferred, but
|
||||
* it also means that it is possible to encounter pages which are
|
||||
* cached and possibly also mapped. So here we check for that and sort
|
||||
* them out ahead of the dio. The glock state machine will take care of
|
||||
* everything else.
|
||||
*
|
||||
* If in fact the cached glock state (gl->gl_state) is deferred (CW) in
|
||||
* the first place, mapping->nr_pages will always be zero.
|
||||
*/
|
||||
if (mapping->nrpages) {
|
||||
loff_t lstart = offset & (PAGE_CACHE_SIZE - 1);
|
||||
loff_t len = iov_length(iov, nr_segs);
|
||||
loff_t end = PAGE_ALIGN(offset + len) - 1;
|
||||
|
||||
rv = 0;
|
||||
if (len == 0)
|
||||
goto out;
|
||||
if (test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags))
|
||||
unmap_shared_mapping_range(ip->i_inode.i_mapping, offset, len);
|
||||
rv = filemap_write_and_wait_range(mapping, lstart, end);
|
||||
if (rv)
|
||||
return rv;
|
||||
truncate_inode_pages_range(mapping, lstart, end);
|
||||
}
|
||||
|
||||
rv = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
|
||||
offset, nr_segs, gfs2_get_block_direct,
|
||||
NULL, NULL, 0);
|
||||
|
||||
@@ -1317,8 +1317,18 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,
|
||||
if (IS_ERR(s))
|
||||
goto error_bdev;
|
||||
|
||||
if (s->s_root)
|
||||
if (s->s_root) {
|
||||
/*
|
||||
* s_umount nests inside bd_mutex during
|
||||
* __invalidate_device(). blkdev_put() acquires
|
||||
* bd_mutex and can't be called under s_umount. Drop
|
||||
* s_umount temporarily. This is safe as we're
|
||||
* holding an active reference.
|
||||
*/
|
||||
up_write(&s->s_umount);
|
||||
blkdev_put(bdev, mode);
|
||||
down_write(&s->s_umount);
|
||||
}
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.ar_quota = GFS2_QUOTA_DEFAULT;
|
||||
|
||||
Reference in New Issue
Block a user