Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/sage/ceph-client

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client:
  ceph: fix readdir EOVERFLOW on 32-bit archs
  ceph: fix frag offset for non-leftmost frags
  ceph: fix dangling pointer
  ceph: explicitly specify page alignment in network messages
  ceph: make page alignment explicit in osd interface
  ceph: fix comment, remove extraneous args
  ceph: fix update of ctime from MDS
  ceph: fix version check on racing inode updates
  ceph: fix uid/gid on resent mds requests
  ceph: fix rdcache_gen usage and invalidate
  ceph: re-request max_size if cap auth changes
  ceph: only let auth caps update max_size
  ceph: fix open for write on clustered mds
  ceph: fix bad pointer dereference in ceph_fill_trace
  ceph: fix small seq message skipping
  Revert "ceph: update issue_seq on cap grant"
  • Loading branch information
torvalds committed Nov 19, 2010
2 parents caf8394 + 3105c19 commit 76db8ac
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 76 deletions.
6 changes: 3 additions & 3 deletions fs/ceph/addr.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ static int readpage_nounlock(struct file *filp, struct page *page)
err = ceph_osdc_readpages(osdc, ceph_vino(inode), &ci->i_layout,
page->index << PAGE_CACHE_SHIFT, &len,
ci->i_truncate_seq, ci->i_truncate_size,
&page, 1);
&page, 1, 0);
if (err == -ENOENT)
err = 0;
if (err < 0) {
Expand Down Expand Up @@ -287,7 +287,7 @@ static int ceph_readpages(struct file *file, struct address_space *mapping,
rc = ceph_osdc_readpages(osdc, ceph_vino(inode), &ci->i_layout,
offset, &len,
ci->i_truncate_seq, ci->i_truncate_size,
pages, nr_pages);
pages, nr_pages, 0);
if (rc == -ENOENT)
rc = 0;
if (rc < 0)
Expand Down Expand Up @@ -774,7 +774,7 @@ static int ceph_writepages_start(struct address_space *mapping,
snapc, do_sync,
ci->i_truncate_seq,
ci->i_truncate_size,
&inode->i_mtime, true, 1);
&inode->i_mtime, true, 1, 0);
max_pages = req->r_num_pages;

alloc_page_vec(fsc, req);
Expand Down
17 changes: 10 additions & 7 deletions fs/ceph/caps.c
Original file line number Diff line number Diff line change
Expand Up @@ -1430,8 +1430,8 @@ static int try_nonblocking_invalidate(struct inode *inode)
invalidating_gen == ci->i_rdcache_gen) {
/* success. */
dout("try_nonblocking_invalidate %p success\n", inode);
ci->i_rdcache_gen = 0;
ci->i_rdcache_revoking = 0;
/* save any racing async invalidate some trouble */
ci->i_rdcache_revoking = ci->i_rdcache_gen - 1;
return 0;
}
dout("try_nonblocking_invalidate %p failed\n", inode);
Expand Down Expand Up @@ -2273,8 +2273,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
{
struct ceph_inode_info *ci = ceph_inode(inode);
int mds = session->s_mds;
unsigned seq = le32_to_cpu(grant->seq);
unsigned issue_seq = le32_to_cpu(grant->issue_seq);
int seq = le32_to_cpu(grant->seq);
int newcaps = le32_to_cpu(grant->caps);
int issued, implemented, used, wanted, dirty;
u64 size = le64_to_cpu(grant->size);
Expand All @@ -2286,8 +2285,8 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
int revoked_rdcache = 0;
int queue_invalidate = 0;

dout("handle_cap_grant inode %p cap %p mds%d seq %u/%u %s\n",
inode, cap, mds, seq, issue_seq, ceph_cap_string(newcaps));
dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n",
inode, cap, mds, seq, ceph_cap_string(newcaps));
dout(" size %llu max_size %llu, i_size %llu\n", size, max_size,
inode->i_size);

Expand Down Expand Up @@ -2383,7 +2382,6 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
}

cap->seq = seq;
cap->issue_seq = issue_seq;

/* file layout may have changed */
ci->i_layout = grant->layout;
Expand Down Expand Up @@ -2691,6 +2689,11 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
NULL /* no caps context */);
try_flush_caps(inode, session, NULL);
up_read(&mdsc->snap_rwsem);

