Revert "GFS2: Fix use-after-free bug on umount"
Steven Whitehouse [Fri, 19 Dec 2008 15:32:06 +0000 (15:32 +0000)]
This reverts commit 78802499912f1ba31ce83a94c55b5a980f250a43.

The original patch is causing problems in relation to order of
operations at umount in relation to jdata files. I need to fix
this a different way.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>

fs/gfs2/glock.c
fs/gfs2/glock.h
fs/gfs2/ops_fstype.c
fs/gfs2/ops_super.c
fs/gfs2/super.c
fs/gfs2/super.h

index 5eae62e..6e298b0 100644 (file)
@@ -1547,9 +1547,8 @@ static void clear_glock(struct gfs2_glock *gl)
  * Called when unmounting the filesystem.
  */
 
-void gfs2_gl_hash_clear(struct super_block *sb)
+void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
 {
-       struct gfs2_sbd *sdp = sb->s_fs_info;
        unsigned long t;
        unsigned int x;
        int cont;
index ce54f33..543ec7e 100644 (file)
@@ -130,7 +130,7 @@ void gfs2_lvb_unhold(struct gfs2_glock *gl);
 
 void gfs2_glock_cb(void *cb_data, unsigned int type, void *data);
 void gfs2_reclaim_glock(struct gfs2_sbd *sdp);
-void gfs2_gl_hash_clear(struct super_block *sb);
+void gfs2_gl_hash_clear(struct gfs2_sbd *sdp);
 void gfs2_glock_finish_truncate(struct gfs2_inode *ip);
 
 int __init gfs2_glock_init(void);
index 2e735be..4cae60f 100644 (file)
@@ -705,40 +705,6 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
        return error;
 }
 
