int err;
struct ceph_inode_cap *cap;
struct ceph_inode_info *ci;
-
++ int alloc_fs = 0;
+
/* open dir */
dout(30, "open_root_inode opening '%s'\n", args->path);
req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_OPEN, 1, args->path, 0, 0);
return err;
err = le32_to_cpu(rinfo.head->result);
- if (err != 0)
- return err;
+ if (err != 0)
+ goto out;
if (rinfo.trace_nr == 0) {
dout(10, "open_root_inode wtf, mds returns 0 but no trace\n");
-- err = -EINVAL;
++ return -EINVAL;
}
- /* create root inode */
- inode = iget_locked(client->sb, rinfo.trace_in[rinfo.trace_nr-1].in->ino);
- if (inode == NULL) {
- err = -ENOMEM;
- goto out;
+ fs_root = client->sb->s_root;
+ if (fs_root == NULL) {
+ /* get the fs root inode. Note that this is not necessarily the root of
+ the mount */
+ err = ceph_get_inode(client->sb, le64_to_cpu(rinfo.trace_in[0].in->ino), &root_inode);
+ if (err < 0) {
- return err;
++ goto out;
+ }
++ alloc_fs = 1;
+
+ fs_root = d_alloc_root(root_inode);
+ if (fs_root == NULL) {
+ err = -ENOMEM;
+ /* fixme: also close? */
- goto out;
++ goto out2;
+ }
+ client->sb->s_root = fs_root;
+ } else {
+ root_inode = client->sb->s_root->d_inode;
+
+ BUG_ON (root_inode == NULL);
}
- if (inode->i_state & I_NEW)
- unlock_new_inode(inode);
- if ((err = ceph_fill_inode(inode, rinfo.trace_in[rinfo.trace_nr-1].in)) < 0)
+ if ((err = ceph_fill_trace(client->sb, &rinfo, &mnt_inode, pmnt_root)) < 0)
- goto out;
+ goto out2;
+ BUG_ON(*pmnt_root == NULL);
+
/* fill in cap */
frommds = rinfo.reply->hdr.src.name.num;
- cap = ceph_add_cap(mnt_inode, frommds,
- cap = ceph_add_cap(inode, session,
++ cap = ceph_add_cap(mnt_inode, session,
le32_to_cpu(rinfo.head->file_caps),
le32_to_cpu(rinfo.head->file_caps_seq));
if (IS_ERR(cap)) {
err = PTR_ERR(cap);
- goto out;
+ goto out2;
}
- ci = ceph_inode(inode);
- ci->i_nr_by_mode[FILE_MODE_PIN]++;
- root = d_alloc_root(inode);
- if (root == NULL) {
+ if (*pmnt_root == NULL) {
- goto out;
+ err = -ENOMEM;
- /* fixme: also close? */
+ goto out2;
}
- client->sb->s_root = root;
+
- dout(30, "open_root_inode success, root d is %p.\n", root);
+ ci = ceph_inode(mnt_inode);
+ ci->i_nr_by_mode[FILE_MODE_PIN]++;
+
- dout(30, "open_root_inode success.\n");
++ dout(30, "open_root_inode success, root d is %p.\n", fs_root);
return 0;
- out:
+ out2:
dout(30, "open_root_inode failure %d\n", err);
- iput(root_inode);
- iput(inode);
++ if (alloc_fs)
++ iput(root_inode);
+ iput(mnt_inode);
+ out:
+ ceph_mdsc_put_session(session);
return err;
}
#define DOUT_PREFIX "inode: "
#include "super.h"
- const struct inode_operations ceph_symlink_iops;
+ /*
+ * symlinks
+ */
+ static void * ceph_sym_follow_link(struct dentry *dentry, struct nameidata *nd)
+ {
+ struct ceph_inode_info *ci = ceph_inode(dentry->d_inode);
+ nd_set_link(nd, ci->i_symlink);
+ return NULL;
+ }
+
+ const struct inode_operations ceph_symlink_iops = {
+ .readlink = generic_readlink,
+ .follow_link = ceph_sym_follow_link,
+ };
+int ceph_get_inode(struct super_block *sb, unsigned long ino, struct inode **pinode)
+{
+ BUG_ON(pinode == NULL);
+
+ *pinode = NULL;
+
+ *pinode = iget_locked(sb, ino);
+
+ if (*pinode == NULL)
+ return -ENOMEM;
+ if ((*pinode)->i_state & I_NEW)
+ unlock_new_inode(*pinode);
+
+ return 0;
+}
+
+ /*
+ * populate an inode based on info from mds
+ */
int ceph_fill_inode(struct inode *inode, struct ceph_mds_reply_inode *info)
{
struct ceph_inode_info *ci = ceph_inode(inode);
/* inode.c */
+extern int ceph_get_inode(struct super_block *sb, unsigned long ino, struct inode **pinode);
extern int ceph_fill_inode(struct inode *inode, struct ceph_mds_reply_inode *info);
extern struct ceph_inode_cap *ceph_find_cap(struct inode *inode, int want);
- extern struct ceph_inode_cap *ceph_add_cap(struct inode *inode, int mds, u32 cap, u32 seq);
- extern int ceph_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat);
+ extern struct ceph_inode_cap *ceph_add_cap(struct inode *inode, struct ceph_mds_session *session, u32 cap, u32 seq);
+ extern void ceph_remove_caps(struct ceph_inode_info *ci);
extern int ceph_handle_cap_grant(struct inode *inode, struct ceph_mds_file_caps *grant, struct ceph_mds_session *session);
/* addr.c */