Merge tag 'ceph-for-4.9-rc1' of git://github.com/ceph/ceph-client
[cascardo/linux.git] / fs / ceph / mds_client.c
index f72d4ae..815acd1 100644 (file)
@@ -370,6 +370,7 @@ const char *ceph_session_state_name(int s)
        case CEPH_MDS_SESSION_CLOSING: return "closing";
        case CEPH_MDS_SESSION_RESTARTING: return "restarting";
        case CEPH_MDS_SESSION_RECONNECTING: return "reconnecting";
+       case CEPH_MDS_SESSION_REJECTED: return "rejected";
        default: return "???";
        }
 }
@@ -1150,8 +1151,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
                while (!list_empty(&ci->i_cap_flush_list)) {
                        cf = list_first_entry(&ci->i_cap_flush_list,
                                              struct ceph_cap_flush, i_list);
-                       list_del(&cf->i_list);
-                       list_add(&cf->i_list, &to_remove);
+                       list_move(&cf->i_list, &to_remove);
                }
 
                spin_lock(&mdsc->cap_dirty_lock);
@@ -1378,7 +1378,7 @@ static int request_close_session(struct ceph_mds_client *mdsc,
        if (!msg)
                return -ENOMEM;
        ceph_con_send(&session->s_con, msg);
-       return 0;
+       return 1;
 }
 
 /*
@@ -2131,6 +2131,10 @@ static int __do_request(struct ceph_mds_client *mdsc,
             ceph_session_state_name(session->s_state));
        if (session->s_state != CEPH_MDS_SESSION_OPEN &&
            session->s_state != CEPH_MDS_SESSION_HUNG) {
+               if (session->s_state == CEPH_MDS_SESSION_REJECTED) {
+                       err = -EACCES;
+                       goto out_session;
+               }
                if (session->s_state == CEPH_MDS_SESSION_NEW ||
                    session->s_state == CEPH_MDS_SESSION_CLOSING)
                        __open_session(mdsc, session);
@@ -2652,6 +2656,15 @@ static void handle_session(struct ceph_mds_session *session,
                wake_up_session_caps(session, 0);
                break;
 
+       case CEPH_SESSION_REJECT:
+               WARN_ON(session->s_state != CEPH_MDS_SESSION_OPENING);
+               pr_info("mds%d rejected session\n", session->s_mds);
+               session->s_state = CEPH_MDS_SESSION_REJECTED;
+               cleanup_session_requests(mdsc, session);
+               remove_session_caps(session);
+               wake = 2; /* for good measure */
+               break;
+
        default:
                pr_err("mdsc_handle_session bad op %d mds%d\n", op, mds);
                WARN_ON(1);
@@ -3557,11 +3570,11 @@ void ceph_mdsc_sync(struct ceph_mds_client *mdsc)
 /*
  * true if all sessions are closed, or we force unmount
  */
-static bool done_closing_sessions(struct ceph_mds_client *mdsc)
+static bool done_closing_sessions(struct ceph_mds_client *mdsc, int skipped)
 {
        if (ACCESS_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_SHUTDOWN)
                return true;
-       return atomic_read(&mdsc->num_sessions) == 0;
+       return atomic_read(&mdsc->num_sessions) <= skipped;
 }
 
 /*
@@ -3572,6 +3585,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
        struct ceph_options *opts = mdsc->fsc->client->options;
        struct ceph_mds_session *session;
        int i;
+       int skipped = 0;
 
        dout("close_sessions\n");
 
@@ -3583,7 +3597,8 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
                        continue;
                mutex_unlock(&mdsc->mutex);
                mutex_lock(&session->s_mutex);
-               __close_session(mdsc, session);
+               if (__close_session(mdsc, session) <= 0)
+                       skipped++;
                mutex_unlock(&session->s_mutex);
                ceph_put_mds_session(session);
                mutex_lock(&mdsc->mutex);
@@ -3591,7 +3606,8 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
        mutex_unlock(&mdsc->mutex);
 
        dout("waiting for sessions to close\n");
-       wait_event_timeout(mdsc->session_close_wq, done_closing_sessions(mdsc),
+       wait_event_timeout(mdsc->session_close_wq,
+                          done_closing_sessions(mdsc, skipped),
                           ceph_timeout_jiffies(opts->mount_timeout));
 
        /* tear down remaining sessions */