of: address: Follow DMA parent for "dma-coherent"
[linux-2.6-microblaze.git] / fs / ceph / super.c
index 377fafc..edfd643 100644 (file)
@@ -143,6 +143,7 @@ enum {
        Opt_snapdirname,
        Opt_mds_namespace,
        Opt_fscache_uniq,
+       Opt_recover_session,
        Opt_last_string,
        /* string args above */
        Opt_dirstat,
@@ -184,6 +185,7 @@ static match_table_t fsopt_tokens = {
        /* int args above */
        {Opt_snapdirname, "snapdirname=%s"},
        {Opt_mds_namespace, "mds_namespace=%s"},
+       {Opt_recover_session, "recover_session=%s"},
        {Opt_fscache_uniq, "fsc=%s"},
        /* string args above */
        {Opt_dirstat, "dirstat"},
@@ -254,6 +256,17 @@ static int parse_fsopt_token(char *c, void *private)
                if (!fsopt->mds_namespace)
                        return -ENOMEM;
                break;
+       case Opt_recover_session:
+               if (!strncmp(argstr[0].from, "no",
+                            argstr[0].to - argstr[0].from)) {
+                       fsopt->flags &= ~CEPH_MOUNT_OPT_CLEANRECOVER;
+               } else if (!strncmp(argstr[0].from, "clean",
+                                   argstr[0].to - argstr[0].from)) {
+                       fsopt->flags |= CEPH_MOUNT_OPT_CLEANRECOVER;
+               } else {
+                       return -EINVAL;
+               }
+               break;
        case Opt_fscache_uniq:
                kfree(fsopt->fscache_uniq);
                fsopt->fscache_uniq = kstrndup(argstr[0].from,
@@ -576,6 +589,10 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
 
        if (fsopt->mds_namespace)
                seq_show_option(m, "mds_namespace", fsopt->mds_namespace);
+
+       if (fsopt->flags & CEPH_MOUNT_OPT_CLEANRECOVER)
+               seq_show_option(m, "recover_session", "clean");
+
        if (fsopt->wsize != CEPH_MAX_WRITE_SIZE)
                seq_printf(m, ",wsize=%d", fsopt->wsize);
        if (fsopt->rsize != CEPH_MAX_READ_SIZE)
@@ -664,6 +681,7 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
 
        fsc->sb = NULL;
        fsc->mount_state = CEPH_MOUNT_MOUNTING;
+       fsc->filp_gen = 1;
 
        atomic_long_set(&fsc->writeback_count, 0);
 
@@ -713,6 +731,7 @@ static void destroy_fs_client(struct ceph_fs_client *fsc)
 {
        dout("destroy_fs_client %p\n", fsc);
 
+       ceph_mdsc_destroy(fsc);
        destroy_workqueue(fsc->inode_wq);
        destroy_workqueue(fsc->cap_wq);
 
@@ -829,7 +848,7 @@ static void ceph_umount_begin(struct super_block *sb)
        fsc->mount_state = CEPH_MOUNT_SHUTDOWN;
        ceph_osdc_abort_requests(&fsc->client->osdc, -EIO);
        ceph_mdsc_force_umount(fsc->mdsc);
-       return;
+       fsc->filp_gen++; // invalidate open files
 }
 
 static int ceph_remount(struct super_block *sb, int *flags, char *data)
@@ -1089,7 +1108,6 @@ static struct dentry *ceph_mount(struct file_system_type *fs_type,
        }
 
        if (ceph_sb_to_client(sb) != fsc) {
-               ceph_mdsc_destroy(fsc);
                destroy_fs_client(fsc);
                fsc = ceph_sb_to_client(sb);
                dout("get_sb got existing client %p\n", fsc);
@@ -1115,7 +1133,6 @@ out_splat:
        goto out_final;
 
 out:
-       ceph_mdsc_destroy(fsc);
        destroy_fs_client(fsc);
 out_final:
        dout("ceph_mount fail %ld\n", PTR_ERR(res));
@@ -1139,8 +1156,6 @@ static void ceph_kill_sb(struct super_block *s)
 
        ceph_fscache_unregister_fs(fsc);
 
-       ceph_mdsc_destroy(fsc);
-
        destroy_fs_client(fsc);
        free_anon_bdev(dev);
 }
@@ -1154,6 +1169,33 @@ static struct file_system_type ceph_fs_type = {
 };
 MODULE_ALIAS_FS("ceph");
 
+int ceph_force_reconnect(struct super_block *sb)
+{
+       struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
+       int err = 0;
+
+       ceph_umount_begin(sb);
+
+       /* Make sure all page caches get invalidated.
+        * see remove_session_caps_cb() */
+       flush_workqueue(fsc->inode_wq);
+
+       /* In case that we were blacklisted. This also reset
+        * all mon/osd connections */
+       ceph_reset_client_addr(fsc->client);
+
+       ceph_osdc_clear_abort_err(&fsc->client->osdc);
+
+       fsc->blacklisted = false;
+       fsc->mount_state = CEPH_MOUNT_MOUNTED;
+
+       if (sb->s_root) {
+               err = __ceph_do_getattr(d_inode(sb->s_root), NULL,
+                                       CEPH_STAT_CAP_INODE, true);
+       }
+       return err;
+}
+
 static int __init init_ceph(void)
 {
        int ret = init_caches();