/* make sure we re-request max_size, if necessary */
spin_lock(&inode->i_lock);
ci->i_requested_max_size = 0;
spin_unlock(&inode->i_lock);
}

/*
Expand Down
16 changes: 12 additions & 4 deletions fs/ceph/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,10 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (req->r_reply_info.dir_end) {
kfree(fi->last_name);
fi->last_name = NULL;
fi->next_offset = 2;
if (ceph_frag_is_rightmost(frag))
fi->next_offset = 2;
else
fi->next_offset = 0;
} else {
rinfo = &req->r_reply_info;
err = note_last_dentry(fi,
Expand All @@ -355,18 +358,22 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
u64 pos = ceph_make_fpos(frag, off);
struct ceph_mds_reply_inode *in =
rinfo->dir_in[off - fi->offset].in;
struct ceph_vino vino;
ino_t ino;

dout("readdir off %d (%d/%d) -> %lld '%.*s' %p\n",
off, off - fi->offset, rinfo->dir_nr, pos,
rinfo->dir_dname_len[off - fi->offset],
rinfo->dir_dname[off - fi->offset], in);
BUG_ON(!in);
ftype = le32_to_cpu(in->mode) >> 12;
vino.ino = le64_to_cpu(in->ino);
vino.snap = le64_to_cpu(in->snapid);
ino = ceph_vino_to_ino(vino);
if (filldir(dirent,
rinfo->dir_dname[off - fi->offset],
rinfo->dir_dname_len[off - fi->offset],
pos,
le64_to_cpu(in->ino),
ftype) < 0) {
pos, ino, ftype) < 0) {
dout("filldir stopping us...\n");
return 0;
}
Expand Down Expand Up @@ -414,6 +421,7 @@ static void reset_readdir(struct ceph_file_info *fi)
fi->last_readdir = NULL;
}
kfree(fi->last_name);
fi->last_name = NULL;
fi->next_offset = 2; /* compensate for . and .. */
if (fi->dentry) {
dput(fi->dentry);
Expand Down
52 changes: 34 additions & 18 deletions fs/ceph/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,13 @@ int ceph_open(struct inode *inode, struct file *file)
}

/*
* No need to block if we have any caps. Update wanted set
* No need to block if we have caps on the auth MDS (for
* write) or any MDS (for read). Update wanted set
* asynchronously.
*/
spin_lock(&inode->i_lock);
if (__ceph_is_any_real_caps(ci)) {
if (__ceph_is_any_real_caps(ci) &&
(((fmode & CEPH_FILE_MODE_WR) == 0) || ci->i_auth_cap)) {
int mds_wanted = __ceph_caps_mds_wanted(ci);
int issued = __ceph_caps_issued(ci, NULL);

Expand Down Expand Up @@ -280,11 +282,12 @@ int ceph_release(struct inode *inode, struct file *file)
static int striped_read(struct inode *inode,
u64 off, u64 len,
struct page **pages, int num_pages,
int *checkeof)
int *checkeof, bool align_to_pages)
{
struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
u64 pos, this_len;
int io_align, page_align;
int page_off = off & ~PAGE_CACHE_MASK; /* first byte's offset in page */
int left, pages_left;
int read;
Expand All @@ -300,14 +303,19 @@ static int striped_read(struct inode *inode,
page_pos = pages;
pages_left = num_pages;
read = 0;
io_align = off & ~PAGE_MASK;

more:
if (align_to_pages)
page_align = (pos - io_align) & ~PAGE_MASK;
else
page_align = pos & ~PAGE_MASK;
this_len = left;
ret = ceph_osdc_readpages(&fsc->client->osdc, ceph_vino(inode),
&ci->i_layout, pos, &this_len,
ci->i_truncate_seq,
ci->i_truncate_size,
page_pos, pages_left);
page_pos, pages_left, page_align);
hit_stripe = this_len < left;
was_short = ret >= 0 && ret < this_len;
if (ret == -ENOENT)
Expand Down Expand Up @@ -374,26 +382,25 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,
dout("sync_read on file %p %llu~%u %s\n", file, off, len,
(file->f_flags & O_DIRECT) ? "O_DIRECT" : "");

if (file->f_flags & O_DIRECT) {
pages = ceph_get_direct_page_vector(data, num_pages, off, len);

/*
* flush any page cache pages in this range. this
* will make concurrent normal and O_DIRECT io slow,
* but it will at least behave sensibly when they are
* in sequence.
*/
} else {
if (file->f_flags & O_DIRECT)
pages = ceph_get_direct_page_vector(data, num_pages);
else
pages = ceph_alloc_page_vector(num_pages, GFP_NOFS);
}
if (IS_ERR(pages))
return PTR_ERR(pages);

/*
* flush any page cache pages in this range. this
* will make concurrent normal and sync io slow,
* but it will at least behave sensibly when they are
* in sequence.
*/
ret = filemap_write_and_wait(inode->i_mapping);
if (ret < 0)
goto done;

ret = striped_read(inode, off, len, pages, num_pages, checkeof);
ret = striped_read(inode, off, len, pages, num_pages, checkeof,
file->f_flags & O_DIRECT);

if (ret >= 0 && (file->f_flags & O_DIRECT) == 0)
ret = ceph_copy_page_vector_to_user(pages, data, off, ret);
Expand Down Expand Up @@ -448,6 +455,7 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
int flags;
int do_sync = 0;
int check_caps = 0;
int page_align, io_align;
int ret;
struct timespec mtime = CURRENT_TIME;

Expand All @@ -462,6 +470,8 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
else
pos = *offset;

io_align = pos & ~PAGE_MASK;

ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left);
if (ret < 0)
return ret;
Expand All @@ -486,20 +496,26 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
*/
more:
len = left;
if (file->f_flags & O_DIRECT)
/* write from beginning of first page, regardless of
io alignment */
page_align = (pos - io_align) & ~PAGE_MASK;
else
page_align = pos & ~PAGE_MASK;
req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
ceph_vino(inode), pos, &len,
CEPH_OSD_OP_WRITE, flags,
ci->i_snap_realm->cached_context,
do_sync,
ci->i_truncate_seq, ci->i_truncate_size,
&mtime, false, 2);
&mtime, false, 2, page_align);
if (!req)
return -ENOMEM;

