cf = kzalloc(sizeof(*cf), GFP_NOFS);
if (cf == NULL) {
- ceph_put_fmode(ceph_inode(inode), fmode); /* clean up */
+ ceph_put_fmode(ceph_inode(inode), fmode); /* clean up */
return -ENOMEM;
}
cf->mode = fmode;
inode->i_gid = parent->i_gid;
inode->i_op = &ceph_dir_iops;
inode->i_fop = &ceph_dir_fops;
+ ceph_inode(inode)->i_snap_caps = CEPH_CAP_PIN; /* so we can open */
return inode;
}
int __ceph_caps_issued(struct ceph_inode_info *ci, int *implemented)
{
- int have = 0;
+ int have = ci->i_snap_caps;
struct ceph_inode_cap *cap;
struct list_head *p;
u32 gen;
last++;
spin_unlock(&ci->vfs_inode.i_lock);
- if (last)
+ if (last && ci->i_vino.snap == CEPH_NOSNAP)
ceph_check_caps(ci, 0);
}
cap = le32_to_cpu(rinfo->head->file_caps);
capseq = le32_to_cpu(rinfo->head->file_caps_seq);
mseq = le32_to_cpu(rinfo->head->file_caps_mseq);
- err = ceph_add_cap(req->r_last_inode,
- req->r_session,
- req->r_fmode,
- cap, capseq, mseq,
- rinfo->snapblob,
- rinfo->snapblob_len);
- if (err)
- goto done;
+ if (ceph_vino(req->r_last_inode).snap == CEPH_NOSNAP) {
+ err = ceph_add_cap(req->r_last_inode,
+ req->r_session,
+ req->r_fmode,
+ cap, capseq, mseq,
+ rinfo->snapblob,
+ rinfo->snapblob_len);
+ if (err)
+ goto done;
+ } else {
+ struct ceph_inode_info *ci =
+ ceph_inode(req->r_last_inode);
+ spin_lock(&req->r_last_inode->i_lock);
+ ci->i_snap_caps |= cap;
+ __ceph_get_fmode(ci, req->r_fmode);
+ spin_unlock(&req->r_last_inode->i_lock);
+ }
}
/* readdir result? */
ci->i_wanted_max_size = 0;
ci->i_requested_max_size = 0;
+ ci->i_cap_exporting_mds = 0;
+ ci->i_cap_exporting_mseq = 0;
+ ci->i_cap_exporting_issued = 0;
+ ci->i_snap_caps = 0;
+
ci->i_rd_ref = ci->i_rdcache_ref = 0;
ci->i_wr_ref = 0;
atomic_set(&ci->i_wrbuffer_ref, 0);
int i_cap_exporting_mds;
unsigned i_cap_exporting_mseq;
unsigned i_cap_exporting_issued;
+ unsigned i_snap_caps;
int i_nr_by_mode[CEPH_FILE_MODE_NUM];
loff_t i_max_size; /* size authorized by mds */