ceph: simplify calling of ceph_get_fmode()
Originally, calling ceph_get_fmode() for open files is by thread that handles request reply. There is a small window between updating caps and and waking the request initiator. We need to prevent ceph_check_caps() from releasing wanted caps in the window. Previous patches made fill_inode() call __ceph_touch_fmode() for open file requests. This prevented ceph_check_caps() from releasing wanted caps for 'caps_wanted_delay_min' seconds, enough for request initiator to get woken up and call ceph_get_fmode(). This allows us to now call ceph_get_fmode() in ceph_open() instead. Signed-off-by: "Yan, Zheng" <zyan@redhat.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
a0d93e327f
commit
135e671e54
|
@ -608,7 +608,7 @@ static void __check_cap_issue(struct ceph_inode_info *ci, struct ceph_cap *cap,
|
||||||
*/
|
*/
|
||||||
void ceph_add_cap(struct inode *inode,
|
void ceph_add_cap(struct inode *inode,
|
||||||
struct ceph_mds_session *session, u64 cap_id,
|
struct ceph_mds_session *session, u64 cap_id,
|
||||||
int fmode, unsigned issued, unsigned wanted,
|
unsigned issued, unsigned wanted,
|
||||||
unsigned seq, unsigned mseq, u64 realmino, int flags,
|
unsigned seq, unsigned mseq, u64 realmino, int flags,
|
||||||
struct ceph_cap **new_cap)
|
struct ceph_cap **new_cap)
|
||||||
{
|
{
|
||||||
|
@ -624,13 +624,6 @@ void ceph_add_cap(struct inode *inode,
|
||||||
dout("add_cap %p mds%d cap %llx %s seq %d\n", inode,
|
dout("add_cap %p mds%d cap %llx %s seq %d\n", inode,
|
||||||
session->s_mds, cap_id, ceph_cap_string(issued), seq);
|
session->s_mds, cap_id, ceph_cap_string(issued), seq);
|
||||||
|
|
||||||
/*
|
|
||||||
* If we are opening the file, include file mode wanted bits
|
|
||||||
* in wanted.
|
|
||||||
*/
|
|
||||||
if (fmode >= 0)
|
|
||||||
wanted |= ceph_caps_for_mode(fmode);
|
|
||||||
|
|
||||||
spin_lock(&session->s_gen_ttl_lock);
|
spin_lock(&session->s_gen_ttl_lock);
|
||||||
gen = session->s_cap_gen;
|
gen = session->s_cap_gen;
|
||||||
spin_unlock(&session->s_gen_ttl_lock);
|
spin_unlock(&session->s_gen_ttl_lock);
|
||||||
|
@ -755,9 +748,6 @@ void ceph_add_cap(struct inode *inode,
|
||||||
cap->issue_seq = seq;
|
cap->issue_seq = seq;
|
||||||
cap->mseq = mseq;
|
cap->mseq = mseq;
|
||||||
cap->cap_gen = gen;
|
cap->cap_gen = gen;
|
||||||
|
|
||||||
if (fmode >= 0)
|
|
||||||
__ceph_get_fmode(ci, fmode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3707,7 +3697,7 @@ retry:
|
||||||
/* add placeholder for the export tagert */
|
/* add placeholder for the export tagert */
|
||||||
int flag = (cap == ci->i_auth_cap) ? CEPH_CAP_FLAG_AUTH : 0;
|
int flag = (cap == ci->i_auth_cap) ? CEPH_CAP_FLAG_AUTH : 0;
|
||||||
tcap = new_cap;
|
tcap = new_cap;
|
||||||
ceph_add_cap(inode, tsession, t_cap_id, -1, issued, 0,
|
ceph_add_cap(inode, tsession, t_cap_id, issued, 0,
|
||||||
t_seq - 1, t_mseq, (u64)-1, flag, &new_cap);
|
t_seq - 1, t_mseq, (u64)-1, flag, &new_cap);
|
||||||
|
|
||||||
if (!list_empty(&ci->i_cap_flush_list) &&
|
if (!list_empty(&ci->i_cap_flush_list) &&
|
||||||
|
@ -3812,7 +3802,7 @@ retry:
|
||||||
__ceph_caps_issued(ci, &issued);
|
__ceph_caps_issued(ci, &issued);
|
||||||
issued |= __ceph_caps_dirty(ci);
|
issued |= __ceph_caps_dirty(ci);
|
||||||
|
|
||||||
ceph_add_cap(inode, session, cap_id, -1, caps, wanted, seq, mseq,
|
ceph_add_cap(inode, session, cap_id, caps, wanted, seq, mseq,
|
||||||
realmino, CEPH_CAP_FLAG_AUTH, &new_cap);
|
realmino, CEPH_CAP_FLAG_AUTH, &new_cap);
|
||||||
|
|
||||||
ocap = peer >= 0 ? __get_cap_for_mds(ci, peer) : NULL;
|
ocap = peer >= 0 ? __get_cap_for_mds(ci, peer) : NULL;
|
||||||
|
@ -4165,16 +4155,6 @@ void ceph_get_fmode(struct ceph_inode_info *ci, int fmode, int count)
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __ceph_get_fmode(struct ceph_inode_info *ci, int fmode)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int bits = (fmode << 1) | 1;
|
|
||||||
for (i = 0; i < CEPH_FILE_MODE_BITS; i++) {
|
|
||||||
if (bits & (1 << i))
|
|
||||||
ci->i_nr_by_mode[i]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Drop open file reference. If we were the last open file,
|
* Drop open file reference. If we were the last open file,
|
||||||
* we may need to release capabilities to the MDS (or schedule
|
* we may need to release capabilities to the MDS (or schedule
|
||||||
|
|
|
@ -212,10 +212,8 @@ static int ceph_init_file_info(struct inode *inode, struct file *file,
|
||||||
if (isdir) {
|
if (isdir) {
|
||||||
struct ceph_dir_file_info *dfi =
|
struct ceph_dir_file_info *dfi =
|
||||||
kmem_cache_zalloc(ceph_dir_file_cachep, GFP_KERNEL);
|
kmem_cache_zalloc(ceph_dir_file_cachep, GFP_KERNEL);
|
||||||
if (!dfi) {
|
if (!dfi)
|
||||||
ceph_put_fmode(ci, fmode, 1); /* clean up */
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
file->private_data = dfi;
|
file->private_data = dfi;
|
||||||
fi = &dfi->file_info;
|
fi = &dfi->file_info;
|
||||||
|
@ -223,15 +221,15 @@ static int ceph_init_file_info(struct inode *inode, struct file *file,
|
||||||
dfi->readdir_cache_idx = -1;
|
dfi->readdir_cache_idx = -1;
|
||||||
} else {
|
} else {
|
||||||
fi = kmem_cache_zalloc(ceph_file_cachep, GFP_KERNEL);
|
fi = kmem_cache_zalloc(ceph_file_cachep, GFP_KERNEL);
|
||||||
if (!fi) {
|
if (!fi)
|
||||||
ceph_put_fmode(ci, fmode, 1); /* clean up */
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
file->private_data = fi;
|
file->private_data = fi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ceph_get_fmode(ci, fmode, 1);
|
||||||
fi->fmode = fmode;
|
fi->fmode = fmode;
|
||||||
|
|
||||||
spin_lock_init(&fi->rw_contexts_lock);
|
spin_lock_init(&fi->rw_contexts_lock);
|
||||||
INIT_LIST_HEAD(&fi->rw_contexts);
|
INIT_LIST_HEAD(&fi->rw_contexts);
|
||||||
fi->meta_err = errseq_sample(&ci->i_meta_err);
|
fi->meta_err = errseq_sample(&ci->i_meta_err);
|
||||||
|
@ -263,7 +261,6 @@ static int ceph_init_file(struct inode *inode, struct file *file, int fmode)
|
||||||
case S_IFLNK:
|
case S_IFLNK:
|
||||||
dout("init_file %p %p 0%o (symlink)\n", inode, file,
|
dout("init_file %p %p 0%o (symlink)\n", inode, file,
|
||||||
inode->i_mode);
|
inode->i_mode);
|
||||||
ceph_put_fmode(ceph_inode(inode), fmode, 1); /* clean up */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -273,7 +270,6 @@ static int ceph_init_file(struct inode *inode, struct file *file, int fmode)
|
||||||
* we need to drop the open ref now, since we don't
|
* we need to drop the open ref now, since we don't
|
||||||
* have .release set to ceph_release.
|
* have .release set to ceph_release.
|
||||||
*/
|
*/
|
||||||
ceph_put_fmode(ceph_inode(inode), fmode, 1); /* clean up */
|
|
||||||
BUG_ON(inode->i_fop->release == ceph_release);
|
BUG_ON(inode->i_fop->release == ceph_release);
|
||||||
|
|
||||||
/* call the proper open fop */
|
/* call the proper open fop */
|
||||||
|
@ -327,7 +323,6 @@ int ceph_renew_caps(struct inode *inode, int fmode)
|
||||||
req->r_inode = inode;
|
req->r_inode = inode;
|
||||||
ihold(inode);
|
ihold(inode);
|
||||||
req->r_num_caps = 1;
|
req->r_num_caps = 1;
|
||||||
req->r_fmode = -1;
|
|
||||||
|
|
||||||
err = ceph_mdsc_do_request(mdsc, NULL, req);
|
err = ceph_mdsc_do_request(mdsc, NULL, req);
|
||||||
ceph_mdsc_put_request(req);
|
ceph_mdsc_put_request(req);
|
||||||
|
@ -373,9 +368,6 @@ int ceph_open(struct inode *inode, struct file *file)
|
||||||
|
|
||||||
/* trivially open snapdir */
|
/* trivially open snapdir */
|
||||||
if (ceph_snap(inode) == CEPH_SNAPDIR) {
|
if (ceph_snap(inode) == CEPH_SNAPDIR) {
|
||||||
spin_lock(&ci->i_ceph_lock);
|
|
||||||
__ceph_get_fmode(ci, fmode);
|
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
|
||||||
return ceph_init_file(inode, file, fmode);
|
return ceph_init_file(inode, file, fmode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,7 +385,7 @@ int ceph_open(struct inode *inode, struct file *file)
|
||||||
dout("open %p fmode %d want %s issued %s using existing\n",
|
dout("open %p fmode %d want %s issued %s using existing\n",
|
||||||
inode, fmode, ceph_cap_string(wanted),
|
inode, fmode, ceph_cap_string(wanted),
|
||||||
ceph_cap_string(issued));
|
ceph_cap_string(issued));
|
||||||
__ceph_get_fmode(ci, fmode);
|
__ceph_touch_fmode(ci, mdsc, fmode);
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
|
|
||||||
/* adjust wanted? */
|
/* adjust wanted? */
|
||||||
|
@ -405,7 +397,6 @@ int ceph_open(struct inode *inode, struct file *file)
|
||||||
return ceph_init_file(inode, file, fmode);
|
return ceph_init_file(inode, file, fmode);
|
||||||
} else if (ceph_snap(inode) != CEPH_NOSNAP &&
|
} else if (ceph_snap(inode) != CEPH_NOSNAP &&
|
||||||
(ci->i_snap_caps & wanted) == wanted) {
|
(ci->i_snap_caps & wanted) == wanted) {
|
||||||
__ceph_get_fmode(ci, fmode);
|
|
||||||
__ceph_touch_fmode(ci, mdsc, fmode);
|
__ceph_touch_fmode(ci, mdsc, fmode);
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
return ceph_init_file(inode, file, fmode);
|
return ceph_init_file(inode, file, fmode);
|
||||||
|
@ -782,8 +773,6 @@ retry:
|
||||||
err = finish_open(file, dentry, ceph_open);
|
err = finish_open(file, dentry, ceph_open);
|
||||||
}
|
}
|
||||||
out_req:
|
out_req:
|
||||||
if (!req->r_err && req->r_target_inode)
|
|
||||||
ceph_put_fmode(ceph_inode(req->r_target_inode), req->r_fmode, 1);
|
|
||||||
ceph_mdsc_put_request(req);
|
ceph_mdsc_put_request(req);
|
||||||
out_ctx:
|
out_ctx:
|
||||||
ceph_release_acl_sec_ctx(&as_ctx);
|
ceph_release_acl_sec_ctx(&as_ctx);
|
||||||
|
|
|
@ -970,7 +970,7 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
|
||||||
if (ceph_snap(inode) == CEPH_NOSNAP) {
|
if (ceph_snap(inode) == CEPH_NOSNAP) {
|
||||||
ceph_add_cap(inode, session,
|
ceph_add_cap(inode, session,
|
||||||
le64_to_cpu(info->cap.cap_id),
|
le64_to_cpu(info->cap.cap_id),
|
||||||
cap_fmode, info_caps,
|
info_caps,
|
||||||
le32_to_cpu(info->cap.wanted),
|
le32_to_cpu(info->cap.wanted),
|
||||||
le32_to_cpu(info->cap.seq),
|
le32_to_cpu(info->cap.seq),
|
||||||
le32_to_cpu(info->cap.mseq),
|
le32_to_cpu(info->cap.mseq),
|
||||||
|
@ -995,13 +995,7 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
|
||||||
dout(" %p got snap_caps %s\n", inode,
|
dout(" %p got snap_caps %s\n", inode,
|
||||||
ceph_cap_string(info_caps));
|
ceph_cap_string(info_caps));
|
||||||
ci->i_snap_caps |= info_caps;
|
ci->i_snap_caps |= info_caps;
|
||||||
if (cap_fmode >= 0)
|
|
||||||
__ceph_get_fmode(ci, cap_fmode);
|
|
||||||
}
|
}
|
||||||
} else if (cap_fmode >= 0) {
|
|
||||||
pr_warn("mds issued no caps on %llx.%llx\n",
|
|
||||||
ceph_vinop(inode));
|
|
||||||
__ceph_get_fmode(ci, cap_fmode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iinfo->inline_version > 0 &&
|
if (iinfo->inline_version > 0 &&
|
||||||
|
|
|
@ -1050,7 +1050,7 @@ extern struct ceph_cap *ceph_get_cap(struct ceph_mds_client *mdsc,
|
||||||
struct ceph_cap_reservation *ctx);
|
struct ceph_cap_reservation *ctx);
|
||||||
extern void ceph_add_cap(struct inode *inode,
|
extern void ceph_add_cap(struct inode *inode,
|
||||||
struct ceph_mds_session *session, u64 cap_id,
|
struct ceph_mds_session *session, u64 cap_id,
|
||||||
int fmode, unsigned issued, unsigned wanted,
|
unsigned issued, unsigned wanted,
|
||||||
unsigned cap, unsigned seq, u64 realmino, int flags,
|
unsigned cap, unsigned seq, u64 realmino, int flags,
|
||||||
struct ceph_cap **new_cap);
|
struct ceph_cap **new_cap);
|
||||||
extern void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release);
|
extern void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release);
|
||||||
|
@ -1096,7 +1096,6 @@ extern int ceph_try_get_caps(struct inode *inode,
|
||||||
int need, int want, bool nonblock, int *got);
|
int need, int want, bool nonblock, int *got);
|
||||||
|
|
||||||
/* for counting open files by mode */
|
/* for counting open files by mode */
|
||||||
extern void __ceph_get_fmode(struct ceph_inode_info *ci, int mode);
|
|
||||||
extern void ceph_get_fmode(struct ceph_inode_info *ci, int mode, int count);
|
extern void ceph_get_fmode(struct ceph_inode_info *ci, int mode, int count);
|
||||||
extern void ceph_put_fmode(struct ceph_inode_info *ci, int mode, int count);
|
extern void ceph_put_fmode(struct ceph_inode_info *ci, int mode, int count);
|
||||||
extern void __ceph_touch_fmode(struct ceph_inode_info *ci,
|
extern void __ceph_touch_fmode(struct ceph_inode_info *ci,
|
||||||
|
|
Loading…
Reference in New Issue