ceph: do not release the global snaprealm until unmounting
[platform/kernel/linux-rpi.git] / fs / ceph / mds_client.c
index c30eefc..fa38c01 100644 (file)
@@ -555,6 +555,28 @@ bad:
        return -EIO;
 }
 
+static int parse_reply_info_getvxattr(void **p, void *end,
+                                     struct ceph_mds_reply_info_parsed *info,
+                                     u64 features)
+{
+       u32 value_len;
+
+       ceph_decode_skip_8(p, end, bad); /* skip current version: 1 */
+       ceph_decode_skip_8(p, end, bad); /* skip first version: 1 */
+       ceph_decode_skip_32(p, end, bad); /* skip payload length */
+
+       ceph_decode_32_safe(p, end, value_len, bad);
+
+       if (value_len == end - *p) {
+         info->xattr_info.xattr_value = *p;
+         info->xattr_info.xattr_value_len = value_len;
+         *p = end;
+         return value_len;
+       }
+bad:
+       return -EIO;
+}
+
 /*
  * parse extra results
  */
@@ -570,6 +592,8 @@ static int parse_reply_info_extra(void **p, void *end,
                return parse_reply_info_readdir(p, end, info, features);
        else if (op == CEPH_MDS_OP_CREATE)
                return parse_reply_info_create(p, end, info, features, s);
+       else if (op == CEPH_MDS_OP_GETVXATTR)
+               return parse_reply_info_getvxattr(p, end, info, features);
        else
                return -EIO;
 }
@@ -2178,7 +2202,8 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req,
        order = get_order(size * num_entries);
        while (order >= 0) {
                rinfo->dir_entries = (void*)__get_free_pages(GFP_KERNEL |
-                                                            __GFP_NOWARN,
+                                                            __GFP_NOWARN |
+                                                            __GFP_ZERO,
                                                             order);
                if (rinfo->dir_entries)
                        break;
@@ -2946,15 +2971,16 @@ int ceph_mdsc_submit_request(struct ceph_mds_client *mdsc, struct inode *dir,
        return err;
 }
 
-static int ceph_mdsc_wait_request(struct ceph_mds_client *mdsc,
-                                 struct ceph_mds_request *req)
+int ceph_mdsc_wait_request(struct ceph_mds_client *mdsc,
+                          struct ceph_mds_request *req,
+                          ceph_mds_request_wait_callback_t wait_func)
 {
        int err;
 
        /* wait */
        dout("do_request waiting\n");
-       if (!req->r_timeout && req->r_wait_for_completion) {
-               err = req->r_wait_for_completion(mdsc, req);
+       if (wait_func) {
+               err = wait_func(mdsc, req);
        } else {
                long timeleft = wait_for_completion_killable_timeout(
                                        &req->r_completion,
@@ -3011,7 +3037,7 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
        /* issue */
        err = ceph_mdsc_submit_request(mdsc, dir, req);
        if (!err)
-               err = ceph_mdsc_wait_request(mdsc, req);
+               err = ceph_mdsc_wait_request(mdsc, req, NULL);
        dout("do_request %p done, result %d\n", req, err);
        return err;
 }
@@ -3097,35 +3123,6 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
 
        result = le32_to_cpu(head->result);
 
-       /*
-        * Handle an ESTALE
-        * if we're not talking to the authority, send to them
-        * if the authority has changed while we weren't looking,
-        * send to new authority
-        * Otherwise we just have to return an ESTALE
-        */
-       if (result == -ESTALE) {
-               dout("got ESTALE on request %llu\n", req->r_tid);
-               req->r_resend_mds = -1;
-               if (req->r_direct_mode != USE_AUTH_MDS) {
-                       dout("not using auth, setting for that now\n");
-                       req->r_direct_mode = USE_AUTH_MDS;
-                       __do_request(mdsc, req);
-                       mutex_unlock(&mdsc->mutex);
-                       goto out;
-               } else  {
-                       int mds = __choose_mds(mdsc, req, NULL);
-                       if (mds >= 0 && mds != req->r_session->s_mds) {
-                               dout("but auth changed, so resending\n");
-                               __do_request(mdsc, req);
-                               mutex_unlock(&mdsc->mutex);
-                               goto out;
-                       }
-               }
-               dout("have to return ESTALE on request %llu\n", req->r_tid);
-       }
-
-
        if (head->safe) {
                set_bit(CEPH_MDS_R_GOT_SAFE, &req->r_req_flags);
                __unregister_request(mdsc, req);
@@ -4841,7 +4838,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
        mutex_unlock(&mdsc->mutex);
 
        ceph_cleanup_snapid_map(mdsc);
-       ceph_cleanup_empty_realms(mdsc);
+       ceph_cleanup_global_and_empty_realms(mdsc);
 
        cancel_work_sync(&mdsc->cap_reclaim_work);
        cancel_delayed_work_sync(&mdsc->delayed_work); /* cancel timer */