Commit 525d15e8 authored by Yan, Zheng's avatar Yan, Zheng Committed by Ilya Dryomov

ceph: check inode type for CEPH_CAP_FILE_{CACHE,RD,REXTEND,LAZYIO}

These bits will have new meaning for directory inodes.
Signed-off-by: default avatar"Yan, Zheng" <zyan@redhat.com>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent f85122af
...@@ -573,7 +573,8 @@ static void __check_cap_issue(struct ceph_inode_info *ci, struct ceph_cap *cap, ...@@ -573,7 +573,8 @@ static void __check_cap_issue(struct ceph_inode_info *ci, struct ceph_cap *cap,
* Each time we receive FILE_CACHE anew, we increment * Each time we receive FILE_CACHE anew, we increment
* i_rdcache_gen. * i_rdcache_gen.
*/ */
if ((issued & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) && if (S_ISREG(ci->vfs_inode.i_mode) &&
(issued & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) &&
(had & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0) { (had & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0) {
ci->i_rdcache_gen++; ci->i_rdcache_gen++;
} }
...@@ -958,7 +959,7 @@ int __ceph_caps_used(struct ceph_inode_info *ci) ...@@ -958,7 +959,7 @@ int __ceph_caps_used(struct ceph_inode_info *ci)
if (ci->i_rd_ref) if (ci->i_rd_ref)
used |= CEPH_CAP_FILE_RD; used |= CEPH_CAP_FILE_RD;
if (ci->i_rdcache_ref || if (ci->i_rdcache_ref ||
(!S_ISDIR(ci->vfs_inode.i_mode) && /* ignore readdir cache */ (S_ISREG(ci->vfs_inode.i_mode) &&
ci->vfs_inode.i_data.nrpages)) ci->vfs_inode.i_data.nrpages))
used |= CEPH_CAP_FILE_CACHE; used |= CEPH_CAP_FILE_CACHE;
if (ci->i_wr_ref) if (ci->i_wr_ref)
...@@ -985,6 +986,20 @@ int __ceph_caps_file_wanted(struct ceph_inode_info *ci) ...@@ -985,6 +986,20 @@ int __ceph_caps_file_wanted(struct ceph_inode_info *ci)
return ceph_caps_for_mode(bits >> 1); return ceph_caps_for_mode(bits >> 1);
} }
/*
* wanted, by virtue of open file modes AND cap refs (buffered/cached data)
*/
int __ceph_caps_wanted(struct ceph_inode_info *ci)
{
int w = __ceph_caps_file_wanted(ci) | __ceph_caps_used(ci);
if (!S_ISDIR(ci->vfs_inode.i_mode)) {
/* we want EXCL if dirty data */
if (w & CEPH_CAP_FILE_BUFFER)
w |= CEPH_CAP_FILE_EXCL;
}
return w;
}
/* /*
* Return caps we have registered with the MDS(s) as 'wanted'. * Return caps we have registered with the MDS(s) as 'wanted'.
*/ */
...@@ -1903,7 +1918,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, ...@@ -1903,7 +1918,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
* If we fail, it's because pages are locked.... try again later. * If we fail, it's because pages are locked.... try again later.
*/ */
if ((!no_delay || mdsc->stopping) && if ((!no_delay || mdsc->stopping) &&
!S_ISDIR(inode->i_mode) && /* ignore readdir cache */ S_ISREG(inode->i_mode) &&
!(ci->i_wb_ref || ci->i_wrbuffer_ref) && /* no dirty pages... */ !(ci->i_wb_ref || ci->i_wrbuffer_ref) && /* no dirty pages... */
inode->i_data.nrpages && /* have cached pages */ inode->i_data.nrpages && /* have cached pages */
(revoking & (CEPH_CAP_FILE_CACHE| (revoking & (CEPH_CAP_FILE_CACHE|
...@@ -2635,7 +2650,8 @@ static int try_get_cap_refs(struct inode *inode, int need, int want, ...@@ -2635,7 +2650,8 @@ static int try_get_cap_refs(struct inode *inode, int need, int want,
snap_rwsem_locked = true; snap_rwsem_locked = true;
} }
*got = need | (have & want); *got = need | (have & want);
if ((need & CEPH_CAP_FILE_RD) && if (S_ISREG(inode->i_mode) &&
(need & CEPH_CAP_FILE_RD) &&
!(*got & CEPH_CAP_FILE_CACHE)) !(*got & CEPH_CAP_FILE_CACHE))
ceph_disable_fscache_readpage(ci); ceph_disable_fscache_readpage(ci);
__take_cap_refs(ci, *got, true); __take_cap_refs(ci, *got, true);
...@@ -2643,7 +2659,8 @@ static int try_get_cap_refs(struct inode *inode, int need, int want, ...@@ -2643,7 +2659,8 @@ static int try_get_cap_refs(struct inode *inode, int need, int want,
} }
} else { } else {
int session_readonly = false; int session_readonly = false;
if ((need & CEPH_CAP_FILE_WR) && ci->i_auth_cap) { if (ci->i_auth_cap &&
(need & (CEPH_CAP_FILE_WR | CEPH_CAP_FILE_EXCL))) {
struct ceph_mds_session *s = ci->i_auth_cap->session; struct ceph_mds_session *s = ci->i_auth_cap->session;
spin_lock(&s->s_cap_lock); spin_lock(&s->s_cap_lock);
session_readonly = s->s_readonly; session_readonly = s->s_readonly;
...@@ -2817,7 +2834,8 @@ int ceph_get_caps(struct file *filp, int need, int want, ...@@ -2817,7 +2834,8 @@ int ceph_get_caps(struct file *filp, int need, int want,
return ret; return ret;
} }
if (ci->i_inline_version != CEPH_INLINE_NONE && if (S_ISREG(ci->vfs_inode.i_mode) &&
ci->i_inline_version != CEPH_INLINE_NONE &&
(_got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) && (_got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) &&
i_size_read(inode) > 0) { i_size_read(inode) > 0) {
struct page *page = struct page *page =
...@@ -2850,7 +2868,8 @@ int ceph_get_caps(struct file *filp, int need, int want, ...@@ -2850,7 +2868,8 @@ int ceph_get_caps(struct file *filp, int need, int want,
break; break;
} }
if ((_got & CEPH_CAP_FILE_RD) && (_got & CEPH_CAP_FILE_CACHE)) if (S_ISREG(ci->vfs_inode.i_mode) &&
(_got & CEPH_CAP_FILE_RD) && (_got & CEPH_CAP_FILE_CACHE))
ceph_fscache_revalidate_cookie(ci); ceph_fscache_revalidate_cookie(ci);
*got = _got; *got = _got;
...@@ -3140,7 +3159,7 @@ static void handle_cap_grant(struct inode *inode, ...@@ -3140,7 +3159,7 @@ static void handle_cap_grant(struct inode *inode,
* try to invalidate (once). (If there are dirty buffers, we * try to invalidate (once). (If there are dirty buffers, we
* will invalidate _after_ writeback.) * will invalidate _after_ writeback.)
*/ */
if (!S_ISDIR(inode->i_mode) && /* don't invalidate readdir cache */ if (S_ISREG(inode->i_mode) && /* don't invalidate readdir cache */
((cap->issued & ~newcaps) & CEPH_CAP_FILE_CACHE) && ((cap->issued & ~newcaps) & CEPH_CAP_FILE_CACHE) &&
(newcaps & CEPH_CAP_FILE_LAZYIO) == 0 && (newcaps & CEPH_CAP_FILE_LAZYIO) == 0 &&
!(ci->i_wrbuffer_ref || ci->i_wb_ref)) { !(ci->i_wrbuffer_ref || ci->i_wb_ref)) {
...@@ -3304,11 +3323,12 @@ static void handle_cap_grant(struct inode *inode, ...@@ -3304,11 +3323,12 @@ static void handle_cap_grant(struct inode *inode,
ceph_cap_string(cap->issued), ceph_cap_string(cap->issued),
ceph_cap_string(newcaps), ceph_cap_string(newcaps),
ceph_cap_string(revoking)); ceph_cap_string(revoking));
if (revoking & used & CEPH_CAP_FILE_BUFFER) if (S_ISREG(inode->i_mode) &&
(revoking & used & CEPH_CAP_FILE_BUFFER))
writeback = true; /* initiate writeback; will delay ack */ writeback = true; /* initiate writeback; will delay ack */
else if (revoking == CEPH_CAP_FILE_CACHE && else if (queue_invalidate &&
(newcaps & CEPH_CAP_FILE_LAZYIO) == 0 && revoking == CEPH_CAP_FILE_CACHE &&
queue_invalidate) (newcaps & CEPH_CAP_FILE_LAZYIO) == 0)
; /* do nothing yet, invalidation will be queued */ ; /* do nothing yet, invalidation will be queued */
else if (cap == ci->i_auth_cap) else if (cap == ci->i_auth_cap)
check_caps = 1; /* check auth cap only */ check_caps = 1; /* check auth cap only */
......
...@@ -1776,7 +1776,8 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg) ...@@ -1776,7 +1776,8 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg)
} }
/* The inode has cached pages, but it's no longer used. /* The inode has cached pages, but it's no longer used.
* we can safely drop it */ * we can safely drop it */
if (wanted == 0 && used == CEPH_CAP_FILE_CACHE && if (S_ISREG(inode->i_mode) &&
wanted == 0 && used == CEPH_CAP_FILE_CACHE &&
!(oissued & CEPH_CAP_FILE_CACHE)) { !(oissued & CEPH_CAP_FILE_CACHE)) {
used = 0; used = 0;
oissued = 0; oissued = 0;
......
...@@ -675,17 +675,7 @@ extern int ceph_caps_revoking(struct ceph_inode_info *ci, int mask); ...@@ -675,17 +675,7 @@ extern int ceph_caps_revoking(struct ceph_inode_info *ci, int mask);
extern int __ceph_caps_used(struct ceph_inode_info *ci); extern int __ceph_caps_used(struct ceph_inode_info *ci);
extern int __ceph_caps_file_wanted(struct ceph_inode_info *ci); extern int __ceph_caps_file_wanted(struct ceph_inode_info *ci);
extern int __ceph_caps_wanted(struct ceph_inode_info *ci);
/*
* wanted, by virtue of open file modes AND cap refs (buffered/cached data)
*/
static inline int __ceph_caps_wanted(struct ceph_inode_info *ci)
{
int w = __ceph_caps_file_wanted(ci) | __ceph_caps_used(ci);
if (w & CEPH_CAP_FILE_BUFFER)
w |= CEPH_CAP_FILE_EXCL; /* we want EXCL if dirty data */
return w;
}
/* what the mds thinks we want */ /* what the mds thinks we want */
extern int __ceph_caps_mds_wanted(struct ceph_inode_info *ci, bool check); extern int __ceph_caps_mds_wanted(struct ceph_inode_info *ci, bool check);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment