]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: fix multiple mount points from same client; serialize mount attempts
authorSage Weil <sage@newdream.net>
Thu, 24 Jul 2008 23:18:35 +0000 (16:18 -0700)
committerSage Weil <sage@newdream.net>
Thu, 24 Jul 2008 23:18:35 +0000 (16:18 -0700)
src/kernel/super.c
src/kernel/super.h

index 09a25aa479c1ad3df301aa35e797bfb43f2d6d78..d624a8a67f9b26dc075ade6634233077f7e60a2c 100644 (file)
@@ -566,65 +566,66 @@ static int parse_mount_args(int flags, char *options, const char *dev_name,
  */
 struct ceph_client *ceph_create_client(void)
 {
-       struct ceph_client *cl;
+       struct ceph_client *client;
        int err = -ENOMEM;
 
-       cl = kzalloc(sizeof(*cl), GFP_KERNEL);
-       if (cl == NULL)
+       client = kzalloc(sizeof(*client), GFP_KERNEL);
+       if (client == NULL)
                return ERR_PTR(-ENOMEM);
 
-       init_waitqueue_head(&cl->mount_wq);
-       spin_lock_init(&cl->sb_lock);
+       mutex_init(&client->mount_mutex);
+
+       init_waitqueue_head(&client->mount_wq);
+       spin_lock_init(&client->sb_lock);
 
-       cl->sb = 0;
-       cl->mount_state = CEPH_MOUNT_MOUNTING;
-       cl->whoami = -1;
+       client->sb = 0;
+       client->mount_state = CEPH_MOUNT_MOUNTING;
+       client->whoami = -1;
 
-       cl->msgr = 0;
+       client->msgr = 0;
 
-       cl->wb_wq = create_workqueue("ceph-writeback");
-       if (cl->wb_wq == 0)
+       client->wb_wq = create_workqueue("ceph-writeback");
+       if (client->wb_wq == 0)
                goto fail;
-       cl->trunc_wq = create_workqueue("ceph-trunc");
-       if (cl->trunc_wq == 0)
+       client->trunc_wq = create_workqueue("ceph-trunc");
+       if (client->trunc_wq == 0)
                goto fail;
 
        /* subsystems */
-       err = ceph_monc_init(&cl->monc, cl);
+       err = ceph_monc_init(&client->monc, client);
        if (err < 0)
                return ERR_PTR(err);
-       ceph_mdsc_init(&cl->mdsc, cl);
-       ceph_osdc_init(&cl->osdc, cl);
+       ceph_mdsc_init(&client->mdsc, client);
+       ceph_osdc_init(&client->osdc, client);
 
-       return cl;
+       return client;
 
 fail:
-       /* fixme: use type->init() eventually */
        return ERR_PTR(-ENOMEM);
 }
 
-void ceph_destroy_client(struct ceph_client *cl)
+void ceph_destroy_client(struct ceph_client *client)
 {
-       dout(10, "destroy_client %p\n", cl);
+       dout(10, "destroy_client %p\n", client);
 
        /* unmount */
        /* ... */
 
-       ceph_monc_stop(&cl->monc);
-       ceph_osdc_stop(&cl->osdc);
+       ceph_monc_stop(&client->monc);
+       ceph_osdc_stop(&client->osdc);
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
-       if (cl->client_kobj)
-               kobject_put(cl->client_kobj);
+       if (client->client_kobj)
+               kobject_put(client->client_kobj);
 #endif
-       if (cl->wb_wq)
-               destroy_workqueue(cl->wb_wq);
-       if (cl->trunc_wq)
-               destroy_workqueue(cl->trunc_wq);
-       if (cl->msgr)
-               ceph_messenger_destroy(cl->msgr);
-       kfree(cl);
-       dout(10, "destroy_client %p done\n", cl);
+       if (client->wb_wq)
+               destroy_workqueue(client->wb_wq);
+       if (client->trunc_wq)
+               destroy_workqueue(client->trunc_wq);
+       if (client->msgr)
+               ceph_messenger_destroy(client->msgr);
+       kfree(client);
+       dout(10, "destroy_client %p done\n", client);
 }
 
 static int have_all_maps(struct ceph_client *client)
@@ -678,27 +679,37 @@ int ceph_mount(struct ceph_client *client, struct vfsmount *mnt)
        char r;
 
        dout(10, "mount start\n");
+       mutex_lock(&client->mount_mutex);
 
        /* messenger */
-       if (client->mount_args.flags & CEPH_MOUNT_MYIP)
-               myaddr = &client->mount_args.my_addr;
-       client->msgr = ceph_messenger_create(myaddr);
-       if (IS_ERR(client->msgr)) {
-               err = PTR_ERR(client->msgr);
-               client->msgr = 0;
-               return err;
+       if (client->msgr == NULL) {
+               if (client->mount_args.flags & CEPH_MOUNT_MYIP)
+                       myaddr = &client->mount_args.my_addr;
+               client->msgr = ceph_messenger_create(myaddr);
+               if (IS_ERR(client->msgr)) {
+                       err = PTR_ERR(client->msgr);
+                       client->msgr = 0;
+                       goto out;
+               }
+               client->msgr->parent = client;
+               client->msgr->dispatch = ceph_dispatch;
+               client->msgr->prepare_pages = ceph_osdc_prepare_pages;
+               client->msgr->peer_reset = ceph_peer_reset;
        }
-       client->msgr->parent = client;
-       client->msgr->dispatch = ceph_dispatch;
-       client->msgr->prepare_pages = ceph_osdc_prepare_pages;
-       client->msgr->peer_reset = ceph_peer_reset;
-
-       while (1) {
+       
+       while (!have_all_maps(client)) {
+               err = -EIO;
+               if (attempts == 0)
+                       goto out;
+               dout(10, "mount sending mount request, %d attempts left\n",
+                    attempts--);
                get_random_bytes(&r, 1);
                which = r % client->mount_args.num_mon;
                mount_msg = ceph_msg_new(CEPH_MSG_CLIENT_MOUNT, 0, 0, 0, 0);
-               if (IS_ERR(mount_msg))
-                       return PTR_ERR(mount_msg);
+               if (IS_ERR(mount_msg)) {
+                       err = PTR_ERR(mount_msg);
+                       goto out;
+               }
                mount_msg->hdr.dst.name.type =
                        cpu_to_le32(CEPH_ENTITY_TYPE_MON);
                mount_msg->hdr.dst.name.num = cpu_to_le32(which);
@@ -715,24 +726,24 @@ int ceph_mount(struct ceph_client *client, struct vfsmount *mnt)
                                                       6*HZ);
                dout(10, "mount wait got %d\n", err);
                if (err == -EINTR)
-                       return err;
-               if (have_all_maps(client))
-                       break;  /* success */
-               dout(10, "mount still waiting for mount, attempts=%d\n",
-                    attempts);
-               if (--attempts == 0)
-                       return -EIO;
+                       goto out;
        }
 
        dout(30, "mount opening base mountpoint\n");
        root = open_root_dentry(client);
-       if (IS_ERR(root))
-               return PTR_ERR(root);
+       if (IS_ERR(root)) {
+               err = PTR_ERR(root);
+               goto out;
+       }
        mnt->mnt_root = root;
        mnt->mnt_sb = client->sb;
        client->mount_state = CEPH_MOUNT_MOUNTED;
        dout(10, "mount success\n");
-       return 0;
+       err = 0;
+
+out:
+       mutex_unlock(&client->mount_mutex);
+       return err;
 }
 
 
index 5dea66ef1498ab950eb74efe9e757a5235e0530a..f08f3589f9c62801294f402d70fb466c33970639 100644 (file)
@@ -127,6 +127,7 @@ extern struct kobject *ceph_kobj;
 struct ceph_client {
        __u32 whoami;                   /* my client number */
 
+       struct mutex mount_mutex;       /* serialize mount attempts */
        struct ceph_mount_args mount_args;
        struct ceph_fsid fsid;