num_pages = calc_pages_for(pos, len);

if (file->f_flags & O_DIRECT) {
pages = ceph_get_direct_page_vector(data, num_pages, pos, len);
pages = ceph_get_direct_page_vector(data, num_pages);
if (IS_ERR(pages)) {
ret = PTR_ERR(pages);
goto out;
Expand Down
49 changes: 31 additions & 18 deletions fs/ceph/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,9 @@ void ceph_fill_file_time(struct inode *inode, int issued,

if (issued & (CEPH_CAP_FILE_EXCL|
CEPH_CAP_FILE_WR|
CEPH_CAP_FILE_BUFFER)) {
CEPH_CAP_FILE_BUFFER|
CEPH_CAP_AUTH_EXCL|
CEPH_CAP_XATTR_EXCL)) {
if (timespec_compare(ctime, &inode->i_ctime) > 0) {
dout("ctime %ld.%09ld -> %ld.%09ld inc w/ cap\n",
inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
Expand Down Expand Up @@ -510,7 +512,7 @@ void ceph_fill_file_time(struct inode *inode, int issued,
warn = 1;
}
} else {
/* we have no write caps; whatever the MDS says is true */
/* we have no write|excl caps; whatever the MDS says is true */
if (ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) >= 0) {
inode->i_ctime = *ctime;
inode->i_mtime = *mtime;
Expand Down Expand Up @@ -566,12 +568,17 @@ static int fill_inode(struct inode *inode,

/*
* provided version will be odd if inode value is projected,
* even if stable. skip the update if we have a newer info
* (e.g., due to inode info racing form multiple MDSs), or if
* we are getting projected (unstable) inode info.
* even if stable. skip the update if we have newer stable
* info (ours>=theirs, e.g. due to racing mds replies), unless
* we are getting projected (unstable) info (in which case the
* version is odd, and we want ours>theirs).
* us them
* 2 2 skip
* 3 2 skip
* 3 3 update
*/
if (le64_to_cpu(info->version) > 0 &&
(ci->i_version & ~1) > le64_to_cpu(info->version))
(ci->i_version & ~1) >= le64_to_cpu(info->version))
goto no_change;

issued = __ceph_caps_issued(ci, &implemented);
Expand Down Expand Up @@ -605,7 +612,14 @@ static int fill_inode(struct inode *inode,
le32_to_cpu(info->time_warp_seq),
&ctime, &mtime, &atime);

ci->i_max_size = le64_to_cpu(info->max_size);
/* only update max_size on auth cap */
if ((info->cap.flags & CEPH_CAP_FLAG_AUTH) &&
ci->i_max_size != le64_to_cpu(info->max_size)) {
dout("max_size %lld -> %llu\n", ci->i_max_size,
le64_to_cpu(info->max_size));
ci->i_max_size = le64_to_cpu(info->max_size);
}

ci->i_layout = info->layout;
inode->i_blkbits = fls(le32_to_cpu(info->layout.fl_stripe_unit)) - 1;

Expand Down Expand Up @@ -1054,7 +1068,8 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
ininfo = rinfo->targeti.in;
vino.ino = le64_to_cpu(ininfo->ino);
vino.snap = le64_to_cpu(ininfo->snapid);
if (!dn->d_inode) {
in = dn->d_inode;
if (!in) {
in = ceph_get_inode(sb, vino);
if (IS_ERR(in)) {
pr_err("fill_trace bad get_inode "
Expand Down Expand Up @@ -1385,11 +1400,8 @@ static void ceph_invalidate_work(struct work_struct *work)
spin_lock(&inode->i_lock);
dout("invalidate_pages %p gen %d revoking %d\n", inode,
ci->i_rdcache_gen, ci->i_rdcache_revoking);
if (ci->i_rdcache_gen == 0 ||
ci->i_rdcache_revoking != ci->i_rdcache_gen) {
BUG_ON(ci->i_rdcache_revoking > ci->i_rdcache_gen);
if (ci->i_rdcache_revoking != ci->i_rdcache_gen) {
/* nevermind! */
ci->i_rdcache_revoking = 0;
spin_unlock(&inode->i_lock);
goto out;
}
Expand All @@ -1399,15 +1411,16 @@ static void ceph_invalidate_work(struct work_struct *work)
ceph_invalidate_nondirty_pages(inode->i_mapping);

spin_lock(&inode->i_lock);
if (orig_gen == ci->i_rdcache_gen) {
if (orig_gen == ci->i_rdcache_gen &&
orig_gen == ci->i_rdcache_revoking) {
dout("invalidate_pages %p gen %d successful\n", inode,
ci->i_rdcache_gen);
ci->i_rdcache_gen = 0;
ci->i_rdcache_revoking = 0;
ci->i_rdcache_revoking--;
check = 1;
} else {
dout("invalidate_pages %p gen %d raced, gen now %d\n",
inode, orig_gen, ci->i_rdcache_gen);
dout("invalidate_pages %p gen %d raced, now %d revoking %d\n",
inode, orig_gen, ci->i_rdcache_gen,
ci->i_rdcache_revoking);
}
spin_unlock(&inode->i_lock);

Expand Down Expand Up @@ -1738,7 +1751,7 @@ int ceph_do_getattr(struct inode *inode, int mask)
return 0;
}

dout("do_getattr inode %p mask %s\n", inode, ceph_cap_string(mask));
dout("do_getattr inode %p mask %s mode 0%o\n", inode, ceph_cap_string(mask), inode->i_mode);
if (ceph_caps_issued_mask(ceph_inode(inode), mask, 1))
return 0;

Expand Down
7 changes: 5 additions & 2 deletions fs/ceph/mds_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,9 @@ static void __register_request(struct ceph_mds_client *mdsc,
ceph_mdsc_get_request(req);
__insert_request(mdsc, req);

req->r_uid = current_fsuid();
req->r_gid = current_fsgid();

if (dir) {
struct ceph_inode_info *ci = ceph_inode(dir);

Expand Down Expand Up @@ -1587,8 +1590,8 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,

head->mdsmap_epoch = cpu_to_le32(mdsc->mdsmap->m_epoch);
head->op = cpu_to_le32(req->r_op);
head->caller_uid = cpu_to_le32(current_fsuid());
head->caller_gid = cpu_to_le32(current_fsgid());
head->caller_uid = cpu_to_le32(req->r_uid);
head->caller_gid = cpu_to_le32(req->r_gid);
head->args = req->r_args;

ceph_encode_filepath(&p, end, ino1, path1);
Expand Down
Loading

0 comments on commit 76db8ac

Please sign in to comment.