- libuuid?
+yehuda
+- what is the purpose of ceph_inode_info.i_hashval.. can we remove it..
+
+
snaps on mds
- cap release probably needs ack by mds. or, mds needs to possibly initiate recovery on import? no, release should pbly just be acked by mds... like it was way back when... bah!
dout(10, "readpage inode %p file %p page %p index %lu\n",
inode, filp, page, page->index);
- err = ceph_osdc_readpage(osdc, ceph_ino(inode), &ci->i_layout,
+ err = ceph_osdc_readpage(osdc, ceph_vino(inode), &ci->i_layout,
page->index << PAGE_SHIFT, PAGE_SIZE, page);
if (unlikely(err < 0))
goto out;
BUG_ON(list_empty(page_list));
page = list_entry(page_list->prev, struct page, lru);
offset = page->index << PAGE_CACHE_SHIFT;
- rc = ceph_osdc_readpages(osdc, mapping, ceph_ino(inode), &ci->i_layout,
+ rc = ceph_osdc_readpages(osdc, mapping, ceph_vino(inode), &ci->i_layout,
offset, nr_pages << PAGE_CACHE_SHIFT,
page_list, nr_pages);
if (rc < 0)
page_cache_get(page);
was_dirty = PageDirty(page);
set_page_writeback(page);
- err = ceph_osdc_writepages(osdc, ceph_ino(inode), &ci->i_layout,
+ err = ceph_osdc_writepages(osdc, ceph_vino(inode), &ci->i_layout,
page_off, len, &page, 1);
if (err >= 0) {
if (was_dirty) {
dout(10, "writepages got %d pages at %llu~%llu\n",
locked_pages, offset, len);
rc = ceph_osdc_writepages(&client->osdc,
- ceph_ino(inode),
+ ceph_vino(inode),
&ci->i_layout,
offset, len,
pagep,
/* or, do sub-page granularity dirty accounting? */
/* try to read the full page */
ci = ceph_inode(inode);
- r = ceph_osdc_readpage(osdc, ceph_ino(inode), &ci->i_layout,
+ r = ceph_osdc_readpage(osdc, ceph_vino(inode), &ci->i_layout,
page_off, PAGE_SIZE, page);
if (r < 0)
return r;
goto retry;
}
- *base = ceph_ino(temp->d_inode);
+ *base = ceph_vino(temp->d_inode).ino;
*plen = len;
dout(10, "build_path_dentry on %p %d built %llx '%.*s'\n",
dentry, atomic_read(&dentry->d_count), *base, len, path);
if (fi->frag != frag || fi->last_readdir == NULL) {
struct ceph_mds_request *req;
struct ceph_mds_request_head *rhead;
+ char *path;
+ int pathlen;
+ u64 pathbase;
frag = ceph_choose_frag(ceph_inode(inode), frag, 0);
/* query mds */
- dout(10, "dir_readdir querying mds for ino %llx frag %x\n",
- ceph_ino(inode), frag);
+ dout(10, "dir_readdir querying mds for ino %llx.%llx frag %x\n",
+ ceph_vinop(inode), frag);
+ path = ceph_build_dentry_path(filp->f_dentry, &pathlen,
+ &pathbase, 1);
req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_READDIR,
- ceph_ino(inode), "", 0, 0,
+ pathbase, path, 0, 0,
filp->f_dentry, USE_AUTH_MDS);
+ kfree(path);
if (IS_ERR(req))
return PTR_ERR(req);
req->r_direct_hash = frag_value(frag);
dout(10, "do_lookup %p mask %d\n", dentry, mask);
if (on_inode) {
/* stat ino directly */
+ WARN_ON(ceph_vino(dentry->d_inode).snap != CEPH_NOSNAP);
req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LSTAT,
- ceph_ino(dentry->d_inode), 0,
+ ceph_vino(dentry->d_inode).ino,0,
0, 0,
dentry, USE_CAP_MDS);
} else {
dout(10, "d_revalidate %p '%.*s' inode %p\n", dentry,
dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
- if (ceph_ino(dir) != 1 && /* ICONTENT useless on root inode */
+ if (ceph_vino(dir).ino != 1 && /* ICONTENT useless on root inode */
ceph_inode(dir)->i_version == dentry->d_time &&
ceph_inode_lease_valid(dir, CEPH_LOCK_ICONTENT)) {
dout(20, "dentry_revalidate %p %lu ICONTENT on dir %p %llu\n",
* pretty sure this is racy
*/
/* note: caller holds dentry->d_lock */
- fh[0].ino = cpu_to_le64(ceph_ino(dentry->d_inode));
+ fh[0].ino = cpu_to_le64(ceph_vino(dentry->d_inode).ino);
fh[0].dname_hash = cpu_to_le32(dentry->d_name.hash);
len = 1;
while (len < max) {
dentry = dentry->d_parent;
if (!dentry)
break;
- fh[len].ino = cpu_to_le64(ceph_ino(dentry->d_inode));
+ fh[len].ino = cpu_to_le64(ceph_vino(dentry->d_inode).ino);
fh[len].dname_hash = cpu_to_le32(dentry->d_name.hash);
len++;
type = 2;
struct inode *inode;
struct dentry *dentry;
int err;
- u64 ino = le64_to_cpu(fh[0].ino);
+ struct ceph_vino vino = {
+ .ino = le64_to_cpu(fh[0].ino),
+ .snap = CEPH_NOSNAP, /* FIXME */
+ };
u32 hash = le32_to_cpu(fh[0].dname_hash);
- inode = ceph_find_inode(sb, ino);
+ inode = ceph_find_inode(sb, vino);
if (!inode) {
struct ceph_mds_request *req;
- derr(10, "__fh_to_dentry %llx.%x -- no inode\n", ino, hash);
+ derr(10, "__fh_to_dentry %llx.%x -- no inode\n", vino.ino,hash);
req = ceph_mdsc_create_request(mdsc,
CEPH_MDS_OP_FINDINODE,
err = ceph_mdsc_do_request(mdsc, req);
ceph_mdsc_put_request(req);
- inode = ceph_find_inode(sb, ino);
+ inode = ceph_find_inode(sb, vino);
if (!inode)
return ERR_PTR(err ? err : -ESTALE);
}
dentry = d_alloc_anon(inode);
if (!dentry) {
- derr(10, "__fh_to_dentry %llx.%x -- inode %p but ENOMEM\n", ino,
+ derr(10, "__fh_to_dentry %llx.%x -- inode %p but ENOMEM\n",
+ vino.ino,
hash, inode);
iput(inode);
return ERR_PTR(-ENOMEM);
}
- dout(10, "__fh_to_dentry %llx.%x -- inode %p dentry %p\n", ino, hash,
- inode, dentry);
+ dout(10, "__fh_to_dentry %llx.%x -- inode %p dentry %p\n", vino.ino,
+ hash, inode, dentry);
return dentry;
}
if (S_ISDIR(inode->i_mode))
flags = O_DIRECTORY;
- dout(5, "open inode %p ino %llx file %p flags %d (%d)\n", inode,
- ceph_ino(inode), file, flags, file->f_flags);
+ dout(5, "open inode %p ino %llx.%llx file %p flags %d (%d)\n", inode,
+ ceph_vinop(inode), file, flags, file->f_flags);
fmode = ceph_flags_to_mode(flags);
wantcaps = ceph_caps_for_mode(fmode);
if (err == 0)
err = ceph_init_file(inode, file, req->r_fmode);
ceph_mdsc_put_request(req);
- dout(5, "open result=%d on %llx\n", err, ceph_ino(inode));
+ dout(5, "open result=%d on %llx.%llx\n", err, ceph_vinop(inode));
out:
dput(dentry);
return err;
dout(10, "sync_read on file %p %lld~%u\n", file, *offset,
(unsigned)count);
- ret = ceph_osdc_sync_read(&client->osdc, ceph_ino(inode),
+ ret = ceph_osdc_sync_read(&client->osdc, ceph_vino(inode),
&ci->i_layout,
pos, count, data);
if (ret > 0)
if (file->f_flags & O_APPEND)
pos = i_size_read(inode);
- ret = ceph_osdc_sync_write(&client->osdc, ceph_ino(inode),
+ ret = ceph_osdc_sync_write(&client->osdc, ceph_vino(inode),
&ci->i_layout,
pos, count, data);
if (ret > 0) {
__ceph_do_pending_vmtruncate(inode);
- dout(10, "aio_read %llx %llu~%u trying to get caps on %p\n",
- ceph_ino(inode), pos, (unsigned)len, inode);
+ dout(10, "aio_read %llx.%llx %llu~%u trying to get caps on %p\n",
+ ceph_vinop(inode), pos, (unsigned)len, inode);
ret = wait_event_interruptible(ci->i_cap_wq,
ceph_get_cap_refs(ci, CEPH_CAP_RD,
CEPH_CAP_RDCACHE,
&got, -1));
if (ret < 0)
goto out;
- dout(10, "aio_read %llx %llu~%u got cap refs %d\n",
- ceph_ino(inode), pos, (unsigned)len, got);
+ dout(10, "aio_read %llx.%llx %llu~%u got cap refs %d\n",
+ ceph_vinop(inode), pos, (unsigned)len, got);
if ((got & CEPH_CAP_RDCACHE) == 0 ||
(inode->i_sb->s_flags & MS_SYNCHRONOUS))
ret = generic_file_aio_read(iocb, iov, nr_segs, pos);
out:
- dout(10, "aio_read %llx dropping cap refs on %d\n", ceph_ino(inode),
- got);
+ dout(10, "aio_read %llx.%llx dropping cap refs on %d\n",
+ ceph_vinop(inode), got);
ceph_put_cap_refs(ci, got);
return ret;
}
/*
* find or create an inode, given the ceph ino number
*/
-struct inode *ceph_get_inode(struct super_block *sb, __u64 ino)
+struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino)
{
struct inode *inode;
struct ceph_inode_info *ci;
- ino_t inot;
+ ino_t t = ceph_vino_to_ino(vino);
- inot = ceph_ino_to_ino(ino);
-#if BITS_PER_LONG == 64
- inode = iget_locked(sb, ino);
-#else
- inode = iget5_locked(sb, inot, ceph_ino_compare, ceph_set_ino_cb, &ino);
-#endif
+ inode = iget5_locked(sb, t, ceph_ino_compare, ceph_set_ino_cb, &vino);
if (inode == NULL)
return ERR_PTR(-ENOMEM);
if (inode->i_state & I_NEW) {
- dout(40, "get_inode created new inode %p %llx\n", inode,
- ceph_ino(inode));
+ dout(40, "get_inode created new inode %p %llx.%llx\n", inode,
+ ceph_vinop(inode));
unlock_new_inode(inode);
}
ci = ceph_inode(inode);
- ceph_set_ino(inode, ino);
+ ceph_set_ino(inode, vino);
ci->i_hashval = inode->i_ino;
- dout(30, "get_inode on %lu=%llx got %p\n", inode->i_ino, ino, inode);
+ dout(30, "get_inode on %lu=%llx.%llx got %p\n", inode->i_ino, vino.ino,
+ vino.snap, inode);
return inode;
}
rb_link_node(&frag->node, parent, p);
rb_insert_color(&frag->node, &ci->i_fragtree);
- dout(20, "get_frag added %llx frag %x\n", ceph_ino(&ci->vfs_inode), f);
+ dout(20, "get_frag added %llx.%llx frag %x\n",
+ ceph_vinop(&ci->vfs_inode), f);
out:
kfree(newfrag);
goto out;
if (frag->split_by == 0) {
/* tree leaf, remove */
- dout(20, "fill_dirfrag removed %llx frag %x (no ref)\n",
- ceph_ino(inode), id);
+ dout(20, "fill_dirfrag removed %llx.%llx frag %x"
+ " (no ref)\n", ceph_vinop(inode), id);
rb_erase(&frag->node, &ci->i_fragtree);
kfree(frag);
} else {
/* tree branch, keep */
- dout(20, "fill_dirfrag cleared %llx frag %x referral\n",
- ceph_ino(inode), id);
+ dout(20, "fill_dirfrag cleared %llx.%llx frag %x"
+ " referral\n", ceph_vinop(inode), id);
frag->mds = -1;
frag->ndist = 0;
}
/* find/add this frag to store mds delegation info */
frag = __ceph_get_frag(ci, id);
if (IS_ERR(frag)) {
- derr(0, "fill_dirfrag ENOMEM on mds ref ino %llx frag %x\n",
- ceph_ino(inode), le32_to_cpu(dirinfo->frag));
+ derr(0, "fill_dirfrag ENOMEM on mds ref %llx.%llx frag %x\n",
+ ceph_vinop(inode), le32_to_cpu(dirinfo->frag));
err = -ENOMEM;
goto out;
}
frag->ndist = min_t(u32, ndist, MAX_DIRFRAG_REP);
for (i = 0; i < frag->ndist; i++)
frag->dist[i] = le32_to_cpu(dirinfo->dist[i]);
- dout(20, "fill_dirfrag %llx frag %x referral mds %d ndist=%d\n",
- ceph_ino(inode), frag->frag, frag->mds, frag->ndist);
+ dout(20, "fill_dirfrag %llx.%llx frag %x referral mds %d ndist=%d\n",
+ ceph_vinop(inode), frag->frag, frag->mds, frag->ndist);
out:
spin_unlock(&inode->i_lock);
u32 id = le32_to_cpu(info->fragtree.splits[i].frag);
struct ceph_inode_frag *frag = __ceph_get_frag(ci, id);
if (IS_ERR(frag)) {
- derr(0,"ENOMEM on ino %llx frag %x\n",
- ceph_ino(inode), id);
+ derr(0,"ENOMEM on ino %llx.%llx frag %x\n",
+ ceph_vinop(inode), id);
continue;
}
frag->split_by =
realdn = d_materialise_unique(dn, in);
if (IS_ERR(realdn)) {
derr(0, "error splicing %p (%d) with %p (%d) "
- "inode %p ino %llx\n",
+ "inode %p ino %llx.%llx\n",
dn, atomic_read(&dn->d_count),
realdn, atomic_read(&realdn->d_count),
realdn->d_inode,
- ceph_ino(realdn->d_inode));
+ ceph_vinop(realdn->d_inode));
if (prehash)
*prehash = false; /* don't rehash on error */
goto out;
} else if (realdn) {
dout(10, "dn %p (%d) spliced with %p (%d) "
- "inode %p ino %llx\n",
+ "inode %p ino %llx.%llx\n",
dn, atomic_read(&dn->d_count),
realdn, atomic_read(&realdn->d_count),
realdn->d_inode,
- ceph_ino(realdn->d_inode));
+ ceph_vinop(realdn->d_inode));
dput(dn);
dn = realdn;
ceph_init_dentry(dn);
} else
- dout(10, "dn %p attached to %p ino %llx\n",
- dn, dn->d_inode, ceph_ino(dn->d_inode));
+ dout(10, "dn %p attached to %p ino %llx.%llx\n",
+ dn, dn->d_inode, ceph_vinop(dn->d_inode));
if ((!prehash || *prehash) && d_unhashed(dn))
d_rehash(dn);
out:
struct inode *in;
struct ceph_mds_reply_inode *ininfo;
int d = 0;
- u64 ino;
+ struct ceph_vino vino;
int have_icontent = 0;
bool have_lease = 0;
}
#endif
- ino = le64_to_cpu(rinfo->trace_in[0].in->ino);
+ vino.ino = le64_to_cpu(rinfo->trace_in[0].in->ino);
+ vino.snap = le64_to_cpu(rinfo->trace_in[0].in->snapid);
if (likely(dn)) {
in = dn->d_inode;
/* trace should start at root, or have only 1 dentry
* (if it is in mds stray dir) */
- WARN_ON(ino != 1 && rinfo->trace_numd != 1);
+ WARN_ON(vino.ino != 1 && rinfo->trace_numd != 1);
} else {
/* first reply (i.e. mount) */
- in = ceph_get_inode(sb, ino);
+ in = ceph_get_inode(sb, vino);
if (IS_ERR(in))
return PTR_ERR(in);
dn = d_alloc_root(in);
}
}
- if (ino == 1) {
+ if (vino.ino == 1) {
err = ceph_fill_inode(in, &rinfo->trace_in[0],
rinfo->trace_numd ?
rinfo->trace_dir[0]:0);
/* attach proper inode */
ininfo = rinfo->trace_in[d+1].in;
+ vino.ino = le64_to_cpu(ininfo->ino);
+ vino.snap = le64_to_cpu(ininfo->snapid);
if (dn->d_inode) {
- if (ceph_ino(dn->d_inode) != le64_to_cpu(ininfo->ino)) {
- dout(10, "dn %p wrong inode %p ino %llx\n",
- dn, dn->d_inode, ceph_ino(dn->d_inode));
+ if (ceph_vino(dn->d_inode).ino != vino.ino ||
+ ceph_vino(dn->d_inode).snap != vino.snap) {
+ dout(10, "dn %p wrong inode %p ino %llx.%llx\n",
+ dn, dn->d_inode, ceph_vinop(dn->d_inode));
d_delete(dn);
dput(dn);
goto retry_lookup;
}
- dout(10, "dn %p correct %p ino %llx\n",
- dn, dn->d_inode, ceph_ino(dn->d_inode));
+ dout(10, "dn %p correct %p ino %llx.%llx\n",
+ dn, dn->d_inode, ceph_vinop(dn->d_inode));
in = dn->d_inode;
} else {
- in = ceph_get_inode(dn->d_sb, le64_to_cpu(ininfo->ino));
+ in = ceph_get_inode(dn->d_sb, vino);
if (IS_ERR(in)) {
derr(30, "get_inode badness\n");
err = PTR_ERR(in);
/* find existing inode */
ininfo = rinfo->trace_in[d+1].in;
- in = ceph_get_inode(parent->d_sb, le64_to_cpu(ininfo->ino));
+ vino.ino = le64_to_cpu(ininfo->ino);
+ vino.snap = le64_to_cpu(ininfo->snapid);
+ in = ceph_get_inode(parent->d_sb, vino);
if (IS_ERR(in)) {
derr(30, "ceph_get_inode badness\n");
err = PTR_ERR(in);
ceph_fill_dirfrag(parent->d_inode, rinfo->dir_dir);
for (i = 0; i < rinfo->dir_nr; i++) {
+ struct ceph_vino vino;
/* dentry */
dname.name = rinfo->dir_dname[i];
- dname.len = rinfo->dir_dname_len[i];
+ dname.len = le32_to_cpu(rinfo->dir_dname_len[i]);
dname.hash = full_name_hash(dname.name, dname.len);
+ vino.ino = le64_to_cpu(rinfo->dir_in[i].in->ino);
+ vino.snap = le64_to_cpu(rinfo->dir_in[i].in->snapid);
+
retry_lookup:
dn = d_lookup(parent, &dname);
dout(30, "calling d_lookup on parent=%p name=%.*s"
}
ceph_init_dentry(dn);
} else if (dn->d_inode &&
- ceph_ino(dn->d_inode) !=
- le64_to_cpu(rinfo->dir_in[i].in->ino)) {
+ (ceph_vino(dn->d_inode).ino != vino.ino ||
+ ceph_vino(dn->d_inode).snap != vino.snap)) {
dout(10, " dn %p points to wrong inode %p\n",
dn, dn->d_inode);
d_delete(dn);
if (dn->d_inode)
in = dn->d_inode;
else {
- in = ceph_get_inode(parent->d_sb,
- rinfo->dir_in[i].in->ino);
+ in = ceph_get_inode(parent->d_sb, vino);
if (in == NULL) {
dout(30, "new_inode badness\n");
d_delete(dn);
}
}
- dout(10, "add_cap inode %p (%llx) got cap %xh now %xh seq %d from %d\n",
- inode, ceph_ino(inode), issued, issued|cap->issued, seq, mds);
+ dout(10, "add_cap inode %p (%llx.%llx) cap %xh now %xh seq %d mds%d\n",
+ inode, ceph_vinop(inode), issued, issued|cap->issued, seq, mds);
cap->issued |= issued;
cap->implemented |= issued;
cap->seq = seq;
* or we'll be mixing up different instances of caps on the
* same inode, and confuse the mds.
*/
- dout(10, "no cap on %p ino %llx from mds%d, ignoring\n",
- inode, ci->i_ceph_ino, mds);
+ dout(10, "no cap on %p ino %llx.%llx from mds%d, ignoring\n",
+ inode, ci->i_vino.ino, ci->i_vino.snap, mds);
goto out;
}
dout(10, " cap %p\n", cap);
u64 pathbase;
if (ia_valid & ATTR_FILE) {
- dout(5, "prepare_setattr dentry %p (inode %llx)\n", dentry,
- ceph_ino(dentry->d_inode));
+ dout(5, "prepare_setattr dentry %p (inode %llx.%llx)\n", dentry,
+ ceph_vinop(dentry->d_inode));
req = ceph_mdsc_create_request(mdsc, op,
- ceph_ino(dentry->d_inode), "",
- 0, 0,
+ ceph_vino(dentry->d_inode).ino,
+ "", 0, 0,
dentry, USE_CAP_MDS);
} else {
dout(5, "prepare_setattr dentry %p (full path)\n", dentry);
return err;
bad:
- derr(10, "corrupt xattr info on %p %llx\n", dentry->d_inode,
- ceph_ino(dentry->d_inode));
+ derr(10, "corrupt xattr info on %p %llx.%llx\n", dentry->d_inode,
+ ceph_vinop(dentry->d_inode));
err = -EIO;
goto out;
}
return err;
bad:
- derr(10, "corrupt xattr info on %p %llx\n", dentry->d_inode,
- ceph_ino(dentry->d_inode));
+ derr(10, "corrupt xattr info on %p %llx.%llx\n", dentry->d_inode,
+ ceph_vinop(dentry->d_inode));
err = -EIO;
goto out;
}
if (mode == USE_CAP_MDS) {
mds = ceph_get_cap_mds(dentry->d_inode);
if (mds >= 0) {
- dout(20, "choose_mds %p %llx mds%d (cap)\n",
- dentry->d_inode, ceph_ino(dentry->d_inode), mds);
+ dout(20, "choose_mds %p %llx.%llx mds%d (cap)\n",
+ dentry->d_inode, ceph_vinop(dentry->d_inode), mds);
return mds;
}
- derr(0, "choose_mds %p %llx has NO CAPS, using auth\n",
- dentry->d_inode, ceph_ino(dentry->d_inode));
+ derr(0, "choose_mds %p %llx.%llx has NO CAPS, using auth\n",
+ dentry->d_inode, ceph_vinop(dentry->d_inode));
WARN_ON(1);
mode = USE_AUTH_MDS;
}
get_random_bytes(&r, 1);
r %= frag->ndist;
mds = frag->dist[r];
- dout(20, "choose_mds %p %llx frag %u "
- "mds%d (%d/%d)\n", dentry->d_inode,
- ceph_ino(&ci->vfs_inode),
+ dout(20, "choose_mds %p %llx.%llx "
+ "frag %u mds%d (%d/%d)\n",
+ dentry->d_inode,
+ ceph_vinop(&ci->vfs_inode),
frag->frag, frag->mds,
(int)r, frag->ndist);
return mds;
mode = USE_AUTH_MDS;
if (frag->mds >= 0) {
mds = frag->mds;
- dout(20, "choose_mds %p %llx frag %u "
- "mds%d (auth)\n", dentry->d_inode,
- ceph_ino(&ci->vfs_inode),
+ dout(20, "choose_mds %p %llx.%llx "
+ "frag %u mds%d (auth)\n",
+ dentry->d_inode,
+ ceph_vinop(&ci->vfs_inode),
frag->frag, mds);
return mds;
}
send_msg_mds(mdsc, req->r_request, mds);
wait_for_completion(&req->r_completion);
spin_lock(&mdsc->lock);
- if (req->r_reply == NULL)
+ if (req->r_reply == NULL) {
+ put_session(session);
+ req->r_session = 0;
goto retry;
+ }
/* clean up request, parse reply */
__unregister_request(mdsc, req);
ceph_decode_need(&p, end, sizeof(u64) +
sizeof(struct ceph_mds_cap_reconnect),
needmore);
- dout(10, " adding cap %p on ino %llx inode %p\n", cap,
- ceph_ino(&ci->vfs_inode), &ci->vfs_inode);
- ceph_encode_64(&p, ceph_ino(&ci->vfs_inode));
+ dout(10, " adding cap %p on ino %llx.%llx inode %p\n", cap,
+ ceph_vinop(&ci->vfs_inode), &ci->vfs_inode);
+ ceph_encode_64(&p, ceph_vino(&ci->vfs_inode).ino);
rec = p;
p += sizeof(*rec);
BUG_ON(p > end);
int mds = le32_to_cpu(msg->hdr.src.name.num);
int op;
u32 seq;
- u64 ino, size, max_size;
- ino_t inot;
+ struct ceph_vino vino;
+ u64 size, max_size;
dout(10, "handle_caps from mds%d\n", mds);
goto bad;
h = msg->front.iov_base;
op = le32_to_cpu(h->op);
- ino = le64_to_cpu(h->ino);
+ vino.ino = le64_to_cpu(h->ino);
+ vino.snap = CEPH_NOSNAP;
seq = le32_to_cpu(h->seq);
size = le64_to_cpu(h->size);
max_size = le64_to_cpu(h->max_size);
session->s_seq++;
/* lookup ino */
- inot = ceph_ino_to_ino(ino);
-#if BITS_PER_LONG == 64
- inode = ilookup(sb, ino);
-#else
- inode = ilookup5(sb, inot, ceph_ino_compare, &ino);
-#endif
- dout(20, "op %d ino %llx inode %p\n", op, ino, inode);
+ inode = ceph_find_inode(sb, vino);
+ dout(20, "op %d ino %llx inode %p\n", op, vino.ino, inode);
if (!inode) {
- dout(10, "wtf, i don't have ino %lu=%llx? closing out cap\n",
- inot, ino);
- send_cap_ack(mdsc, ino, 0, 0, seq, size, 0, 0, 0, 0, mds);
+ dout(10, "i don't have ino %llx, sending release\n", vino.ino);
+ send_cap_ack(mdsc, vino.ino, 0, 0, seq, size, 0, 0, 0, 0, mds);
goto no_inode;
}
dout(20, "done invalidating pages on %p\n", inode);
}
- send_cap_ack(mdsc, ceph_ino(inode),
+ send_cap_ack(mdsc, ceph_vino(inode).ino,
keep, wanted, seq,
size, max_size, &mtime, &atime, time_warp_seq,
session->s_mds);
struct dentry *parent, *dentry;
int mds = le32_to_cpu(msg->hdr.src.name.num);
struct ceph_mds_lease *h = msg->front.iov_base;
- u64 ino;
+ struct ceph_vino vino;
int mask;
struct qstr dname;
- ino_t inot;
dout(10, "handle_lease from mds%d\n", mds);
/* decode */
if (msg->front.iov_len < sizeof(*h) + sizeof(u32))
goto bad;
- ino = le64_to_cpu(h->ino);
+ vino.ino = le64_to_cpu(h->ino);
+ vino.snap = CEPH_NOSNAP;
mask = le16_to_cpu(h->mask);
dname.name = (void *)h + sizeof(*h) + sizeof(u32);
dname.len = msg->front.iov_len - sizeof(*h) - sizeof(u32);
mutex_lock(&session->s_mutex);
/* lookup inode */
- inot = ceph_ino_to_ino(ino);
-#if BITS_PER_LONG == 64
- inode = ilookup(sb, ino);
-#else
- inode = ilookup5(sb, inot, ceph_ino_compare, &ino);
-#endif
+ inode = ceph_find_inode(sb, vino);
dout(20, "action is %d, mask %d, ino %llx %p\n", h->action,
- mask, ino, inode);
-
- BUG_ON(h->action != CEPH_MDS_LEASE_REVOKE); /* for now */
-
+ mask, vino.ino, inode);
if (inode == NULL) {
- dout(10, "i don't have inode %llx\n", ino);
+ dout(10, "i don't have inode %llx\n", vino.ino);
goto release;
}
+ BUG_ON(h->action != CEPH_MDS_LEASE_REVOKE); /* for now */
+
/* inode */
ci = ceph_inode(inode);
revoke_inode_lease(ci, mask);
lease = msg->front.iov_base;
lease->action = CEPH_MDS_LEASE_RELEASE;
lease->mask = mask;
- lease->ino = cpu_to_le64(ceph_ino(inode));
+ lease->ino = cpu_to_le64(ceph_vino(inode).ino);
*(__le32 *)((void *)lease + sizeof(*lease)) = cpu_to_le32(dnamelen);
if (dentry)
memcpy((void *)lease + sizeof(*lease) + 4, dentry->d_name.name,
#include <linux/completion.h>
#include <linux/spinlock.h>
+#include "types.h"
#include "messenger.h"
#include "mdsmap.h"
extern struct ceph_mds_request *
ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op,
- ceph_ino_t ino1, const char *path1,
- ceph_ino_t ino2, const char *path2,
+ u64 ino1, const char *path1,
+ u64 ino2, const char *path2,
struct dentry *ref, int want_auth);
extern int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
struct ceph_mds_request *req);
* object boundary.
*/
static __u64 calc_layout(struct ceph_osd_client *osdc,
- ceph_ino_t ino, struct ceph_file_layout *layout,
+ struct ceph_vino vino, struct ceph_file_layout *layout,
__u64 off, __u64 len,
struct ceph_osd_request *req)
{
struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base;
__u64 toff = off, tlen = len;
- reqhead->oid.ino = ino;
- reqhead->oid.snap = 0;
+ reqhead->oid.ino = vino.ino;
+ reqhead->oid.snap = vino.snap;
calc_file_object_mapping(layout, &toff, &tlen, &reqhead->oid,
&off, &len);
/*
* synchronous read direct to user buffer
*/
-int ceph_osdc_sync_read(struct ceph_osd_client *osdc, ceph_ino_t ino,
+int ceph_osdc_sync_read(struct ceph_osd_client *osdc, struct ceph_vino vino,
struct ceph_file_layout *layout,
__u64 off, __u64 len,
char __user *data)
int nr_pages, i, po, left, l;
__s32 rc;
- dout(10, "sync_read on ino %llx at %llu~%llu\n", ino, off, len);
+ dout(10, "sync_read on vino %llx.%llx at %llu~%llu\n", vino.ino,
+ vino.snap, off, len);
/* request msg */
reqm = new_request_msg(osdc, CEPH_OSD_OP_READ);
if (IS_ERR(req))
return PTR_ERR(req);
- len = calc_layout(osdc, ino, layout, off, len, req);
+ len = calc_layout(osdc, vino, layout, off, len, req);
nr_pages = calc_pages_for(off, len); /* recalc */
dout(10, "sync_read %llu~%llu -> %d pages\n", off, len, nr_pages);
/*
* read a single page.
*/
-int ceph_osdc_readpage(struct ceph_osd_client *osdc, ceph_ino_t ino,
+int ceph_osdc_readpage(struct ceph_osd_client *osdc, struct ceph_vino vino,
struct ceph_file_layout *layout,
loff_t off, loff_t len,
struct page *page)
struct ceph_osd_request *req;
__s32 rc;
- dout(10, "readpage on ino %llx at %lld~%lld\n", ino, off, len);
+ dout(10, "readpage on ino %llx.%llx at %lld~%lld\n", vino.ino,
+ vino.snap, off, len);
/* request msg */
reqm = new_request_msg(osdc, CEPH_OSD_OP_READ);
}
req->r_pages[0] = page;
- len = calc_layout(osdc, ino, layout, off, len, req);
+ len = calc_layout(osdc, vino, layout, off, len, req);
BUG_ON(len != PAGE_CACHE_SIZE);
rc = do_request(osdc, req);
*/
int ceph_osdc_readpages(struct ceph_osd_client *osdc,
struct address_space *mapping,
- ceph_ino_t ino, struct ceph_file_layout *layout,
+ struct ceph_vino vino, struct ceph_file_layout *layout,
__u64 off, __u64 len,
struct list_head *page_list, int nr_pages)
{
* we can that falls within the range specified by
* nr_pages.
*/
- dout(10, "readpages on ino %llx on %llu~%llu\n", ino, off, len);
+ dout(10, "readpages on ino %llx.%llx on %llu~%llu\n", vino.ino,
+ vino.snap, off, len);
/* alloc request, w/ optimistically-sized page vector */
reqm = new_request_msg(osdc, CEPH_OSD_OP_READ);
dout(10, "readpages contig page extent is %llu~%llu\n", off, len);
/* request msg */
- len = calc_layout(osdc, ino, layout, off, len, req);
+ len = calc_layout(osdc, vino, layout, off, len, req);
req->r_nr_pages = calc_pages_for(off, len);
dout(10, "readpages final extent is %llu~%llu -> %d pages\n",
off, len, req->r_nr_pages);
/*
* synchronous write. from userspace.
*/
-int ceph_osdc_sync_write(struct ceph_osd_client *osdc, ceph_ino_t ino,
+int ceph_osdc_sync_write(struct ceph_osd_client *osdc, struct ceph_vino vino,
struct ceph_file_layout *layout,
__u64 off, __u64 len, const char __user *data)
{
int nr_pages, i, po, l, left;
__s32 rc;
- dout(10, "sync_write on ino %llx at %llu~%llu\n", ino, off, len);
+ dout(10, "sync_write on ino %llx.%llx at %llu~%llu\n", vino.ino,
+ vino.snap, off, len);
/* request msg */
reqm = new_request_msg(osdc, CEPH_OSD_OP_WRITE);
return PTR_ERR(req);
}
- len = calc_layout(osdc, ino, layout, off, len, req);
+ len = calc_layout(osdc, vino, layout, off, len, req);
nr_pages = calc_pages_for(off, len); /* recalc */
dout(10, "sync_write %llu~%llu -> %d pages\n", off, len, nr_pages);
/*
* do a write job for N pages
*/
-int ceph_osdc_writepages(struct ceph_osd_client *osdc, ceph_ino_t ino,
+int ceph_osdc_writepages(struct ceph_osd_client *osdc, struct ceph_vino vino,
struct ceph_file_layout *layout,
loff_t off, loff_t len,
struct page **pages, int nr_pages)
struct ceph_osd_request *req;
int rc = 0;
+ BUG_ON(vino.snap != CEPH_NOSNAP);
+
/* request + msg */
reqm = new_request_msg(osdc, CEPH_OSD_OP_WRITE);
if (IS_ERR(reqm))
else
reqhead->flags = CEPH_OSD_OP_SAFE;
- len = calc_layout(osdc, ino, layout, off, len, req);
+ len = calc_layout(osdc, vino, layout, off, len, req);
nr_pages = calc_pages_for(off, len);
dout(10, "writepages %llu~%llu -> %d pages\n", off, len, nr_pages);
#include <linux/completion.h>
#include "ceph_fs.h"
+#include "types.h"
#include "osdmap.h"
struct ceph_msg;
struct ceph_msg *msg);
extern int ceph_osdc_prepare_pages(void *p, struct ceph_msg *m, int want);
-extern int ceph_osdc_readpage(struct ceph_osd_client *osdc, ceph_ino_t ino,
+extern int ceph_osdc_readpage(struct ceph_osd_client *osdc,
+ struct ceph_vino vino,
struct ceph_file_layout *layout,
loff_t off, loff_t len,
struct page *page);
extern int ceph_osdc_readpages(struct ceph_osd_client *osdc,
struct address_space *mapping,
- ceph_ino_t ino, struct ceph_file_layout *layout,
+ struct ceph_vino vino,
+ struct ceph_file_layout *layout,
__u64 off, __u64 len,
struct list_head *page_list, int nr_pages);
-extern int ceph_osdc_prepare_write(struct ceph_osd_client *osdc, ceph_ino_t ino,
- struct ceph_file_layout *layout,
- loff_t off, loff_t len,
- struct page *page);
-extern int ceph_osdc_commit_write(struct ceph_osd_client *osdc, ceph_ino_t ino,
- struct ceph_file_layout *layout,
- loff_t off, loff_t len,
- struct page *page);
-extern int ceph_osdc_writepages(struct ceph_osd_client *osdc, ceph_ino_t ino,
+extern int ceph_osdc_prepare_write(struct ceph_osd_client *osdc,
+ struct ceph_vino vino,
+ struct ceph_file_layout *layout,
+ loff_t off, loff_t len,
+ struct page *page);
+extern int ceph_osdc_commit_write(struct ceph_osd_client *osdc,
+ struct ceph_vino vino,
+ struct ceph_file_layout *layout,
+ loff_t off, loff_t len,
+ struct page *page);
+extern int ceph_osdc_writepages(struct ceph_osd_client *osdc,
+ struct ceph_vino vino,
struct ceph_file_layout *layout,
loff_t off, loff_t len,
struct page **pagevec, int nr_pages);
-extern int ceph_osdc_sync_read(struct ceph_osd_client *osdc, ceph_ino_t ino,
+extern int ceph_osdc_sync_read(struct ceph_osd_client *osdc,
+ struct ceph_vino vino,
struct ceph_file_layout *layout,
__u64 off, __u64 len,
char __user *data);
-extern int ceph_osdc_sync_write(struct ceph_osd_client *osdc, ceph_ino_t ino,
+extern int ceph_osdc_sync_write(struct ceph_osd_client *osdc,
+ struct ceph_vino vino,
struct ceph_file_layout *layout,
__u64 off, __u64 len,
const char __user *data);
-extern int ceph_osdc_prepare_write(struct ceph_osd_client *osdc, ceph_ino_t ino,
+extern int ceph_osdc_prepare_write(struct ceph_osd_client *osdc,
+ struct ceph_vino vino,
struct ceph_file_layout *layout,
loff_t off, loff_t len,
struct page *page);
-extern int ceph_osdc_commit_write(struct ceph_osd_client *osdc, ceph_ino_t ino,
+extern int ceph_osdc_commit_write(struct ceph_osd_client *osdc,
+ struct ceph_vino vino,
struct ceph_file_layout *layout,
loff_t off, loff_t len,
struct page *page);
-extern int ceph_osdc_writepage(struct ceph_osd_client *osdc, ceph_ino_t ino,
+extern int ceph_osdc_writepage(struct ceph_osd_client *osdc,
+ struct ceph_vino vino,
struct ceph_file_layout *layout,
loff_t off, loff_t len,
struct page *page);
struct ceph_inode_info *ci = ceph_inode(inode);
if (memcmp(&ci->i_old_atime, &inode->i_atime, sizeof(struct timeval))) {
- dout(30, "ceph_write_inode %llx .. atime updated\n",
- ceph_ino(inode));
+ dout(30, "ceph_write_inode %llx.%llx .. atime updated\n",
+ ceph_vinop(inode));
/* eventually push this async to mds ... */
}
return 0;
struct ceph_inode_frag *frag;
struct rb_node *n;
- dout(30, "destroy_inode %p ino %llx\n", inode, ceph_ino(inode));
+ dout(30, "destroy_inode %p ino %llx.%llx\n", inode, ceph_vinop(inode));
kfree(ci->i_symlink);
while ((n = rb_first(&ci->i_fragtree)) != 0) {
frag = rb_entry(n, struct ceph_inode_frag, node);
err = ceph_mount(client, mnt, path);
if (err < 0)
goto out_splat;
- dout(22, "root ino %llx\n", ceph_ino(mnt->mnt_root->d_inode));
+ dout(22, "root ino %llx.%llx\n", ceph_vinop(mnt->mnt_root->d_inode));
return 0;
out_splat:
#include <linux/sysfs.h>
#include "ceph_fs.h"
+#include "types.h"
#include "messenger.h"
#include "mon_client.h"
#include "mds_client.h"
};
struct ceph_inode_info {
- u64 i_ceph_ino; /* make this ifdef away on 64 bit */
+ struct ceph_vino i_vino; /* ceph ino + snap */
+ unsigned long i_hashval;
u64 i_version;
u64 i_time_warp_seq;
int i_rd_ref, i_rdcache_ref, i_wr_ref;
atomic_t i_wrbuffer_ref;
- unsigned long i_hashval;
struct work_struct i_wb_work; /* writeback work */
/*
- * ino_t is <64 bits on many architectures... blech
+ * ino_t is <64 bits on many architectures, blech.
+ * let snapped inos chain up on the same linux ino_t.
*/
-static inline ino_t ceph_ino_to_ino(u64 cephino)
+static inline ino_t ceph_vino_to_ino(struct ceph_vino vino)
{
- ino_t ino = (ino_t)cephino;
+ ino_t ino = (ino_t)vino.ino;
#if BITS_PER_LONG == 32
- ino ^= cephino >> (sizeof(u64)-sizeof(ino_t)) * 8;
+ ino ^= vino.ino >> (sizeof(u64)-sizeof(ino_t)) * 8;
#endif
return ino;
}
-static inline void ceph_set_ino(struct inode *inode, __u64 ino)
+static inline void ceph_set_ino(struct inode *inode, struct ceph_vino vino)
{
struct ceph_inode_info *ci = ceph_inode(inode);
- ci->i_ceph_ino = ino;
- inode->i_ino = ceph_ino_to_ino(ino);
+ ci->i_vino = vino;
+ inode->i_ino = ceph_vino_to_ino(vino);
}
static inline int ceph_set_ino_cb(struct inode *inode, void *data)
{
- ceph_set_ino(inode, *(__u64 *)data);
+ ceph_set_ino(inode, *(struct ceph_vino *)data);
return 0;
}
-static inline u64 ceph_ino(struct inode *inode)
+static inline struct ceph_vino ceph_vino(struct inode *inode)
{
struct ceph_inode_info *ci = ceph_inode(inode);
- return ci->i_ceph_ino;
+ return ci->i_vino;
}
+#define ceph_vinop(i) ceph_inode(i)->i_vino.ino, ceph_inode(i)->i_vino.snap
static inline int ceph_ino_compare(struct inode *inode, void *data)
{
- __u64 ino = *(__u64 *)data;
+ struct ceph_vino *pvino = (struct ceph_vino *)data;
struct ceph_inode_info *ci = ceph_inode(inode);
- return (ci->i_ceph_ino == ino);
+ return (ci->i_vino.ino == pvino->ino &&
+ ci->i_vino.snap == pvino->snap);
}
-static inline struct inode *ceph_find_inode(struct super_block *sb, __u64 ino)
+static inline struct inode *ceph_find_inode(struct super_block *sb,
+ struct ceph_vino vino)
{
- ino_t inot = ceph_ino_to_ino(ino);
- return ilookup5(sb, inot, ceph_ino_compare, &ino);
+ ino_t t = ceph_vino_to_ino(vino);
+ return ilookup5(sb, t, ceph_ino_compare, &vino);
}
/* inode.c */
extern const struct inode_operations ceph_file_iops;
extern const struct inode_operations ceph_special_iops;
-extern struct inode *ceph_get_inode(struct super_block *sb, u64 ino);
+extern struct inode *ceph_get_inode(struct super_block *sb,
+ struct ceph_vino vino);
extern int ceph_fill_inode(struct inode *inode,
struct ceph_mds_reply_info_in *iinfo,
struct ceph_mds_reply_dirfrag *dirinfo);
--- /dev/null
+#ifndef _FS_CEPH_TYPES_H
+#define _FS_CEPH_TYPES_H
+
+struct ceph_vino {
+ u64 ino;
+ u64 snap;
+};
+
+#endif