-/**
- * gfs2_jindex_free - Clear all the journal index information
- * @sdp: The GFS2 superblock
- *
- */
-
-static void gfs2_jindex_free(struct gfs2_sbd *sdp)
-{
-       struct list_head list, *head;
-       struct gfs2_jdesc *jd;
-       struct gfs2_journal_extent *jext;
-
-       spin_lock(&sdp->sd_jindex_spin);
-       list_add(&list, &sdp->sd_jindex_list);
-       list_del_init(&sdp->sd_jindex_list);
-       sdp->sd_journals = 0;
-       spin_unlock(&sdp->sd_jindex_spin);
-
-       while (!list_empty(&list)) {
-               jd = list_entry(list.next, struct gfs2_jdesc, jd_list);
-               head = &jd->extent_list;
-               while (!list_empty(head)) {
-                       jext = list_entry(head->next,
-                                         struct gfs2_journal_extent,
-                                         extent_list);
-                       list_del(&jext->extent_list);
-                       kfree(jext);
-               }
-               list_del(&jd->jd_list);
-               iput(jd->jd_inode);
-               kfree(jd);
-       }
-}
-
 static int init_journal(struct gfs2_sbd *sdp, int undo)
 {
        struct inode *master = sdp->sd_master_dir->d_inode;
@@ -1237,7 +1203,7 @@ fail_sb:
 fail_locking:
        init_locking(sdp, &mount_gh, UNDO);
 fail_lm:
-       gfs2_gl_hash_clear(sb);
+       gfs2_gl_hash_clear(sdp);
        gfs2_lm_unmount(sdp);
        while (invalidate_inodes(sb))
                yield();
@@ -1297,61 +1263,17 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags,
 static void gfs2_kill_sb(struct super_block *sb)
 {
        struct gfs2_sbd *sdp = sb->s_fs_info;
-
-       if (sdp == NULL) {
-               kill_block_super(sb);
-               return;
-       }
-       gfs2_meta_syncfs(sdp);
-       dput(sdp->sd_root_dir);
-       dput(sdp->sd_master_dir);
-       sdp->sd_root_dir = NULL;
-       sdp->sd_master_dir = NULL;
-
-       /*  Unfreeze the filesystem, if we need to  */
-       mutex_lock(&sdp->sd_freeze_lock);
-       if (sdp->sd_freeze_count)
-               gfs2_glock_dq_uninit(&sdp->sd_freeze_gh);
-       mutex_unlock(&sdp->sd_freeze_lock);
-
-       kthread_stop(sdp->sd_quotad_process);
-       kthread_stop(sdp->sd_logd_process);
-       kthread_stop(sdp->sd_recoverd_process);
-
-       if (!(sb->s_flags & MS_RDONLY)) {
-               int error = gfs2_make_fs_ro(sdp);
-               if (error)
-                       gfs2_io_error(sdp);
-       }
-
-       /* At this point, we're through modifying the disk */
-       gfs2_jindex_free(sdp);
-       gfs2_clear_rgrpd(sdp);
-       iput(sdp->sd_jindex);
-       iput(sdp->sd_inum_inode);
-       iput(sdp->sd_statfs_inode);
-       iput(sdp->sd_rindex);
-       iput(sdp->sd_quota_inode);
-
-       gfs2_glock_put(sdp->sd_rename_gl);
-       gfs2_glock_put(sdp->sd_trans_gl);
-
-       if (!sdp->sd_args.ar_spectator) {
-               gfs2_glock_dq_uninit(&sdp->sd_journal_gh);
-               gfs2_glock_dq_uninit(&sdp->sd_jinode_gh);
-               gfs2_glock_dq_uninit(&sdp->sd_ir_gh);
-               gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
-               gfs2_glock_dq_uninit(&sdp->sd_qc_gh);
-               iput(sdp->sd_ir_inode);
-               iput(sdp->sd_sc_inode);
-               iput(sdp->sd_qc_inode);
+       if (sdp) {
+               gfs2_meta_syncfs(sdp);
+               dput(sdp->sd_root_dir);
+               dput(sdp->sd_master_dir);
+               sdp->sd_root_dir = NULL;
+               sdp->sd_master_dir = NULL;
        }
-       gfs2_glock_dq_uninit(&sdp->sd_live_gh);
+       shrink_dcache_sb(sb);
        kill_block_super(sb);
-       gfs2_lm_unmount(sdp);
-       gfs2_sys_fs_del(sdp);
-       gfs2_delete_debugfs_file(sdp);
-       kfree(sdp);
+       if (sdp)
+               gfs2_delete_debugfs_file(sdp);
 }
 
 struct file_system_type gfs2_fs_type = {
index bd08a0a..08837a7 100644 (file)
@@ -95,7 +95,7 @@ do_flush:
  * Returns: errno
  */
 
-int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
+static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
 {
        struct gfs2_holder t_gh;
        int error;
@@ -122,6 +122,70 @@ int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
 }
 
 /**
+ * gfs2_put_super - Unmount the filesystem
+ * @sb: The VFS superblock
+ *
+ */
+
+static void gfs2_put_super(struct super_block *sb)
+{
+       struct gfs2_sbd *sdp = sb->s_fs_info;
+       int error;
+
+       /*  Unfreeze the filesystem, if we need to  */
+
+       mutex_lock(&sdp->sd_freeze_lock);
+       if (sdp->sd_freeze_count)
+               gfs2_glock_dq_uninit(&sdp->sd_freeze_gh);
+       mutex_unlock(&sdp->sd_freeze_lock);
+
+       kthread_stop(sdp->sd_quotad_process);
+       kthread_stop(sdp->sd_logd_process);
+       kthread_stop(sdp->sd_recoverd_process);
+
+       if (!(sb->s_flags & MS_RDONLY)) {
+               error = gfs2_make_fs_ro(sdp);
+               if (error)
+                       gfs2_io_error(sdp);
+       }
+       /*  At this point, we're through modifying the disk  */
+
+       /*  Release stuff  */
+
+       iput(sdp->sd_jindex);
+       iput(sdp->sd_inum_inode);
+       iput(sdp->sd_statfs_inode);
+       iput(sdp->sd_rindex);
+       iput(sdp->sd_quota_inode);
+
+       gfs2_glock_put(sdp->sd_rename_gl);
+       gfs2_glock_put(sdp->sd_trans_gl);
+
+       if (!sdp->sd_args.ar_spectator) {
+               gfs2_glock_dq_uninit(&sdp->sd_journal_gh);
+               gfs2_glock_dq_uninit(&sdp->sd_jinode_gh);
+               gfs2_glock_dq_uninit(&sdp->sd_ir_gh);
+               gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
+               gfs2_glock_dq_uninit(&sdp->sd_qc_gh);
+               iput(sdp->sd_ir_inode);
+               iput(sdp->sd_sc_inode);
+               iput(sdp->sd_qc_inode);
+       }
+
+       gfs2_glock_dq_uninit(&sdp->sd_live_gh);
+       gfs2_clear_rgrpd(sdp);
+       gfs2_jindex_free(sdp);
+       /*  Take apart glock structures and buffer lists  */
+       gfs2_gl_hash_clear(sdp);
+       /*  Unmount the locking protocol  */
+       gfs2_lm_unmount(sdp);
+
+       /*  At this point, we're through participating in the lockspace  */
+       gfs2_sys_fs_del(sdp);
+       kfree(sdp);
+}
+
+/**
  * gfs2_write_super
  * @sb: the superblock
  *
@@ -622,7 +686,7 @@ const struct super_operations gfs2_super_ops = {
        .destroy_inode          = gfs2_destroy_inode,
        .write_inode            = gfs2_write_inode,
        .delete_inode           = gfs2_delete_inode,
-       .put_super              = gfs2_gl_hash_clear,
+       .put_super              = gfs2_put_super,
        .write_super            = gfs2_write_super,
        .sync_fs                = gfs2_sync_fs,
        .write_super_lockfs     = gfs2_write_super_lockfs,
index f14658b..141b781 100644 (file)
 #include "trans.h"
 #include "util.h"
 
+/**
+ * gfs2_jindex_free - Clear all the journal index information
+ * @sdp: The GFS2 superblock
+ *
+ */
+
+void gfs2_jindex_free(struct gfs2_sbd *sdp)
+{
+       struct list_head list, *head;
+       struct gfs2_jdesc *jd;
+       struct gfs2_journal_extent *jext;
+
+       spin_lock(&sdp->sd_jindex_spin);
+       list_add(&list, &sdp->sd_jindex_list);
+       list_del_init(&sdp->sd_jindex_list);
+       sdp->sd_journals = 0;
+       spin_unlock(&sdp->sd_jindex_spin);
+
+       while (!list_empty(&list)) {
+               jd = list_entry(list.next, struct gfs2_jdesc, jd_list);
+               head = &jd->extent_list;
+               while (!list_empty(head)) {
+                       jext = list_entry(head->next,
+                                         struct gfs2_journal_extent,
+                                         extent_list);
+                       list_del(&jext->extent_list);
+                       kfree(jext);
+               }
+               list_del(&jd->jd_list);
+               iput(jd->jd_inode);
+               kfree(jd);
+       }
+}
+
 static struct gfs2_jdesc *jdesc_find_i(struct list_head *head, unsigned int jid)
 {
        struct gfs2_jdesc *jd;
index 4d2492b..f6b8b00 100644 (file)
@@ -25,6 +25,8 @@ static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)
        return x;
 }
 
+void gfs2_jindex_free(struct gfs2_sbd *sdp);
+
 struct gfs2_jdesc *gfs2_jdesc_find(struct gfs2_sbd *sdp, unsigned int jid);
 int gfs2_jdesc_check(struct gfs2_jdesc *jd);
 
@@ -32,7 +34,6 @@ int gfs2_lookup_in_master_dir(struct gfs2_sbd *sdp, char *filename,
                              struct gfs2_inode **ipp);
 
 int gfs2_make_fs_rw(struct gfs2_sbd *sdp);
-int gfs2_make_fs_ro(struct gfs2_sbd *sdp);
 
 int gfs2_statfs_init(struct gfs2_sbd *sdp);
 void gfs2_statfs_change(struct gfs2_sbd *sdp,