diff options
| -rw-r--r-- | fs/ceph/caps.c | 75 | ||||
| -rw-r--r-- | fs/ceph/inode.c | 60 | ||||
| -rw-r--r-- | fs/ceph/mds_client.c | 129 | ||||
| -rw-r--r-- | fs/ceph/mds_client.h | 16 | ||||
| -rw-r--r-- | fs/ceph/mdsmap.c | 1 | ||||
| -rw-r--r-- | net/ceph/messenger.c | 55 |
6 files changed, 174 insertions, 162 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index f3496db4bb3e..94c026bba2c2 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
| @@ -657,6 +657,9 @@ void ceph_add_cap(struct inode *inode, | |||
| 657 | session->s_nr_caps++; | 657 | session->s_nr_caps++; |
| 658 | spin_unlock(&session->s_cap_lock); | 658 | spin_unlock(&session->s_cap_lock); |
| 659 | } else { | 659 | } else { |
| 660 | if (cap->cap_gen < session->s_cap_gen) | ||
| 661 | cap->issued = cap->implemented = CEPH_CAP_PIN; | ||
| 662 | |||
| 660 | /* | 663 | /* |
| 661 | * auth mds of the inode changed. we received the cap export | 664 | * auth mds of the inode changed. we received the cap export |
| 662 | * message, but still haven't received the cap import message. | 665 | * message, but still haven't received the cap import message. |
| @@ -1855,14 +1858,17 @@ retry_locked: | |||
| 1855 | retain |= CEPH_CAP_ANY; /* be greedy */ | 1858 | retain |= CEPH_CAP_ANY; /* be greedy */ |
| 1856 | } else if (S_ISDIR(inode->i_mode) && | 1859 | } else if (S_ISDIR(inode->i_mode) && |
| 1857 | (issued & CEPH_CAP_FILE_SHARED) && | 1860 | (issued & CEPH_CAP_FILE_SHARED) && |
| 1858 | __ceph_dir_is_complete(ci)) { | 1861 | __ceph_dir_is_complete(ci)) { |
| 1859 | /* | 1862 | /* |
| 1860 | * If a directory is complete, we want to keep | 1863 | * If a directory is complete, we want to keep |
| 1861 | * the exclusive cap. So that MDS does not end up | 1864 | * the exclusive cap. So that MDS does not end up |
| 1862 | * revoking the shared cap on every create/unlink | 1865 | * revoking the shared cap on every create/unlink |
| 1863 | * operation. | 1866 | * operation. |
| 1864 | */ | 1867 | */ |
| 1865 | want = CEPH_CAP_ANY_SHARED | CEPH_CAP_FILE_EXCL; | 1868 | if (IS_RDONLY(inode)) |
| 1869 | want = CEPH_CAP_ANY_SHARED; | ||
| 1870 | else | ||
| 1871 | want = CEPH_CAP_ANY_SHARED | CEPH_CAP_FILE_EXCL; | ||
| 1866 | retain |= want; | 1872 | retain |= want; |
| 1867 | } else { | 1873 | } else { |
| 1868 | 1874 | ||
| @@ -1970,8 +1976,7 @@ retry_locked: | |||
| 1970 | goto ack; | 1976 | goto ack; |
| 1971 | 1977 | ||
| 1972 | /* things we might delay */ | 1978 | /* things we might delay */ |
| 1973 | if ((cap->issued & ~retain) == 0 && | 1979 | if ((cap->issued & ~retain) == 0) |
| 1974 | cap->mds_wanted == want) | ||
| 1975 | continue; /* nope, all good */ | 1980 | continue; /* nope, all good */ |
| 1976 | 1981 | ||
| 1977 | if (no_delay) | 1982 | if (no_delay) |
| @@ -3048,7 +3053,8 @@ static void handle_cap_grant(struct inode *inode, | |||
| 3048 | int used, wanted, dirty; | 3053 | int used, wanted, dirty; |
| 3049 | u64 size = le64_to_cpu(grant->size); | 3054 | u64 size = le64_to_cpu(grant->size); |
| 3050 | u64 max_size = le64_to_cpu(grant->max_size); | 3055 | u64 max_size = le64_to_cpu(grant->max_size); |
| 3051 | int check_caps = 0; | 3056 | unsigned char check_caps = 0; |
| 3057 | bool was_stale = cap->cap_gen < session->s_cap_gen; | ||
| 3052 | bool wake = false; | 3058 | bool wake = false; |
| 3053 | bool writeback = false; | 3059 | bool writeback = false; |
| 3054 | bool queue_trunc = false; | 3060 | bool queue_trunc = false; |
| @@ -3063,21 +3069,6 @@ static void handle_cap_grant(struct inode *inode, | |||
| 3063 | 3069 | ||
| 3064 | 3070 | ||
| 3065 | /* | 3071 | /* |
| 3066 | * auth mds of the inode changed. we received the cap export message, | ||
| 3067 | * but still haven't received the cap import message. handle_cap_export | ||
| 3068 | * updated the new auth MDS' cap. | ||
| 3069 | * | ||
| 3070 | * "ceph_seq_cmp(seq, cap->seq) <= 0" means we are processing a message | ||
| 3071 | * that was sent before the cap import message. So don't remove caps. | ||
| 3072 | */ | ||
| 3073 | if (ceph_seq_cmp(seq, cap->seq) <= 0) { | ||
| 3074 | WARN_ON(cap != ci->i_auth_cap); | ||
| 3075 | WARN_ON(cap->cap_id != le64_to_cpu(grant->cap_id)); | ||
| 3076 | seq = cap->seq; | ||
| 3077 | newcaps |= cap->issued; | ||
| 3078 | } | ||
| 3079 | |||
| 3080 | /* | ||
| 3081 | * If CACHE is being revoked, and we have no dirty buffers, | 3072 | * If CACHE is being revoked, and we have no dirty buffers, |
| 3082 | * try to invalidate (once). (If there are dirty buffers, we | 3073 | * try to invalidate (once). (If there are dirty buffers, we |
| 3083 | * will invalidate _after_ writeback.) | 3074 | * will invalidate _after_ writeback.) |
| @@ -3096,6 +3087,24 @@ static void handle_cap_grant(struct inode *inode, | |||
| 3096 | } | 3087 | } |
| 3097 | } | 3088 | } |
| 3098 | 3089 | ||
| 3090 | if (was_stale) | ||
| 3091 | cap->issued = cap->implemented = CEPH_CAP_PIN; | ||
| 3092 | |||
| 3093 | /* | ||
| 3094 | * auth mds of the inode changed. we received the cap export message, | ||
| 3095 | * but still haven't received the cap import message. handle_cap_export | ||
| 3096 | * updated the new auth MDS' cap. | ||
| 3097 | * | ||
| 3098 | * "ceph_seq_cmp(seq, cap->seq) <= 0" means we are processing a message | ||
| 3099 | * that was sent before the cap import message. So don't remove caps. | ||
| 3100 | */ | ||
| 3101 | if (ceph_seq_cmp(seq, cap->seq) <= 0) { | ||
| 3102 | WARN_ON(cap != ci->i_auth_cap); | ||
| 3103 | WARN_ON(cap->cap_id != le64_to_cpu(grant->cap_id)); | ||
| 3104 | seq = cap->seq; | ||
| 3105 | newcaps |= cap->issued; | ||
| 3106 | } | ||
| 3107 | |||
| 3099 | /* side effects now are allowed */ | 3108 | /* side effects now are allowed */ |
| 3100 | cap->cap_gen = session->s_cap_gen; | 3109 | cap->cap_gen = session->s_cap_gen; |
| 3101 | cap->seq = seq; | 3110 | cap->seq = seq; |
| @@ -3200,13 +3209,20 @@ static void handle_cap_grant(struct inode *inode, | |||
| 3200 | ceph_cap_string(wanted), | 3209 | ceph_cap_string(wanted), |
| 3201 | ceph_cap_string(used), | 3210 | ceph_cap_string(used), |
| 3202 | ceph_cap_string(dirty)); | 3211 | ceph_cap_string(dirty)); |
| 3203 | if (wanted != le32_to_cpu(grant->wanted)) { | 3212 | |
| 3204 | dout("mds wanted %s -> %s\n", | 3213 | if ((was_stale || le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) && |
| 3205 | ceph_cap_string(le32_to_cpu(grant->wanted)), | 3214 | (wanted & ~(cap->mds_wanted | newcaps))) { |
| 3206 | ceph_cap_string(wanted)); | 3215 | /* |
| 3207 | /* imported cap may not have correct mds_wanted */ | 3216 | * If mds is importing cap, prior cap messages that update |
| 3208 | if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) | 3217 | * 'wanted' may get dropped by mds (migrate seq mismatch). |
| 3209 | check_caps = 1; | 3218 | * |
| 3219 | * We don't send cap message to update 'wanted' if what we | ||
| 3220 | * want are already issued. If mds revokes caps, cap message | ||
| 3221 | * that releases caps also tells mds what we want. But if | ||
| 3222 | * caps got revoked by mds forcedly (session stale). We may | ||
| 3223 | * haven't told mds what we want. | ||
| 3224 | */ | ||
| 3225 | check_caps = 1; | ||
| 3210 | } | 3226 | } |
| 3211 | 3227 | ||
| 3212 | /* revocation, grant, or no-op? */ | 3228 | /* revocation, grant, or no-op? */ |
| @@ -3539,9 +3555,9 @@ retry: | |||
| 3539 | goto out_unlock; | 3555 | goto out_unlock; |
| 3540 | 3556 | ||
| 3541 | if (target < 0) { | 3557 | if (target < 0) { |
| 3542 | __ceph_remove_cap(cap, false); | 3558 | if (cap->mds_wanted | cap->issued) |
| 3543 | if (!ci->i_auth_cap) | ||
| 3544 | ci->i_ceph_flags |= CEPH_I_CAP_DROPPED; | 3559 | ci->i_ceph_flags |= CEPH_I_CAP_DROPPED; |
| 3560 | __ceph_remove_cap(cap, false); | ||
| 3545 | goto out_unlock; | 3561 | goto out_unlock; |
| 3546 | } | 3562 | } |
| 3547 | 3563 | ||
| @@ -3569,7 +3585,6 @@ retry: | |||
| 3569 | tcap->cap_id = t_cap_id; | 3585 | tcap->cap_id = t_cap_id; |
| 3570 | tcap->seq = t_seq - 1; | 3586 | tcap->seq = t_seq - 1; |
| 3571 | tcap->issue_seq = t_seq - 1; | 3587 | tcap->issue_seq = t_seq - 1; |
| 3572 | tcap->mseq = t_mseq; | ||
| 3573 | tcap->issued |= issued; | 3588 | tcap->issued |= issued; |
| 3574 | tcap->implemented |= issued; | 3589 | tcap->implemented |= issued; |
| 3575 | if (cap == ci->i_auth_cap) | 3590 | if (cap == ci->i_auth_cap) |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 79dd5e6ed755..9d1f34d46627 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
| @@ -1098,8 +1098,9 @@ out_unlock: | |||
| 1098 | * splice a dentry to an inode. | 1098 | * splice a dentry to an inode. |
| 1099 | * caller must hold directory i_mutex for this to be safe. | 1099 | * caller must hold directory i_mutex for this to be safe. |
| 1100 | */ | 1100 | */ |
| 1101 | static struct dentry *splice_dentry(struct dentry *dn, struct inode *in) | 1101 | static int splice_dentry(struct dentry **pdn, struct inode *in) |
| 1102 | { | 1102 | { |
| 1103 | struct dentry *dn = *pdn; | ||
| 1103 | struct dentry *realdn; | 1104 | struct dentry *realdn; |
| 1104 | 1105 | ||
| 1105 | BUG_ON(d_inode(dn)); | 1106 | BUG_ON(d_inode(dn)); |
| @@ -1132,28 +1133,23 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in) | |||
| 1132 | if (IS_ERR(realdn)) { | 1133 | if (IS_ERR(realdn)) { |
| 1133 | pr_err("splice_dentry error %ld %p inode %p ino %llx.%llx\n", | 1134 | pr_err("splice_dentry error %ld %p inode %p ino %llx.%llx\n", |
| 1134 | PTR_ERR(realdn), dn, in, ceph_vinop(in)); | 1135 | PTR_ERR(realdn), dn, in, ceph_vinop(in)); |
| 1135 | dn = realdn; | 1136 | return PTR_ERR(realdn); |
| 1136 | /* | 1137 | } |
| 1137 | * Caller should release 'dn' in the case of error. | 1138 | |
| 1138 | * If 'req->r_dentry' is passed to this function, | 1139 | if (realdn) { |
| 1139 | * caller should leave 'req->r_dentry' untouched. | ||
| 1140 | */ | ||
| 1141 | goto out; | ||
| 1142 | } else if (realdn) { | ||
| 1143 | dout("dn %p (%d) spliced with %p (%d) " | 1140 | dout("dn %p (%d) spliced with %p (%d) " |
| 1144 | "inode %p ino %llx.%llx\n", | 1141 | "inode %p ino %llx.%llx\n", |
| 1145 | dn, d_count(dn), | 1142 | dn, d_count(dn), |
| 1146 | realdn, d_count(realdn), | 1143 | realdn, d_count(realdn), |
| 1147 | d_inode(realdn), ceph_vinop(d_inode(realdn))); | 1144 | d_inode(realdn), ceph_vinop(d_inode(realdn))); |
| 1148 | |||
