ceph: handle SESSION_FORCE_RO message
authorYan, Zheng <zyan@redhat.com>
Mon, 5 Jan 2015 03:04:04 +0000 (11:04 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Thu, 19 Feb 2015 10:31:37 +0000 (13:31 +0300)
mark session as readonly and wake up all cap waiters.

Signed-off-by: Yan, Zheng <zyan@redhat.com>
fs/ceph/caps.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
include/linux/ceph/ceph_fs.h

index b93c631c6c87d550e1f9674aaec5d41906d12143..d0618e8412fd1e7ba96866bc8c148c7166224d48 100644 (file)
@@ -2143,6 +2143,21 @@ again:
                        ret = 1;
                }
        } else {
+               int session_readonly = false;
+               if ((need & CEPH_CAP_FILE_WR) && ci->i_auth_cap) {
+                       struct ceph_mds_session *s = ci->i_auth_cap->session;
+                       spin_lock(&s->s_cap_lock);
+                       session_readonly = s->s_readonly;
+                       spin_unlock(&s->s_cap_lock);
+               }
+               if (session_readonly) {
+                       dout("get_cap_refs %p needed %s but mds%d readonly\n",
+                            inode, ceph_cap_string(need), ci->i_auth_cap->mds);
+                       *err = -EROFS;
+                       ret = 1;
+                       goto out_unlock;
+               }
+
                dout("get_cap_refs %p have %s needed %s\n", inode,
                     ceph_cap_string(have), ceph_cap_string(need));
        }
index d2171f4a698072d34bad5f68be85c3ae4aa19914..c6c33b411a2f7f7679af20038bcecf5cad5ed4a6 100644 (file)
@@ -2580,6 +2580,14 @@ static void handle_session(struct ceph_mds_session *session,
                send_flushmsg_ack(mdsc, session, seq);
                break;
 
+       case CEPH_SESSION_FORCE_RO:
+               dout("force_session_readonly %p\n", session);
+               spin_lock(&session->s_cap_lock);
+               session->s_readonly = true;
+               spin_unlock(&session->s_cap_lock);
+               wake_up_session_caps(session, 0);
+               break;
+
        default:
                pr_err("mdsc_handle_session bad op %d mds%d\n", op, mds);
                WARN_ON(1);
@@ -2791,6 +2799,8 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
        spin_unlock(&session->s_gen_ttl_lock);
 
        spin_lock(&session->s_cap_lock);
+       /* don't know if session is readonly */
+       session->s_readonly = 0;
        /*
         * notify __ceph_remove_cap() that we are composing cap reconnect.
         * If a cap get released before being added to the cap reconnect,
index e2817d00f7d9f51922b2a1c04b20de97e410edfe..a87b92f500bbc11809e24c678261883cde8bca37 100644 (file)
@@ -137,6 +137,7 @@ struct ceph_mds_session {
        int               s_nr_caps, s_trim_caps;
        int               s_num_cap_releases;
        int               s_cap_reconnect;
+       int               s_readonly;
        struct list_head  s_cap_releases; /* waiting cap_release messages */
        struct list_head  s_cap_releases_done; /* ready to send */
        struct ceph_cap  *s_cap_iterator;
index 69e2c9e2305bdd11882c402b9ad63100fa9e539b..31eb03d0c7662dddd02fb126a24bc4198ffc65d8 100644 (file)
@@ -271,6 +271,7 @@ enum {
        CEPH_SESSION_RECALL_STATE,
        CEPH_SESSION_FLUSHMSG,
        CEPH_SESSION_FLUSHMSG_ACK,
+       CEPH_SESSION_FORCE_RO,
 };
 
 extern const char *ceph_session_op_name(int op);