return ret;
}
- if (S_ISREG(ci->vfs_inode.i_mode) &&
+ if (!S_ISDIR(ci->vfs_inode.i_mode) &&
ci->i_inline_version != CEPH_INLINE_NONE &&
(_got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) &&
i_size_read(inode) > 0) {
if (had & CEPH_CAP_FILE_RD)
if (--ci->i_rd_ref == 0)
last++;
- if (had & CEPH_CAP_FILE_CACHE)
- if (--ci->i_rdcache_ref == 0)
+ if (had & CEPH_CAP_FILE_CACHE) {
+ if (--ci->i_rdcache_ref == 0) {
last++;
+ /* Zero out layout if we lost CREATE caps */
+ if (S_ISDIR(inode->i_mode) &&
+ !(__ceph_caps_issued(ci, NULL) & CEPH_CAP_DIR_CREATE)) {
+ ceph_put_string(rcu_dereference_raw(ci->i_layout.pool_ns));
+ memset(&ci->i_layout, 0, sizeof(ci->i_layout));
+ }
+ }
+ }
if (had & CEPH_CAP_FILE_EXCL)
if (--ci->i_fx_ref == 0)
last++;
ci->i_subdirs = extra_info->nsubdirs;
}
- if (newcaps & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR)) {
+ if (!S_ISDIR(inode->i_mode) &&
+ (newcaps & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR))) {
/* file layout may have changed */
s64 old_pool = ci->i_layout.pool_id;
struct ceph_string *old_ns;
ceph_cap_string(cap->issued),
ceph_cap_string(newcaps),
ceph_cap_string(revoking));
+
+ if (S_ISDIR(inode->i_mode) &&
+ (revoking & CEPH_CAP_DIR_CREATE) && !ci->i_rdcache_ref) {
+ ceph_put_string(rcu_dereference_raw(ci->i_layout.pool_ns));
+ memset(&ci->i_layout, 0, sizeof(ci->i_layout));
+ }
+
if (S_ISREG(inode->i_mode) &&
(revoking & used & CEPH_CAP_FILE_BUFFER))
writeback = true; /* initiate writeback; will delay ack */
return err;
}
+/* Clone the layout from a synchronous create, if the dir now has Dc caps */
+static void
+copy_file_layout(struct inode *dst, struct inode *src)
+{
+ struct ceph_inode_info *cdst = ceph_inode(dst);
+ struct ceph_inode_info *csrc = ceph_inode(src);
+
+ spin_lock(&cdst->i_ceph_lock);
+ if ((__ceph_caps_issued(cdst, NULL) & CEPH_CAP_DIR_CREATE) &&
+ !ceph_file_layout_is_valid(&cdst->i_layout)) {
+ memcpy(&cdst->i_layout, &csrc->i_layout,
+ sizeof(cdst->i_layout));
+ rcu_assign_pointer(cdst->i_layout.pool_ns,
+ ceph_try_get_string(csrc->i_layout.pool_ns));
+ cdst->i_max_size = csrc->i_max_size;
+ cdst->i_truncate_size = csrc->i_truncate_size;
+ }
+ spin_unlock(&cdst->i_ceph_lock);
+}
/*
* Do a lookup + open with a single request. If we get a non-existent
} else {
dout("atomic_open finish_open on dn %p\n", dn);
if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
- ceph_init_inode_acls(d_inode(dentry), &as_ctx);
+ struct inode *newino = d_inode(dentry);
+
+ copy_file_layout(dir, newino);
+ ceph_init_inode_acls(newino, &as_ctx);
file->f_mode |= FMODE_CREATED;
}
err = finish_open(file, dentry, ceph_open);
ci->i_subdirs = le64_to_cpu(info->subdirs);
}
- if (new_version ||
- (new_issued & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR))) {
+ if (!S_ISDIR(inode->i_mode) && (new_version ||
+ (new_issued & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR)))) {
s64 old_pool = ci->i_layout.pool_id;
struct ceph_string *old_ns;