- apply_truncate needs to truncate page cache, or something?
kernel client
-- take file_mode refs on inode safely/atomically on open
- fix session close seq interaction with mds (sessions don't currently close all the way)
- file_data_version stuff!
- deal with CAP_RDCACHE properly: invalidate cache pages?
return 0;
}
-
-const struct file_operations ceph_dir_fops = {
- .read = generic_read_dir,
- .readdir = ceph_dir_readdir,
- .open = ceph_open,
- .release = ceph_release,
-};
-
-
int ceph_do_lookup(struct super_block *sb, struct dentry *dentry, int mask)
{
struct ceph_client *client = ceph_sb_to_client(sb);
}
}
+const struct file_operations ceph_dir_fops = {
+ .read = generic_read_dir,
+ .readdir = ceph_dir_readdir,
+ .open = ceph_open,
+ .release = ceph_release,
+};
const struct inode_operations ceph_dir_iops = {
.lookup = ceph_dir_lookup,
/*
* if err==0, caller is responsible for a put_session on *psession
*/
-struct ceph_mds_request *
+static struct ceph_mds_request *
prepare_open_request(struct super_block *sb, struct dentry *dentry,
int flags, int create_mode)
{
req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_OPEN, pathbase, path,
0, 0);
req->r_expects_cap = 1;
+ req->r_fmode = ceph_file_mode(flags);
kfree(path);
if (!IS_ERR(req)) {
rhead = req->r_request->front.iov_base;
return req;
}
-
-static int ceph_init_file(struct inode *inode, struct file *file, int flags)
+/*
+ * initialize private struct file data.
+ * if we fail, clean up by dropping fmode reference on the ceph_inode
+ */
+static int ceph_init_file(struct inode *inode, struct file *file, int fmode)
{
- struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_file_info *cf;
- int fmode = ceph_file_mode(flags);
cf = kzalloc(sizeof(*cf), GFP_KERNEL);
- if (cf == NULL)
+ if (cf == NULL) {
+ ceph_put_fmode(ceph_inode(inode), fmode); /* clean up */
return -ENOMEM;
+ }
file->private_data = cf;
-
cf->mode = fmode;
- ceph_get_mode(ci, fmode);
return 0;
}
if ((__ceph_caps_issued(ci) & wantcaps) == wantcaps) {
dout(10, "open fmode %d caps %d using existing on %p\n",
fmode, wantcaps, inode);
+ __ceph_get_fmode(ci, fmode);
spin_unlock(&inode->i_lock);
- err = ceph_init_file(inode, file, flags);
- BUG_ON(err); /* fixme */
- return 0;
+ return ceph_init_file(inode, file, fmode);
}
spin_unlock(&inode->i_lock);
dout(10, "open mode %d, don't have caps %d\n", fmode, wantcaps);
if (IS_ERR(req))
return PTR_ERR(req);
err = ceph_mdsc_do_request(mdsc, req);
- if (err == 0)
- err = ceph_init_file(inode, file, flags);
+ if (err == 0)
+ err = ceph_init_file(inode, file, req->r_fmode);
ceph_mdsc_put_request(req);
dout(5, "ceph_open result=%d on %llx\n", err, ceph_ino(inode));
return err;
req->r_last_dentry = dentry; /* use this dentry in fill_trace */
err = ceph_mdsc_do_request(mdsc, req);
if (err == 0)
- err = ceph_init_file(req->r_last_inode, file, flags);
+ err = ceph_init_file(req->r_last_inode, file, req->r_fmode);
else if (err == -ENOENT) {
ceph_init_dentry(dentry);
d_add(dentry, NULL);
* for now, store the open mode in ceph_file_info.
*/
- ceph_put_mode(ci, cf->mode);
+ ceph_put_fmode(ci, cf->mode);
if (cf->last_readdir)
ceph_mdsc_put_request(cf->last_readdir);
kfree(cf);
*/
struct ceph_inode_cap *ceph_add_cap(struct inode *inode,
struct ceph_mds_session *session,
+ int fmode,
u32 issued, u32 seq)
{
int mds = session->s_mds;
cap->issued |= issued;
cap->implemented |= issued;
cap->seq = seq;
+ __ceph_get_fmode(ci, fmode);
spin_unlock(&inode->i_lock);
if (is_new)
igrab(inode);
spin_unlock(&inode->i_lock);
}
-/*
- * called on struct file init and release, to safely track which
- * capabilities we want due to currently open files
- */
-void ceph_get_mode(struct ceph_inode_info *ci, int mode)
-{
- spin_lock(&ci->vfs_inode.i_lock);
- ci->i_nr_by_mode[mode]++;
- spin_unlock(&ci->vfs_inode.i_lock);
-}
-
-void ceph_put_mode(struct ceph_inode_info *ci, int mode)
+void ceph_put_fmode(struct ceph_inode_info *ci, int fmode)
{
int last = 0;
spin_lock(&ci->vfs_inode.i_lock);
- dout(20, "put_mode %p mode %d %d -> %d\n", &ci->vfs_inode, mode,
- ci->i_nr_by_mode[mode], ci->i_nr_by_mode[mode]-1);
- if (--ci->i_nr_by_mode[mode] == 0)
+ dout(20, "put_mode %p fmode %d %d -> %d\n", &ci->vfs_inode, fmode,
+ ci->i_nr_by_mode[fmode], ci->i_nr_by_mode[fmode]-1);
+ if (--ci->i_nr_by_mode[fmode] == 0)
last++;
spin_unlock(&ci->vfs_inode.i_lock);
req->r_last_dentry = 0;
req->r_old_dentry = 0;
req->r_expects_cap = 0;
+ req->r_fmode = 0;
req->r_cap = 0;
req->r_session = 0;
req->r_num_mds = 0;
capseq = le32_to_cpu(rinfo->head->file_caps_seq);
req->r_cap = ceph_add_cap(req->r_last_inode,
req->r_session,
+ req->r_fmode,
cap, capseq);
if (IS_ERR(req->r_cap)) {
err = PTR_ERR(req->r_cap);
struct dentry *r_last_dentry;
struct dentry *r_old_dentry; /* for rename */
int r_expects_cap;
+ int r_fmode; /* if expecting cap */
unsigned long r_from_time;
struct ceph_inode_cap *r_cap;
struct ceph_mds_session *r_session;
return FILE_MODE_RDWR; /* not -EINVAL under Linux, strangely */
}
+static inline void __ceph_get_fmode(struct ceph_inode_info *ci, int mode)
+{
+ ci->i_nr_by_mode[mode]++;
+}
+extern void ceph_put_fmode(struct ceph_inode_info *ci, int mode);
+
static inline struct ceph_client *ceph_inode_to_client(struct inode *inode)
{
return (struct ceph_client *)inode->i_sb->s_fs_info;
extern struct ceph_inode_cap *ceph_add_cap(struct inode *inode,
struct ceph_mds_session *session,
+ int fmode,
u32 cap, u32 seq);
extern void ceph_remove_cap(struct ceph_inode_cap *cap);
extern void ceph_remove_all_caps(struct ceph_inode_info *ci);
extern void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr);
extern void ceph_cap_delayed_work(struct work_struct *work);
extern void ceph_check_caps(struct ceph_inode_info *ci, int was_last);
-extern void ceph_get_mode(struct ceph_inode_info *ci, int mode);
-extern void ceph_put_mode(struct ceph_inode_info *ci, int mode);
extern void ceph_inode_set_size(struct inode *inode, loff_t size);
extern void ceph_inode_writeback(struct work_struct *work);
done
# mds
-$CEPH_BIN/cmds $ARGS --debug_mds 20 --debug_ms 1
+$CEPH_BIN/cmds $ARGS --debug_mds 20 --debug_ms 20
echo "started. stop.sh to stop. see out/* (e.g. 'tail -f out/????') for debug output."