Skip to content

Commit

Permalink
Revert "GFS2: Fix use-after-free bug on umount"
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
swhiteho committed Jan 5, 2009
1 parent 7ed122e commit fefc03b
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 94 deletions.
3 changes: 1 addition & 2 deletions fs/gfs2/glock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion fs/gfs2/glock.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
98 changes: 10 additions & 88 deletions fs/gfs2/ops_fstype.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1237,7 +1203,7 @@ static int fill_super(struct super_block *sb, void *data, int silent)
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();
Expand Down Expand Up @@ -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 = {
Expand Down
68 changes: 66 additions & 2 deletions fs/gfs2/ops_super.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ static int gfs2_write_inode(struct inode *inode, int sync)
* 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;
Expand All @@ -121,6 +121,70 @@ int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
return error;
}

/**
* 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
Expand Down Expand Up @@ -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,
Expand Down
34 changes: 34 additions & 0 deletions fs/gfs2/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,40 @@
#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;
Expand Down
3 changes: 2 additions & 1 deletion fs/gfs2/super.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ 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);

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,
Expand Down

0 comments on commit fefc03b

Please sign in to comment.