Commit ef38ff9d authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw

* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw: (49 commits)
  [GFS2] fix assertion in log_refund()
  [GFS2] fix GFP_KERNEL misuses
  [GFS2] test for IS_ERR rather than 0
  [GFS2] Invalidate cache at correct point
  [GFS2] fs/gfs2/recovery.c: suppress warnings
  [GFS2] Faster gfs2_bitfit algorithm
  [GFS2] Streamline quota lock/check for no-quota case
  [GFS2] Remove drop of module ref where not needed
  [GFS2] gfs2_adjust_quota has broken unstuffing code
  [GFS2] possible null pointer dereference fixup
  [GFS2] Need to ensure that sector_t is 64bits for GFS2
  [GFS2] re-support special inode
  [GFS2] remove gfs2_dev_iops
  [GFS2] fix file_system_type leak on gfs2meta mount
  [GFS2] Allow bmap to allocate extents
  [GFS2] Fix a page lock / glock deadlock
  [GFS2] proper extern for gfs2/locking/dlm/mount.c:gdlm_ops
  [GFS2] gfs2/ops_file.c should #include "ops_inode.h"
  [GFS2] be*_add_cpu conversion
  [GFS2] Fix bug where we called drop_bh incorrectly
  ...
parents fda31d7d 62be1f71
config GFS2_FS config GFS2_FS
tristate "GFS2 file system support" tristate "GFS2 file system support"
depends on EXPERIMENTAL depends on EXPERIMENTAL && (64BIT || (LSF && LBD))
select FS_POSIX_ACL select FS_POSIX_ACL
select CRC32 select CRC32
help help
......
obj-$(CONFIG_GFS2_FS) += gfs2.o obj-$(CONFIG_GFS2_FS) += gfs2.o
gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \ gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \
glops.o inode.o lm.o log.o lops.o locking.o main.o meta_io.o \ glops.o inode.o log.o lops.o locking.o main.o meta_io.o \
mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \ mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \
ops_fstype.o ops_inode.o ops_super.o quota.o \ ops_fstype.o ops_inode.o ops_super.o quota.o \
recovery.o rgrp.o super.o sys.o trans.o util.o recovery.o rgrp.o super.o sys.o trans.o util.o
......
...@@ -116,7 +116,7 @@ static int acl_get(struct gfs2_inode *ip, int access, struct posix_acl **acl, ...@@ -116,7 +116,7 @@ static int acl_get(struct gfs2_inode *ip, int access, struct posix_acl **acl,
goto out; goto out;
er.er_data_len = GFS2_EA_DATA_LEN(el->el_ea); er.er_data_len = GFS2_EA_DATA_LEN(el->el_ea);
er.er_data = kmalloc(er.er_data_len, GFP_KERNEL); er.er_data = kmalloc(er.er_data_len, GFP_NOFS);
error = -ENOMEM; error = -ENOMEM;
if (!er.er_data) if (!er.er_data)
goto out; goto out;
...@@ -222,7 +222,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip) ...@@ -222,7 +222,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip)
return error; return error;
} }
clone = posix_acl_clone(acl, GFP_KERNEL); clone = posix_acl_clone(acl, GFP_NOFS);
error = -ENOMEM; error = -ENOMEM;
if (!clone) if (!clone)
goto out; goto out;
...@@ -272,7 +272,7 @@ int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) ...@@ -272,7 +272,7 @@ int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
if (!acl) if (!acl)
return gfs2_setattr_simple(ip, attr); return gfs2_setattr_simple(ip, attr);
clone = posix_acl_clone(acl, GFP_KERNEL); clone = posix_acl_clone(acl, GFP_NOFS);
error = -ENOMEM; error = -ENOMEM;
if (!clone) if (!clone)
goto out; goto out;
......
This diff is collapsed.
This diff is collapsed.
...@@ -277,10 +277,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, ...@@ -277,10 +277,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
} }
*dataptrs = 0; *dataptrs = 0;
if (!ip->i_di.di_blocks) gfs2_add_inode_blocks(&ip->i_inode, -1);
gfs2_consist_inode(ip);
ip->i_di.di_blocks--;
gfs2_set_inode_blocks(&ip->i_inode);
} }
if (bstart) if (bstart)
gfs2_free_meta(ip, bstart, blen); gfs2_free_meta(ip, bstart, blen);
...@@ -321,6 +318,8 @@ static int ea_remove_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, ...@@ -321,6 +318,8 @@ static int ea_remove_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
int error; int error;
al = gfs2_alloc_get(ip); al = gfs2_alloc_get(ip);
if (!al)
return -ENOMEM;
error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
if (error) if (error)
...@@ -449,7 +448,7 @@ static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea, ...@@ -449,7 +448,7 @@ static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
unsigned int x; unsigned int x;
int error = 0; int error = 0;
bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_KERNEL); bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS);
if (!bh) if (!bh)
return -ENOMEM; return -ENOMEM;
...@@ -582,10 +581,11 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp) ...@@ -582,10 +581,11 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_ea_header *ea; struct gfs2_ea_header *ea;
unsigned int n = 1;
u64 block; u64 block;
block = gfs2_alloc_meta(ip); block = gfs2_alloc_block(ip, &n);
gfs2_trans_add_unrevoke(sdp, block, 1);
*bhp = gfs2_meta_new(ip->i_gl, block); *bhp = gfs2_meta_new(ip->i_gl, block);
gfs2_trans_add_bh(ip->i_gl, *bhp, 1); gfs2_trans_add_bh(ip->i_gl, *bhp, 1);
gfs2_metatype_set(*bhp, GFS2_METATYPE_EA, GFS2_FORMAT_EA); gfs2_metatype_set(*bhp, GFS2_METATYPE_EA, GFS2_FORMAT_EA);
...@@ -597,8 +597,7 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp) ...@@ -597,8 +597,7 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp)
ea->ea_flags = GFS2_EAFLAG_LAST; ea->ea_flags = GFS2_EAFLAG_LAST;
ea->ea_num_ptrs = 0; ea->ea_num_ptrs = 0;
ip->i_di.di_blocks++; gfs2_add_inode_blocks(&ip->i_inode, 1);
gfs2_set_inode_blocks(&ip->i_inode);
return 0; return 0;
} }
...@@ -642,15 +641,15 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea, ...@@ -642,15 +641,15 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
struct buffer_head *bh; struct buffer_head *bh;
u64 block; u64 block;
int mh_size = sizeof(struct gfs2_meta_header); int mh_size = sizeof(struct gfs2_meta_header);
unsigned int n = 1;
block = gfs2_alloc_meta(ip); block = gfs2_alloc_block(ip, &n);
gfs2_trans_add_unrevoke(sdp, block, 1);
bh = gfs2_meta_new(ip->i_gl, block); bh = gfs2_meta_new(ip->i_gl, block);
gfs2_trans_add_bh(ip->i_gl, bh, 1); gfs2_trans_add_bh(ip->i_gl, bh, 1);
gfs2_metatype_set(bh, GFS2_METATYPE_ED, GFS2_FORMAT_ED); gfs2_metatype_set(bh, GFS2_METATYPE_ED, GFS2_FORMAT_ED);
ip->i_di.di_blocks++; gfs2_add_inode_blocks(&ip->i_inode, 1);
gfs2_set_inode_blocks(&ip->i_inode);
copy = data_len > sdp->sd_jbsize ? sdp->sd_jbsize : copy = data_len > sdp->sd_jbsize ? sdp->sd_jbsize :
data_len; data_len;
...@@ -684,15 +683,13 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er, ...@@ -684,15 +683,13 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
int error; int error;
al = gfs2_alloc_get(ip); al = gfs2_alloc_get(ip);
if (!al)
return -ENOMEM;
error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); error = gfs2_quota_lock_check(ip);
if (error) if (error)
goto out; goto out;
error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
if (error)
goto out_gunlock_q;
al->al_requested = blks; al->al_requested = blks;
error = gfs2_inplace_reserve(ip); error = gfs2_inplace_reserve(ip);
...@@ -966,9 +963,9 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er, ...@@ -966,9 +963,9 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
gfs2_trans_add_bh(ip->i_gl, indbh, 1); gfs2_trans_add_bh(ip->i_gl, indbh, 1);
} else { } else {
u64 blk; u64 blk;
unsigned int n = 1;
blk = gfs2_alloc_meta(ip); blk = gfs2_alloc_block(ip, &n);
gfs2_trans_add_unrevoke(sdp, blk, 1);
indbh = gfs2_meta_new(ip->i_gl, blk); indbh = gfs2_meta_new(ip->i_gl, blk);
gfs2_trans_add_bh(ip->i_gl, indbh, 1); gfs2_trans_add_bh(ip->i_gl, indbh, 1);
gfs2_metatype_set(indbh, GFS2_METATYPE_IN, GFS2_FORMAT_IN); gfs2_metatype_set(indbh, GFS2_METATYPE_IN, GFS2_FORMAT_IN);
...@@ -978,8 +975,7 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er, ...@@ -978,8 +975,7 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
*eablk = cpu_to_be64(ip->i_di.di_eattr); *eablk = cpu_to_be64(ip->i_di.di_eattr);
ip->i_di.di_eattr = blk; ip->i_di.di_eattr = blk;
ip->i_di.di_flags |= GFS2_DIF_EA_INDIRECT; ip->i_di.di_flags |= GFS2_DIF_EA_INDIRECT;
ip->i_di.di_blocks++; gfs2_add_inode_blocks(&ip->i_inode, 1);
gfs2_set_inode_blocks(&ip->i_inode);
eablk++; eablk++;
} }
...@@ -1210,7 +1206,7 @@ static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip, ...@@ -1210,7 +1206,7 @@ static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
unsigned int x; unsigned int x;
int error; int error;
bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_KERNEL); bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS);
if (!bh) if (!bh)
return -ENOMEM; return -ENOMEM;
...@@ -1347,7 +1343,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) ...@@ -1347,7 +1343,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
else else
goto out; goto out;
gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0); gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE);
for (x = 0; x < rlist.rl_rgrps; x++) { for (x = 0; x < rlist.rl_rgrps; x++) {
struct gfs2_rgrpd *rgd; struct gfs2_rgrpd *rgd;
...@@ -1387,10 +1383,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) ...@@ -1387,10 +1383,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
} }
*eablk = 0; *eablk = 0;
if (!ip->i_di.di_blocks) gfs2_add_inode_blocks(&ip->i_inode, -1);
gfs2_consist_inode(ip);
ip->i_di.di_blocks--;
gfs2_set_inode_blocks(&ip->i_inode);
} }
if (bstart) if (bstart)
gfs2_free_meta(ip, bstart, blen); gfs2_free_meta(ip, bstart, blen);
...@@ -1442,10 +1435,7 @@ static int ea_dealloc_block(struct gfs2_inode *ip) ...@@ -1442,10 +1435,7 @@ static int ea_dealloc_block(struct gfs2_inode *ip)
gfs2_free_meta(ip, ip->i_di.di_eattr, 1); gfs2_free_meta(ip, ip->i_di.di_eattr, 1);
ip->i_di.di_eattr = 0; ip->i_di.di_eattr = 0;
if (!ip->i_di.di_blocks) gfs2_add_inode_blocks(&ip->i_inode, -1);
gfs2_consist_inode(ip);
ip->i_di.di_blocks--;
gfs2_set_inode_blocks(&ip->i_inode);
error = gfs2_meta_inode_buffer(ip, &dibh); error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) { if (!error) {
...@@ -1474,6 +1464,8 @@ int gfs2_ea_dealloc(struct gfs2_inode *ip) ...@@ -1474,6 +1464,8 @@ int gfs2_ea_dealloc(struct gfs2_inode *ip)
int error; int error;
al = gfs2_alloc_get(ip); al = gfs2_alloc_get(ip);
if (!al)
return -ENOMEM;
error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
if (error) if (error)
......
This diff is collapsed.
...@@ -32,24 +32,23 @@ ...@@ -32,24 +32,23 @@
#define GLR_TRYFAILED 13 #define GLR_TRYFAILED 13
#define GLR_CANCELED 14 #define GLR_CANCELED 14
static inline int gfs2_glock_is_locked_by_me(struct gfs2_glock *gl) static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *gl)
{ {
struct gfs2_holder *gh; struct gfs2_holder *gh;
int locked = 0;
struct pid *pid; struct pid *pid;
/* Look in glock's list of holders for one with current task as owner */ /* Look in glock's list of holders for one with current task as owner */
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
pid = task_pid(current); pid = task_pid(current);
list_for_each_entry(gh, &gl->gl_holders, gh_list) { list_for_each_entry(gh, &gl->gl_holders, gh_list) {
if (gh->gh_owner_pid == pid) { if (gh->gh_owner_pid == pid)
locked = 1; goto out;
break;
}
} }
gh = NULL;
out:
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
return locked; return gh;
} }
static inline int gfs2_glock_is_held_excl(struct gfs2_glock *gl) static inline int gfs2_glock_is_held_excl(struct gfs2_glock *gl)
...@@ -79,7 +78,6 @@ static inline int gfs2_glock_is_blocking(struct gfs2_glock *gl) ...@@ -79,7 +78,6 @@ static inline int gfs2_glock_is_blocking(struct gfs2_glock *gl)
int gfs2_glock_get(struct gfs2_sbd *sdp, int gfs2_glock_get(struct gfs2_sbd *sdp,
u64 number, const struct gfs2_glock_operations *glops, u64 number, const struct gfs2_glock_operations *glops,
int create, struct gfs2_glock **glp); int create, struct gfs2_glock **glp);
void gfs2_glock_hold(struct gfs2_glock *gl);
int gfs2_glock_put(struct gfs2_glock *gl); int gfs2_glock_put(struct gfs2_glock *gl);
void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags, void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags,
struct gfs2_holder *gh); struct gfs2_holder *gh);
......
/* /*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
* *
* This copyrighted material is made available to anyone wishing to use, * This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions * modify, copy, or redistribute it subject to the terms and conditions
...@@ -126,7 +126,13 @@ static void meta_go_inval(struct gfs2_glock *gl, int flags) ...@@ -126,7 +126,13 @@ static void meta_go_inval(struct gfs2_glock *gl, int flags)
return; return;
gfs2_meta_inval(gl); gfs2_meta_inval(gl);
gl->gl_vn++; if (gl->gl_object == GFS2_I(gl->gl_sbd->sd_rindex))
gl->gl_sbd->sd_rindex_uptodate = 0;
else if (gl->gl_ops == &gfs2_rgrp_glops && gl->gl_object) {
struct gfs2_rgrpd *rgd = (struct gfs2_rgrpd *)gl->gl_object;
rgd->rd_flags &= ~GFS2_RDF_UPTODATE;
}
} }
/** /**
......
/* /*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
* *
* This copyrighted material is made available to anyone wishing to use, * This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions * modify, copy, or redistribute it subject to the terms and conditions
...@@ -44,7 +44,6 @@ struct gfs2_log_header_host { ...@@ -44,7 +44,6 @@ struct gfs2_log_header_host {
struct gfs2_log_operations { struct gfs2_log_operations {
void (*lo_add) (struct gfs2_sbd *sdp, struct gfs2_log_element *le); void (*lo_add) (struct gfs2_sbd *sdp, struct gfs2_log_element *le);
void (*lo_incore_commit) (struct gfs2_sbd *sdp, struct gfs2_trans *tr);
void (*lo_before_commit) (struct gfs2_sbd *sdp); void (*lo_before_commit) (struct gfs2_sbd *sdp);
void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_ail *ai); void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_ail *ai);
void (*lo_before_scan) (struct gfs2_jdesc *jd, void (*lo_before_scan) (struct gfs2_jdesc *jd,
...@@ -70,7 +69,6 @@ struct gfs2_bitmap { ...@@ -70,7 +69,6 @@ struct gfs2_bitmap {
}; };
struct gfs2_rgrp_host { struct gfs2_rgrp_host {
u32 rg_flags;
u32 rg_free; u32 rg_free;
u32 rg_dinodes; u32 rg_dinodes;
u64 rg_igeneration; u64 rg_igeneration;
...@@ -87,17 +85,17 @@ struct gfs2_rgrpd { ...@@ -87,17 +85,17 @@ struct gfs2_rgrpd {
u32 rd_data; /* num of data blocks in rgrp */ u32 rd_data; /* num of data blocks in rgrp */
u32 rd_bitbytes; /* number of bytes in data bitmaps */ u32 rd_bitbytes; /* number of bytes in data bitmaps */
struct gfs2_rgrp_host rd_rg; struct gfs2_rgrp_host rd_rg;
u64 rd_rg_vn;
struct gfs2_bitmap *rd_bits; struct gfs2_bitmap *rd_bits;
unsigned int rd_bh_count; unsigned int rd_bh_count;
struct mutex rd_mutex; struct mutex rd_mutex;
u32 rd_free_clone; u32 rd_free_clone;
struct gfs2_log_element rd_le; struct gfs2_log_element rd_le;
u32 rd_last_alloc_data; u32 rd_last_alloc;
u32 rd_last_alloc_meta;
struct gfs2_sbd *rd_sbd; struct gfs2_sbd *rd_sbd;
unsigned long rd_flags; unsigned char rd_flags;
#define GFS2_RDF_CHECK 0x0001 /* Need to check for unlinked inodes */ #define GFS2_RDF_CHECK 0x01 /* Need to check for unlinked inodes */
#define GFS2_RDF_NOALLOC 0x02 /* rg prohibits allocation */
#define GFS2_RDF_UPTODATE 0x04 /* rg is up to date */
}; };
enum gfs2_state_bits { enum gfs2_state_bits {
...@@ -168,6 +166,8 @@ enum { ...@@ -168,6 +166,8 @@ enum {
GLF_DIRTY = 5, GLF_DIRTY = 5,
GLF_DEMOTE_IN_PROGRESS = 6, GLF_DEMOTE_IN_PROGRESS = 6,
GLF_LFLUSH = 7, GLF_LFLUSH = 7,
GLF_WAITERS2 = 8,
GLF_CONV_DEADLK = 9,
}; };
struct gfs2_glock { struct gfs2_glock {
...@@ -187,18 +187,15 @@ struct gfs2_glock { ...@@ -187,18 +187,15 @@ struct gfs2_glock {
struct list_head gl_holders; struct list_head gl_holders;
struct list_head gl_waiters1; /* HIF_MUTEX */ struct list_head gl_waiters1; /* HIF_MUTEX */
struct list_head gl_waiters3; /* HIF_PROMOTE */ struct list_head gl_waiters3; /* HIF_PROMOTE */
int gl_waiters2; /* GIF_DEMOTE */
const struct gfs2_glock_operations *gl_ops; const struct gfs2_glock_operations *gl_ops;
struct gfs2_holder *gl_req_gh; struct gfs2_holder *gl_req_gh;
gfs2_glop_bh_t gl_req_bh;
void *gl_lock; void *gl_lock;
char *gl_lvb; char *gl_lvb;
atomic_t gl_lvb_count; atomic_t gl_lvb_count;
u64 gl_vn;
unsigned long gl_stamp; unsigned long gl_stamp;
unsigned long gl_tchange; unsigned long gl_tchange;
void *gl_object; void *gl_object;
...@@ -213,6 +210,8 @@ struct gfs2_glock { ...@@ -213,6 +210,8 @@ struct gfs2_glock {
struct delayed_work gl_work; struct delayed_work gl_work;
}; };
#define GFS2_MIN_LVB_SIZE 32 /* Min size of LVB that gfs2 supports */
struct gfs2_alloc { struct gfs2_alloc {
/* Quota stuff */ /* Quota stuff */
...@@ -241,14 +240,9 @@ enum { ...@@ -241,14 +240,9 @@ enum {
struct gfs2_dinode_host { struct gfs2_dinode_host {
u64 di_size; /* number of bytes in file */ u64 di_size; /* number of bytes in file */
u64 di_blocks; /* number of blocks in file */
u64 di_goal_meta; /* rgrp to alloc from next */
u64 di_goal_data; /* data block goal */
u64 di_generation; /* generation number for NFS */ u64 di_generation; /* generation number for NFS */
u32 di_flags; /* GFS2_DIF_... */ u32 di_flags; /* GFS2_DIF_... */
u16 di_height; /* height of metadata */
/* These only apply to directories */ /* These only apply to directories */
u16 di_depth; /* Number of bits in the table */
u32 di_entries; /* The number of entries in the directory */ u32 di_entries; /* The number of entries in the directory */
u64 di_eattr; /* extended attribute block number */ u64 di_eattr; /* extended attribute block number */
}; };
...@@ -265,9 +259,10 @@ struct gfs2_inode { ...@@ -265,9 +259,10 @@ struct gfs2_inode {
struct gfs2_holder i_iopen_gh; struct gfs2_holder i_iopen_gh;
struct gfs2_holder i_gh; /* for prepare/commit_write only */ struct gfs2_holder i_gh; /* for prepare/commit_write only */
struct gfs2_alloc *i_alloc; struct gfs2_alloc *i_alloc;
u64 i_last_rg_alloc; u64 i_goal; /* goal block for allocations */
struct rw_semaphore i_rw_mutex; struct rw_semaphore i_rw_mutex;
u8 i_height;
u8 i_depth;
}; };
/* /*
...@@ -490,9 +485,9 @@ struct gfs2_sbd { ...@@ -490,9 +485,9 @@ struct gfs2_sbd {
u32 sd_qc_per_block; u32 sd_qc_per_block;
u32 sd_max_dirres; /* Max blocks needed to add a directory entry */ u32 sd_max_dirres; /* Max blocks needed to add a directory entry */
u32 sd_max_height; /* Max height of a file's metadata tree */ u32 sd_max_height; /* Max height of a file's metadata tree */
u64 sd_heightsize[GFS2_MAX_META_HEIGHT]; u64 sd_heightsize[GFS2_MAX_META_HEIGHT + 1];
u32 sd_max_jheight; /* Max height of journaled file's meta tree */ u32 sd_max_jheight; /* Max height of journaled file's meta tree */
u64 sd_jheightsize[GFS2_MAX_META_HEIGHT]; u64 sd_jheightsize[GFS2_MAX_META_HEIGHT + 1];
struct gfs2_args sd_args; /* Mount arguments */ struct gfs2_args sd_args; /* Mount arguments */
struct gfs2_tune sd_tune; /* Filesystem tuning structure */ struct gfs2_tune sd_tune; /* Filesystem tuning structure */
...@@ -533,7 +528,7 @@ struct gfs2_sbd { ...@@ -533,7 +528,7 @@ struct gfs2_sbd {
/* Resource group stuff */ /* Resource group stuff */
u64 sd_rindex_vn; int sd_rindex_uptodate;
spinlock_t sd_rindex_spin; spinlock_t sd_rindex_spin;
struct mutex sd_rindex_mutex; struct mutex sd_rindex_mutex;
struct list_head sd_rindex_list; struct list_head sd_rindex_list;
...@@ -637,9 +632,6 @@ struct gfs2_sbd { ...@@ -637,9 +632,6 @@ struct gfs2_sbd {
/* Counters */ /* Counters */
atomic_t sd_glock_count;
atomic_t sd_glock_held_count;
atomic_t sd_inode_count;
atomic_t sd_reclaimed; atomic_t sd_reclaimed;
char sd_fsname[GFS2_FSNAME_LEN]; char sd_fsname[GFS2_FSNAME_LEN];
......
/* /*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
* *
* This copyrighted material is made available to anyone wishing to use, * This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions * modify, copy, or redistribute it subject to the terms and conditions
...@@ -149,7 +149,8 @@ void gfs2_set_iop(struct inode *inode) ...@@ -149,7 +149,8 @@ void gfs2_set_iop(struct inode *inode)
} else if (S_ISLNK(mode)) { } else if (S_ISLNK(mode)) {
inode->i_op = &gfs2_symlink_iops; inode->i_op = &gfs2_symlink_iops;
} else { } else {
inode->i_op = &gfs2_dev_iops; inode->i_op = &gfs2_file_iops;
init_special_inode(inode, inode->i_mode, inode->i_rdev);
} }
unlock_new_inode(inode); unlock_new_inode(inode);
...@@ -248,12 +249,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) ...@@ -248,12 +249,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
{ {
struct gfs2_dinode_host *di = &ip->i_di; struct gfs2_dinode_host *di = &ip->i_di;
const struct gfs2_dinode *str = buf; const struct gfs2_dinode *str = buf;
u16 height, depth;
if (ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)) { if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)))
if (gfs2_consist_inode(ip)) goto corrupt;
gfs2_dinode_print(ip);
return -EIO;
}
ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino); ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino);
ip->i_inode.i_mode = be32_to_cpu(str->di_mode); ip->i_inode.i_mode = be32_to_cpu(str->di_mode);
ip->i_inode.i_rdev = 0; ip->i_inode.i_rdev = 0;
...@@ -275,8 +274,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) ...@@ -275,8 +274,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink); ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink);
di->di_size = be64_to_cpu(str->di_size); di->di_size = be64_to_cpu(str->di_size);
i_size_write(&ip->i_inode, di->di_size); i_size_write(&ip->i_inode, di->di_size);
di->di_blocks = be64_to_cpu(str->di_blocks); gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
gfs2_set_inode_blocks(&ip->i_inode);
ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime); ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime);
ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec); ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime); ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
...@@ -284,15 +282,20 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) ...@@ -284,15 +282,20 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime); ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime);
ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec); ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec);
di->di_goal_meta = be64_to_cpu(str->di_goal_meta); ip->i_goal = be64_to_cpu(str->di_goal_meta);
di->di_goal_data = be64_to_cpu(str->di_goal_data);
di->di_generation = be64_to_cpu(str->di_generation); di->di_generation = be64_to_cpu(str->di_generation);
di->di_flags = be32_to_cpu(str->di_flags); di->di_flags = be32_to_cpu(str->di_flags);
gfs2_set_inode_flags(&ip->i_inode); gfs2_set_inode_flags(&ip->i_inode);
di->di_height = be16_to_cpu(str->di_height); height = be16_to_cpu(str->di_height);
if (unlikely(height > GFS2_MAX_META_HEIGHT))
di->di_depth = be16_to_cpu(str->di_depth); goto corrupt;
ip->i_height = (u8)height;
depth = be16_to_cpu(str->di_depth);
if (unlikely(depth > GFS2_DIR_MAX_DEPTH))
goto corrupt;
ip->i_depth = (u8)depth;
di->di_entries = be32_to_cpu(str->di_entries); di->di_entries = be32_to_cpu(str->di_entries);
di->di_eattr = be64_to_cpu(str->di_eattr); di->di_eattr = be64_to_cpu(str->di_eattr);
...@@ -300,6 +303,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) ...@@ -300,6 +303,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
gfs2_set_aops(&ip->i_inode); gfs2_set_aops(&ip->i_inode);
return 0; return 0;
corrupt:
if (gfs2_consist_inode(ip))
gfs2_dinode_print(ip);
return -EIO;
} }
/** /**
...@@ -337,13 +344,15 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip) ...@@ -337,13 +344,15 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip)
struct gfs2_rgrpd *rgd; struct gfs2_rgrpd *rgd;
int error; int error;
if (ip->i_di.di_blocks != 1) { if (gfs2_get_inode_blocks(&ip->i_inode) != 1) {
if (gfs2_consist_inode(ip)) if (gfs2_consist_inode(ip))
gfs2_dinode_print(ip); gfs2_dinode_print(ip);
return -EIO; return -EIO;
} }
al = gfs2_alloc_get(ip); al = gfs2_alloc_get(ip);
if (!al)
return -ENOMEM;
error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
if (error) if (error)
...@@ -487,7 +496,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, ...@@ -487,7 +496,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
return dir; return dir;
} }
if (gfs2_glock_is_locked_by_me(dip->i_gl) == 0) { if (gfs2_glock_is_locked_by_me(dip->i_gl) == NULL) {
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
if (error) if (error)
return ERR_PTR(error); return ERR_PTR(error);
...@@ -818,7 +827,8 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, ...@@ -818,7 +827,8 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
int error; int error;
munge_mode_uid_gid(dip, &mode, &uid, &gid); munge_mode_uid_gid(dip, &mode, &uid, &gid);
gfs2_alloc_get(dip); if (!gfs2_alloc_get(dip))
return -ENOMEM;
error = gfs2_quota_lock(dip, uid, gid); error = gfs2_quota_lock(dip, uid, gid);
if (error) if (error)
...@@ -853,6 +863,8 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name, ...@@ -853,6 +863,8 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
int error; int error;
al = gfs2_alloc_get(dip); al = gfs2_alloc_get(dip);
if (!al)
return -ENOMEM;
error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
if (error) if (error)
...@@ -1219,7 +1231,7 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len) ...@@ -1219,7 +1231,7 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len)
x = ip->i_di.di_size + 1; x = ip->i_di.di_size + 1;
if (x > *len) { if (x > *len) {
*buf = kmalloc(x, GFP_KERNEL); *buf = kmalloc(x, GFP_NOFS);
if (!*buf) { if (!*buf) {
error = -ENOMEM; error = -ENOMEM;
goto out_brelse; goto out_brelse;
...@@ -1391,21 +1403,21 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) ...@@ -1391,21 +1403,21 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
str->di_gid = cpu_to_be32(ip->i_inode.i_gid); str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink); str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
str->di_size = cpu_to_be64(di->di_size); str->di_size = cpu_to_be64(di->di_size);
str->di_blocks = cpu_to_be64(di->di_blocks); str->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec); str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec); str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec);
str->di_goal_meta = cpu_to_be64(di->di_goal_meta); str->di_goal_meta = cpu_to_be64(ip->i_goal);
str->di_goal_data = cpu_to_be64(di->di_goal_data); str->di_goal_data = cpu_to_be64(ip->i_goal);
str->di_generation = cpu_to_be64(di->di_generation); str->di_generation = cpu_to_be64(di->di_generation);
str->di_flags = cpu_to_be32(di->di_flags); str->di_flags = cpu_to_be32(di->di_flags);
str->di_height = cpu_to_be16(di->di_height); str->di_height = cpu_to_be16(ip->i_height);
str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) && str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&
!(ip->i_di.di_flags & GFS2_DIF_EXHASH) ? !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?
GFS2_FORMAT_DE : 0); GFS2_FORMAT_DE : 0);
str->di_depth = cpu_to_be16(di->di_depth); str->di_depth = cpu_to_be16(ip->i_depth);
str->di_entries = cpu_to_be32(di->di_entries); str->di_entries = cpu_to_be32(di->di_entries);
str->di_eattr = cpu_to_be64(di->di_eattr); str->di_eattr = cpu_to_be64(di->di_eattr);
...@@ -1423,15 +1435,13 @@ void gfs2_dinode_print(const struct gfs2_inode *ip) ...@@ -1423,15 +1435,13 @@ void gfs2_dinode_print(const struct gfs2_inode *ip)
printk(KERN_INFO " no_addr = %llu\n", printk(KERN_INFO " no_addr = %llu\n",
(unsigned long long)ip->i_no_addr); (unsigned long long)ip->i_no_addr);
printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size); printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size);
printk(KERN_INFO " di_blocks = %llu\n", printk(KERN_INFO " blocks = %llu\n",
(unsigned long long)di->di_blocks); (unsigned long long)gfs2_get_inode_blocks(&ip->i_inode));
printk(KERN_INFO " di_goal_meta = %llu\n", printk(KERN_INFO " i_goal = %llu\n",
(unsigned long long)di->di_goal_meta); (unsigned long long)ip->i_goal);
printk(KERN_INFO " di_goal_data = %llu\n",
(unsigned long long)di->di_goal_data);
printk(KERN_INFO " di_flags = 0x%.8X\n", di->di_flags); printk(KERN_INFO " di_flags = 0x%.8X\n", di->di_flags);
printk(KERN_INFO " di_height = %u\n", di->di_height); printk(KERN_INFO " i_height = %u\n", ip->i_height);
printk(KERN_INFO " di_depth = %u\n", di->di_depth); printk(KERN_INFO " i_depth = %u\n", ip->i_depth);
printk(KERN_INFO " di_entries = %u\n", di->di_entries); printk(KERN_INFO " di_entries = %u\n", di->di_entries);
printk(KERN_INFO " di_eattr = %llu\n", printk(KERN_INFO " di_eattr = %llu\n",
(unsigned long long)di->di_eattr); (unsigned long long)di->di_eattr);
......
...@@ -10,9 +10,11 @@ ...@@ -10,9 +10,11 @@
#ifndef __INODE_DOT_H__ #ifndef __INODE_DOT_H__
#define __INODE_DOT_H__ #define __INODE_DOT_H__
#include "util.h"
static inline int gfs2_is_stuffed(const struct gfs2_inode *ip) static inline int gfs2_is_stuffed(const struct gfs2_inode *ip)
{ {
return !ip->i_di.di_height; return !ip->i_height;
} }
static inline int gfs2_is_jdata(const struct gfs2_inode *ip) static inline int gfs2_is_jdata(const struct gfs2_inode *ip)
...@@ -37,13 +39,25 @@ static inline int gfs2_is_dir(const struct gfs2_inode *ip) ...@@ -37,13 +39,25 @@ static inline int gfs2_is_dir(const struct gfs2_inode *ip)
return S_ISDIR(ip->i_inode.i_mode); return S_ISDIR(ip->i_inode.i_mode);
} }
static inline void gfs2_set_inode_blocks(struct inode *inode) static inline void gfs2_set_inode_blocks(struct inode *inode, u64 blocks)
{
inode->i_blocks = blocks <<
(GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
}
static inline u64 gfs2_get_inode_blocks(const struct inode *inode)
{ {
struct gfs2_inode *ip = GFS2_I(inode); return inode->i_blocks >>
inode->i_blocks = ip->i_di.di_blocks <<
(GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT); (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
} }
static inline void gfs2_add_inode_blocks(struct inode *inode, s64 change)
{
gfs2_assert(GFS2_SB(inode), (change >= 0 || inode->i_blocks > -change));
change *= (GFS2_SB(inode)->sd_sb.sb_bsize/GFS2_BASIC_BLOCK);
inode->i_blocks += change;
}
static inline int gfs2_check_inum(const struct gfs2_inode *ip, u64 no_addr, static inline int gfs2_check_inum(const struct gfs2_inode *ip, u64 no_addr,
u64 no_formal_ino) u64 no_formal_ino)
{ {
......
/*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License version 2.
*/
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/buffer_head.h>
#include <linux/delay.h>
#include <linux/gfs2_ondisk.h>
#include <linux/lm_interface.h>
#include "gfs2.h"
#include "incore.h"
#include "glock.h"
#include "lm.h"
#include "super.h"
#include "util.h"
/**
* gfs2_lm_mount - mount a locking protocol
* @sdp: the filesystem
* @args: mount arguements
* @silent: if 1, don't complain if the FS isn't a GFS2 fs
*
* Returns: errno
*/
int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
{
char *proto = sdp->sd_proto_name;
char *table = sdp->sd_table_name;
int flags = 0;
int error;
if (sdp->sd_args.ar_spectator)
flags |= LM_MFLAG_SPECTATOR;
fs_info(sdp, "Trying to join cluster \"%s\", \"%s\"\n", proto, table);
error = gfs2_mount_lockproto(proto, table, sdp->sd_args.ar_hostdata,
gfs2_glock_cb, sdp,
GFS2_MIN_LVB_SIZE, flags,
&sdp->sd_lockstruct, &sdp->sd_kobj);
if (error) {
fs_info(sdp, "can't mount proto=%s, table=%s, hostdata=%s\n",
proto, table, sdp->sd_args.ar_hostdata);
goto out;
}
if (gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lockspace) ||
gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_ops) ||
gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lvb_size >=
GFS2_MIN_LVB_SIZE)) {
gfs2_unmount_lockproto(&sdp->sd_lockstruct);
goto out;
}
if (sdp->sd_args.ar_spectator)
snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.s", table);
else
snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.%u", table,
sdp->sd_lockstruct.ls_jid);
fs_info(sdp, "Joined cluster. Now mounting FS...\n");
if ((sdp->sd_lockstruct.ls_flags & LM_LSFLAG_LOCAL) &&
!sdp->sd_args.ar_ignore_local_fs) {
sdp->sd_args.ar_localflocks = 1;
sdp->sd_args.ar_localcaching = 1;
}
out:
return error;
}
void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp)
{
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
sdp->sd_lockstruct.ls_ops->lm_others_may_mount(
sdp->sd_lockstruct.ls_lockspace);
}
void gfs2_lm_unmount(struct gfs2_sbd *sdp)
{
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
gfs2_unmount_lockproto(&sdp->sd_lockstruct);
}
int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...)
{
va_list args;
if (test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags))
return 0;
va_start(args, fmt);
vprintk(fmt, args);
va_end(args);
fs_err(sdp, "about to withdraw this file system\n");
BUG_ON(sdp->sd_args.ar_debug);
fs_err(sdp, "telling LM to withdraw\n");
gfs2_withdraw_lockproto(&sdp->sd_lockstruct);
fs_err(sdp, "withdrawn\n");
dump_stack();
return -1;
}
int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name,
void **lockp)
{
int error = -EIO;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
error = sdp->sd_lockstruct.ls_ops->lm_get_lock(
sdp->sd_lockstruct.ls_lockspace, name, lockp);
return error;
}
void gfs2_lm_put_lock(struct gfs2_sbd *sdp, void *lock)
{
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
sdp->sd_lockstruct.ls_ops->lm_put_lock(lock);
}
unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock,
unsigned int cur_state, unsigned int req_state,
unsigned int flags)
{
int ret = 0;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock, cur_state,
req_state, flags);
return ret;
}
unsigned int gfs2_lm_unlock(struct gfs2_sbd *sdp, void *lock,
unsigned int cur_state)
{
int ret = 0;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
ret = sdp->sd_lockstruct.ls_ops->lm_unlock(lock, cur_state);
return ret;
}
void gfs2_lm_cancel(struct gfs2_sbd *sdp, void *lock)
{
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
sdp->sd_lockstruct.ls_ops->lm_cancel(lock);
}
int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp)
{
int error = -EIO;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
error = sdp->sd_lockstruct.ls_ops->lm_hold_lvb(lock, lvbp);
return error;
}
void gfs2_lm_unhold_lvb(struct gfs2_sbd *sdp, void *lock, char *lvb)
{
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
sdp->sd_lockstruct.ls_ops->lm_unhold_lvb(lock, lvb);
}
int gfs2_lm_plock_get(struct gfs2_sbd *sdp, struct lm_lockname *name,
struct file *file, struct file_lock *fl)
{
int error = -EIO;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
error = sdp->sd_lockstruct.ls_ops->lm_plock_get(
sdp->sd_lockstruct.ls_lockspace, name, file, fl);
return error;
}
int gfs2_lm_plock(struct gfs2_sbd *sdp, struct lm_lockname *name,
struct file *file, int cmd, struct file_lock *fl)
{
int error = -EIO;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
error = sdp->sd_lockstruct.ls_ops->lm_plock(
sdp->sd_lockstruct.ls_lockspace, name, file, cmd, fl);
return error;
}
int gfs2_lm_punlock(struct gfs2_sbd *sdp, struct lm_lockname *name,
struct file *file, struct file_lock *fl)
{
int error = -EIO;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
error = sdp->sd_lockstruct.ls_ops->lm_punlock(
sdp->sd_lockstruct.ls_lockspace, name, file, fl);
return error;
}
void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,
unsigned int message)
{
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
sdp->sd_lockstruct.ls_ops->lm_recovery_done(
sdp->sd_lockstruct.ls_lockspace, jid, message);
}
/*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License version 2.
*/
#ifndef __LM_DOT_H__
#define __LM_DOT_H__
struct gfs2_sbd;
#define GFS2_MIN_LVB_SIZE 32
int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent);
void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp);
void gfs2_lm_unmount(struct gfs2_sbd *sdp);
int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name,
void **lockp);
void gfs2_lm_put_lock(struct gfs2_sbd *sdp, void *lock);
unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock,
unsigned int cur_state, unsigned int req_state,
unsigned int flags);
unsigned int gfs2_lm_unlock(struct gfs2_sbd *sdp, void *lock,
unsigned int cur_state);
void gfs2_lm_cancel(struct gfs2_sbd *sdp, void *lock);
int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp);
void gfs2_lm_unhold_lvb(struct gfs2_sbd *sdp, void *lock, char *lvb);
int gfs2_lm_plock_get(struct gfs2_sbd *sdp, struct lm_lockname *name,
struct file *file, struct file_lock *fl);
int gfs2_lm_plock(struct gfs2_sbd *sdp, struct lm_lockname *name,
struct file *file, int cmd, struct file_lock *fl);
int gfs2_lm_punlock(struct gfs2_sbd *sdp, struct lm_lockname *name,
struct file *file, struct file_lock *fl);
void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,
unsigned int message);
#endif /* __LM_DOT_H__ */
...@@ -137,7 +137,8 @@ static inline unsigned int make_flags(struct gdlm_lock *lp, ...@@ -137,7 +137,8 @@ static inline unsigned int make_flags(struct gdlm_lock *lp,
/* Conversion deadlock avoidance by DLM */ /* Conversion deadlock avoidance by DLM */
if (!test_bit(LFL_FORCE_PROMOTE, &lp->flags) && if (!(lp->ls->fsflags & LM_MFLAG_CONV_NODROP) &&
!test_bit(LFL_FORCE_PROMOTE, &lp->flags) &&
!(lkf & DLM_LKF_NOQUEUE) && !(lkf & DLM_LKF_NOQUEUE) &&
cur > DLM_LOCK_NL && req > DLM_LOCK_NL && cur != req) cur > DLM_LOCK_NL && req > DLM_LOCK_NL && cur != req)
lkf |= DLM_LKF_CONVDEADLK; lkf |= DLM_LKF_CONVDEADLK;
...@@ -164,7 +165,7 @@ static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name, ...@@ -164,7 +165,7 @@ static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name,
{ {
struct gdlm_lock *lp; struct gdlm_lock *lp;
lp = kzalloc(sizeof(struct gdlm_lock), GFP_KERNEL); lp = kzalloc(sizeof(struct gdlm_lock), GFP_NOFS);
if (!lp) if (!lp)
return -ENOMEM; return -ENOMEM;
...@@ -382,7 +383,7 @@ static int gdlm_add_lvb(struct gdlm_lock *lp) ...@@ -382,7 +383,7 @@ static int gdlm_add_lvb(struct gdlm_lock *lp)
{ {
char *lvb; char *lvb;
lvb = kzalloc(GDLM_LVB_SIZE, GFP_KERNEL); lvb = kzalloc(GDLM_LVB_SIZE, GFP_NOFS);
if (!lvb) if (!lvb)
return -ENOMEM; return -ENOMEM;
......
...@@ -183,5 +183,10 @@ int gdlm_plock_get(void *, struct lm_lockname *, struct file *, ...@@ -183,5 +183,10 @@ int gdlm_plock_get(void *, struct lm_lockname *, struct file *,
struct file_lock *); struct file_lock *);
int gdlm_punlock(void *, struct lm_lockname *, struct file *, int gdlm_punlock(void *, struct lm_lockname *, struct file *,
struct file_lock *); struct file_lock *);
/* mount.c */
extern const struct lm_lockops gdlm_ops;
#endif #endif
...@@ -11,8 +11,6 @@ ...@@ -11,8 +11,6 @@
#include "lock_dlm.h" #include "lock_dlm.h"
extern struct lm_lockops gdlm_ops;
static int __init init_lock_dlm(void) static int __init init_lock_dlm(void)
{ {
int error; int error;
......
...@@ -12,8 +12,6 @@ ...@@ -12,8 +12,6 @@
#include "lock_dlm.h" #include "lock_dlm.h"
extern struct lm_lockops gdlm_ops;
static ssize_t proto_name_show(struct gdlm_ls *ls, char *buf) static ssize_t proto_name_show(struct gdlm_ls *ls, char *buf)
{ {
return sprintf(buf, "%s\n", gdlm_ops.lm_proto_name); return sprintf(buf, "%s\n", gdlm_ops.lm_proto_name);
......
...@@ -135,7 +135,15 @@ static void process_complete(struct gdlm_lock *lp) ...@@ -135,7 +135,15 @@ static void process_complete(struct gdlm_lock *lp)
lp->lksb.sb_status, lp->lockname.ln_type, lp->lksb.sb_status, lp->lockname.ln_type,
(unsigned long long)lp->lockname.ln_number, (unsigned long long)lp->lockname.ln_number,
lp->flags); lp->flags);
return; if (lp->lksb.sb_status == -EDEADLOCK &&
lp->ls->fsflags & LM_MFLAG_CONV_NODROP) {
lp->req = lp->cur;
acb.lc_ret |= LM_OUT_CONV_DEADLK;
if (lp->cur == DLM_LOCK_IV)
lp->lksb.sb_lkid = 0;
goto out;
} else
return;
} }
/* /*
......
...@@ -140,7 +140,7 @@ static int nolock_hold_lvb(void *lock, char **lvbp) ...@@ -140,7 +140,7 @@ static int nolock_hold_lvb(void *lock, char **lvbp)
struct nolock_lockspace *nl = lock; struct nolock_lockspace *nl = lock;
int error = 0; int error = 0;
*lvbp = kzalloc(nl->nl_lvb_size, GFP_KERNEL); *lvbp = kzalloc(nl->nl_lvb_size, GFP_NOFS);
if (!*lvbp) if (!*lvbp)
error = -ENOMEM; error = -ENOMEM;
......
...@@ -769,8 +769,8 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) ...@@ -769,8 +769,8 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm; sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm;
gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0); gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0);
reserved = calc_reserved(sdp); reserved = calc_reserved(sdp);
gfs2_assert_withdraw(sdp, sdp->sd_log_blks_reserved + tr->tr_reserved >= reserved);
unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved; unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved;
gfs2_assert_withdraw(sdp, unused >= 0);
atomic_add(unused, &sdp->sd_log_blks_free); atomic_add(unused, &sdp->sd_log_blks_free);
gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <= gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <=
sdp->sd_jdesc->jd_blocks); sdp->sd_jdesc->jd_blocks);
...@@ -779,6 +779,21 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) ...@@ -779,6 +779,21 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
} }
static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
{
struct list_head *head = &tr->tr_list_buf;
struct gfs2_bufdata *bd;
gfs2_log_lock(sdp);
while (!list_empty(head)) {
bd = list_entry(head->next, struct gfs2_bufdata, bd_list_tr);
list_del_init(&bd->bd_list_tr);
tr->tr_num_buf--;
}
gfs2_log_unlock(sdp);
gfs2_assert_warn(sdp, !tr->tr_num_buf);
}
/** /**
* gfs2_log_commit - Commit a transaction to the log * gfs2_log_commit - Commit a transaction to the log
* @sdp: the filesystem * @sdp: the filesystem
...@@ -790,7 +805,7 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) ...@@ -790,7 +805,7 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
{ {
log_refund(sdp, tr); log_refund(sdp, tr);
lops_incore_commit(sdp, tr); buf_lo_incore_commit(sdp, tr);
sdp->sd_vfs->s_dirt = 1; sdp->sd_vfs->s_dirt = 1;
up_read(&sdp->sd_log_flush_lock); up_read(&sdp->sd_log_flush_lock);
......
...@@ -152,21 +152,6 @@ out: ...@@ -152,21 +152,6 @@ out:
unlock_buffer(bd->bd_bh); unlock_buffer(bd->bd_bh);
} }
static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
{
struct list_head *head = &tr->tr_list_buf;
struct gfs2_bufdata *bd;
gfs2_log_lock(sdp);
while (!list_empty(head)) {
bd = list_entry(head->next, struct gfs2_bufdata, bd_list_tr);
list_del_init(&bd->bd_list_tr);
tr->tr_num_buf--;
}
gfs2_log_unlock(sdp);
gfs2_assert_warn(sdp, !tr->tr_num_buf);
}
static void buf_lo_before_commit(struct gfs2_sbd *sdp) static void buf_lo_before_commit(struct gfs2_sbd *sdp)
{ {
struct buffer_head *bh; struct buffer_head *bh;
...@@ -419,8 +404,10 @@ static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, ...@@ -419,8 +404,10 @@ static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
blkno = be64_to_cpu(*(__be64 *)(bh->b_data + offset)); blkno = be64_to_cpu(*(__be64 *)(bh->b_data + offset));
error = gfs2_revoke_add(sdp, blkno, start); error = gfs2_revoke_add(sdp, blkno, start);
if (error < 0) if (error < 0) {
brelse(bh);
return error; return error;
}
else if (error) else if (error)
sdp->sd_found_revokes++; sdp->sd_found_revokes++;
...@@ -737,7 +724,6 @@ static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) ...@@ -737,7 +724,6 @@ static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
const struct gfs2_log_operations gfs2_buf_lops = { const struct gfs2_log_operations gfs2_buf_lops = {
.lo_add = buf_lo_add, .lo_add = buf_lo_add,
.lo_incore_commit = buf_lo_incore_commit,
.lo_before_commit = buf_lo_before_commit, .lo_before_commit = buf_lo_before_commit,
.lo_after_commit = buf_lo_after_commit, .lo_after_commit = buf_lo_after_commit,
.lo_before_scan = buf_lo_before_scan, .lo_before_scan = buf_lo_before_scan,
...@@ -763,7 +749,6 @@ const struct gfs2_log_operations gfs2_rg_lops = { ...@@ -763,7 +749,6 @@ const struct gfs2_log_operations gfs2_rg_lops = {
const struct gfs2_log_operations gfs2_databuf_lops = { const struct gfs2_log_operations gfs2_databuf_lops = {
.lo_add = databuf_lo_add, .lo_add = databuf_lo_add,
.lo_incore_commit = buf_lo_incore_commit,
.lo_before_commit = databuf_lo_before_commit, .lo_before_commit = databuf_lo_before_commit,
.lo_after_commit = databuf_lo_after_commit, .lo_after_commit = databuf_lo_after_commit,
.lo_scan_elements = databuf_lo_scan_elements, .lo_scan_elements = databuf_lo_scan_elements,
......
/* /*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
* *
* This copyrighted material is made available to anyone wishing to use, * This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions * modify, copy, or redistribute it subject to the terms and conditions
...@@ -57,15 +57,6 @@ static inline void lops_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) ...@@ -57,15 +57,6 @@ static inline void lops_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
le->le_ops->lo_add(sdp, le); le->le_ops->lo_add(sdp, le);
} }
static inline void lops_incore_commit(struct gfs2_sbd *sdp,
struct gfs2_trans *tr)
{
int x;
for (x = 0; gfs2_log_ops[x]; x++)
if (gfs2_log_ops[x]->lo_incore_commit)
gfs2_log_ops[x]->lo_incore_commit(sdp, tr);
}
static inline void lops_before_commit(struct gfs2_sbd *sdp) static inline void lops_before_commit(struct gfs2_sbd *sdp)
{ {
int x; int x;
......
...@@ -89,6 +89,12 @@ static int __init init_gfs2_fs(void) ...@@ -89,6 +89,12 @@ static int __init init_gfs2_fs(void)
if (!gfs2_bufdata_cachep) if (!gfs2_bufdata_cachep)
goto fail; goto fail;
gfs2_rgrpd_cachep = kmem_cache_create("gfs2_rgrpd",
sizeof(struct gfs2_rgrpd),
0, 0, NULL);
if (!gfs2_rgrpd_cachep)
goto fail;
error = register_filesystem(&gfs2_fs_type); error = register_filesystem(&gfs2_fs_type);
if (error) if (error)
goto fail; goto fail;
...@@ -108,6 +114,9 @@ fail_unregister: ...@@ -108,6 +114,9 @@ fail_unregister:
fail: fail:
gfs2_glock_exit(); gfs2_glock_exit();
if (gfs2_rgrpd_cachep)
kmem_cache_destroy(gfs2_rgrpd_cachep);
if (gfs2_bufdata_cachep) if (gfs2_bufdata_cachep)
kmem_cache_destroy(gfs2_bufdata_cachep); kmem_cache_destroy(gfs2_bufdata_cachep);
...@@ -133,6 +142,7 @@ static void __exit exit_gfs2_fs(void) ...@@ -133,6 +142,7 @@ static void __exit exit_gfs2_fs(void)
unregister_filesystem(&gfs2_fs_type); unregister_filesystem(&gfs2_fs_type);
unregister_filesystem(&gfs2meta_fs_type); unregister_filesystem(&gfs2meta_fs_type);
kmem_cache_destroy(gfs2_rgrpd_cachep);
kmem_cache_destroy(gfs2_bufdata_cachep); kmem_cache_destroy(gfs2_bufdata_cachep);
kmem_cache_destroy(gfs2_inode_cachep); kmem_cache_destroy(gfs2_inode_cachep);
kmem_cache_destroy(gfs2_glock_cachep); kmem_cache_destroy(gfs2_glock_cachep);
......
/* /*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
* *
* This copyrighted material is made available to anyone wishing to use, * This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions * modify, copy, or redistribute it subject to the terms and conditions
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <linux/gfs2_ondisk.h> #include <linux/gfs2_ondisk.h>
#include <linux/lm_interface.h> #include <linux/lm_interface.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/pagevec.h>
#include "gfs2.h" #include "gfs2.h"
#include "incore.h" #include "incore.h"
...@@ -104,11 +103,9 @@ static int gfs2_writepage_common(struct page *page, ...@@ -104,11 +103,9 @@ static int gfs2_writepage_common(struct page *page,
loff_t i_size = i_size_read(inode); loff_t i_size = i_size_read(inode);
pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT; pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
unsigned offset; unsigned offset;
int ret = -EIO;
if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl))) if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl)))
goto out; goto out;
ret = 0;
if (current->journal_info) if (current->journal_info)
goto redirty; goto redirty;
/* Is the page fully outside i_size? (truncate in progress) */ /* Is the page fully outside i_size? (truncate in progress) */
...@@ -280,7 +277,7 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping, ...@@ -280,7 +277,7 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping,
int i; int i;
int ret; int ret;
ret = gfs2_trans_begin(sdp, nrblocks, 0); ret = gfs2_trans_begin(sdp, nrblocks, nrblocks);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -510,23 +507,26 @@ static int __gfs2_readpage(void *file, struct page *page) ...@@ -510,23 +507,26 @@ static int __gfs2_readpage(void *file, struct page *page)
static int gfs2_readpage(struct file *file, struct page *page) static int gfs2_readpage(struct file *file, struct page *page)
{ {
struct gfs2_inode *ip = GFS2_I(page->mapping->host); struct gfs2_inode *ip = GFS2_I(page->mapping->host);
struct gfs2_holder gh; struct gfs2_holder *gh;
int error; int error;
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh); gh = gfs2_glock_is_locked_by_me(ip->i_gl);
error = gfs2_glock_nq_atime(&gh); if (!gh) {
if (unlikely(error)) { gh = kmalloc(sizeof(struct gfs2_holder), GFP_NOFS);
if (!gh)
return -ENOBUFS;
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, gh);
unlock_page(page); unlock_page(page);
goto out; error = gfs2_glock_nq_atime(gh);
if (likely(error != 0))
goto out;
return AOP_TRUNCATED_PAGE;
} }
error = __gfs2_readpage(file, page); error = __gfs2_readpage(file, page);
gfs2_glock_dq(&gh); gfs2_glock_dq(gh);
out: out:
gfs2_holder_uninit(&gh); gfs2_holder_uninit(gh);
if (error == GLR_TRYFAILED) { kfree(gh);
yield();
return AOP_TRUNCATED_PAGE;
}
return error; return error;
} }
...@@ -648,15 +648,15 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, ...@@ -648,15 +648,15 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
if (alloc_required) { if (alloc_required) {
al = gfs2_alloc_get(ip); al = gfs2_alloc_get(ip);
if (!al) {
error = -ENOMEM;
goto out_unlock;
}
error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); error = gfs2_quota_lock_check(ip);
if (error) if (error)
goto out_alloc_put; goto out_alloc_put;
error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
if (error)
goto out_qunlock;
al->al_requested = data_blocks + ind_blocks; al->al_requested = data_blocks + ind_blocks;
error = gfs2_inplace_reserve(ip); error = gfs2_inplace_reserve(ip);
if (error) if (error)
...@@ -828,7 +828,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, ...@@ -828,7 +828,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
unsigned int to = from + len; unsigned int to = from + len;
int ret; int ret;
BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == 0); BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == NULL);
ret = gfs2_meta_inode_buffer(ip, &dibh); ret = gfs2_meta_inode_buffer(ip, &dibh);
if (unlikely(ret)) { if (unlikely(ret)) {
......
...@@ -43,7 +43,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) ...@@ -43,7 +43,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
struct gfs2_holder d_gh; struct gfs2_holder d_gh;
struct gfs2_inode *ip = NULL; struct gfs2_inode *ip = NULL;
int error; int error;
int had_lock=0; int had_lock = 0;
if (inode) { if (inode) {
if (is_bad_inode(inode)) if (is_bad_inode(inode))
...@@ -54,7 +54,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) ...@@ -54,7 +54,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
if (sdp->sd_args.ar_localcaching) if (sdp->sd_args.ar_localcaching)
goto valid; goto valid;
had_lock = gfs2_glock_is_locked_by_me(dip->i_gl); had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL);
if (!had_lock) { if (!had_lock) {
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
if (error) if (error)
......
...@@ -204,8 +204,6 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, ...@@ -204,8 +204,6 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb,
inode = gfs2_inode_lookup(sb, DT_UNKNOWN, inode = gfs2_inode_lookup(sb, DT_UNKNOWN,
inum->no_addr, inum->no_addr,
0, 0); 0, 0);
if (!inode)
goto fail;
if (IS_ERR(inode)) { if (IS_ERR(inode)) {
error = PTR_ERR(inode); error = PTR_ERR(inode);
goto fail; goto fail;
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include "glock.h" #include "glock.h"
#include "glops.h" #include "glops.h"
#include "inode.h" #include "inode.h"
#include "lm.h"
#include "log.h" #include "log.h"
#include "meta_io.h" #include "meta_io.h"
#include "quota.h" #include "quota.h"
...@@ -39,6 +38,7 @@ ...@@ -39,6 +38,7 @@
#include "util.h" #include "util.h"
#include "eaops.h" #include "eaops.h"
#include "ops_address.h" #include "ops_address.h"
#include "ops_inode.h"
/** /**
* gfs2_llseek - seek to a location in a file * gfs2_llseek - seek to a location in a file
...@@ -369,12 +369,9 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page) ...@@ -369,12 +369,9 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
if (al == NULL) if (al == NULL)
goto out_unlock; goto out_unlock;
ret = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); ret = gfs2_quota_lock_check(ip);
if (ret) if (ret)
goto out_alloc_put; goto out_alloc_put;
ret = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
if (ret)
goto out_quota_unlock;
al->al_requested = data_blocks + ind_blocks; al->al_requested = data_blocks + ind_blocks;
ret = gfs2_inplace_reserve(ip); ret = gfs2_inplace_reserve(ip);
if (ret) if (ret)
...@@ -596,6 +593,36 @@ static int gfs2_setlease(struct file *file, long arg, struct file_lock **fl) ...@@ -596,6 +593,36 @@ static int gfs2_setlease(struct file *file, long arg, struct file_lock **fl)
return generic_setlease(file, arg, fl); return generic_setlease(file, arg, fl);
} }
static int gfs2_lm_plock_get(struct gfs2_sbd *sdp, struct lm_lockname *name,
struct file *file, struct file_lock *fl)
{
int error = -EIO;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
error = sdp->sd_lockstruct.ls_ops->lm_plock_get(
sdp->sd_lockstruct.ls_lockspace, name, file, fl);
return error;
}
static int gfs2_lm_plock(struct gfs2_sbd *sdp, struct lm_lockname *name,
struct file *file, int cmd, struct file_lock *fl)
{
int error = -EIO;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
error = sdp->sd_lockstruct.ls_ops->lm_plock(
sdp->sd_lockstruct.ls_lockspace, name, file, cmd, fl);
return error;
}
static int gfs2_lm_punlock(struct gfs2_sbd *sdp, struct lm_lockname *name,
struct file *file, struct file_lock *fl)
{
int error = -EIO;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
error = sdp->sd_lockstruct.ls_ops->lm_punlock(
sdp->sd_lockstruct.ls_lockspace, name, file, fl);
return error;
}
/** /**
* gfs2_lock - acquire/release a posix lock on a file * gfs2_lock - acquire/release a posix lock on a file
* @file: the file pointer * @file: the file pointer
......
/* /*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
* *
* This copyrighted material is made available to anyone wishing to use, * This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions * modify, copy, or redistribute it subject to the terms and conditions
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "glock.h" #include "glock.h"
#include "glops.h" #include "glops.h"
#include "inode.h" #include "inode.h"
#include "lm.h"
#include "mount.h" #include "mount.h"
#include "ops_fstype.h" #include "ops_fstype.h"
#include "ops_dentry.h" #include "ops_dentry.h"
...@@ -363,6 +362,13 @@ static int map_journal_extents(struct gfs2_sbd *sdp) ...@@ -363,6 +362,13 @@ static int map_journal_extents(struct gfs2_sbd *sdp)
return rc; return rc;
} }
static void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp)
{
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
sdp->sd_lockstruct.ls_ops->lm_others_may_mount(
sdp->sd_lockstruct.ls_lockspace);
}
static int init_journal(struct gfs2_sbd *sdp, int undo) static int init_journal(struct gfs2_sbd *sdp, int undo)
{ {
struct gfs2_holder ji_gh; struct gfs2_holder ji_gh;
...@@ -542,7 +548,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo) ...@@ -542,7 +548,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
} }
ip = GFS2_I(sdp->sd_rindex); ip = GFS2_I(sdp->sd_rindex);
set_bit(GLF_STICKY, &ip->i_gl->gl_flags); set_bit(GLF_STICKY, &ip->i_gl->gl_flags);
sdp->sd_rindex_vn = ip->i_gl->gl_vn - 1; sdp->sd_rindex_uptodate = 0;
/* Read in the quota inode */ /* Read in the quota inode */
sdp->sd_quota_inode = gfs2_lookup_simple(sdp->sd_master_dir, "quota"); sdp->sd_quota_inode = gfs2_lookup_simple(sdp->sd_master_dir, "quota");
...@@ -704,6 +710,69 @@ fail: ...@@ -704,6 +710,69 @@ fail:
return error; return error;
} }
/**
* gfs2_lm_mount - mount a locking protocol
* @sdp: the filesystem
* @args: mount arguements
* @silent: if 1, don't complain if the FS isn't a GFS2 fs
*
* Returns: errno
*/
static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
{
char *proto = sdp->sd_proto_name;
char *table = sdp->sd_table_name;
int flags = LM_MFLAG_CONV_NODROP;
int error;
if (sdp->sd_args.ar_spectator)
flags |= LM_MFLAG_SPECTATOR;
fs_info(sdp, "Trying to join cluster \"%s\", \"%s\"\n", proto, table);
error = gfs2_mount_lockproto(proto, table, sdp->sd_args.ar_hostdata,
gfs2_glock_cb, sdp,
GFS2_MIN_LVB_SIZE, flags,
&sdp->sd_lockstruct, &sdp->sd_kobj);
if (error) {
fs_info(sdp, "can't mount proto=%s, table=%s, hostdata=%s\n",
proto, table, sdp->sd_args.ar_hostdata);
goto out;
}
if (gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lockspace) ||
gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_ops) ||
gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lvb_size >=
GFS2_MIN_LVB_SIZE)) {
gfs2_unmount_lockproto(&sdp->sd_lockstruct);
goto out;
}
if (sdp->sd_args.ar_spectator)
snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.s", table);
else
snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.%u", table,
sdp->sd_lockstruct.ls_jid);
fs_info(sdp, "Joined cluster. Now mounting FS...\n");
if ((sdp->sd_lockstruct.ls_flags & LM_LSFLAG_LOCAL) &&
!sdp->sd_args.ar_ignore_local_fs) {
sdp->sd_args.ar_localflocks = 1;
sdp->sd_args.ar_localcaching = 1;
}
out:
return error;
}
void gfs2_lm_unmount(struct gfs2_sbd *sdp)
{
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
gfs2_unmount_lockproto(&sdp->sd_lockstruct);
}
/** /**
* fill_super - Read in superblock * fill_super - Read in superblock
* @sb: The VFS superblock * @sb: The VFS superblock
...@@ -874,7 +943,6 @@ static struct super_block* get_gfs2_sb(const char *dev_name) ...@@ -874,7 +943,6 @@ static struct super_block* get_gfs2_sb(const char *dev_name)
{ {
struct kstat stat; struct kstat stat;
struct nameidata nd; struct nameidata nd;
struct file_system_type *fstype;
struct super_block *sb = NULL, *s; struct super_block *sb = NULL, *s;
int error; int error;
...@@ -886,8 +954,7 @@ static struct super_block* get_gfs2_sb(const char *dev_name) ...@@ -886,8 +954,7 @@ static struct super_block* get_gfs2_sb(const char *dev_name)
} }
error = vfs_getattr(nd.path.mnt, nd.path.dentry, &stat); error = vfs_getattr(nd.path.mnt, nd.path.dentry, &stat);
fstype = get_fs_type("gfs2"); list_for_each_entry(s, &gfs2_fs_type.fs_supers, s_instances) {
list_for_each_entry(s, &fstype->fs_supers, s_instances) {
if ((S_ISBLK(stat.mode) && s->s_dev == stat.rdev) || if ((S_ISBLK(stat.mode) && s->s_dev == stat.rdev) ||
(S_ISDIR(stat.mode) && (S_ISDIR(stat.mode) &&
s == nd.path.dentry->d_inode->i_sb)) { s == nd.path.dentry->d_inode->i_sb)) {
...@@ -931,7 +998,6 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags, ...@@ -931,7 +998,6 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags,
error = PTR_ERR(new); error = PTR_ERR(new);
goto error; goto error;
} }
module_put(fs_type->owner);
new->s_flags = flags; new->s_flags = flags;
strlcpy(new->s_id, sb->s_id, sizeof(new->s_id)); strlcpy(new->s_id, sb->s_id, sizeof(new->s_id));
sb_set_blocksize(new, sb->s_blocksize); sb_set_blocksize(new, sb->s_blocksize);
......
...@@ -200,15 +200,15 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, ...@@ -200,15 +200,15 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
if (alloc_required) { if (alloc_required) {
struct gfs2_alloc *al = gfs2_alloc_get(dip); struct gfs2_alloc *al = gfs2_alloc_get(dip);
if (!al) {
error = -ENOMEM;
goto out_gunlock;
}
error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); error = gfs2_quota_lock_check(dip);
if (error) if (error)
goto out_alloc; goto out_alloc;
error = gfs2_quota_check(dip, dip->i_inode.i_uid, dip->i_inode.i_gid);
if (error)
goto out_gunlock_q;
al->al_requested = sdp->sd_max_dirres; al->al_requested = sdp->sd_max_dirres;
error = gfs2_inplace_reserve(dip); error = gfs2_inplace_reserve(dip);
...@@ -716,15 +716,15 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, ...@@ -716,15 +716,15 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
if (alloc_required) { if (alloc_required) {
struct gfs2_alloc *al = gfs2_alloc_get(ndip); struct gfs2_alloc *al = gfs2_alloc_get(ndip);
if (!al) {
error = -ENOMEM;
goto out_gunlock;
}
error = gfs2_quota_lock(ndip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); error = gfs2_quota_lock_check(ndip);
if (error) if (error)
goto out_alloc; goto out_alloc;
error = gfs2_quota_check(ndip, ndip->i_inode.i_uid, ndip->i_inode.i_gid);
if (error)
goto out_gunlock_q;
al->al_requested = sdp->sd_max_dirres; al->al_requested = sdp->sd_max_dirres;
error = gfs2_inplace_reserve(ndip); error = gfs2_inplace_reserve(ndip);
...@@ -898,7 +898,7 @@ static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd) ...@@ -898,7 +898,7 @@ static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd)
int error; int error;
int unlock = 0; int unlock = 0;
if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) { if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
if (error) if (error)
return error; return error;
...@@ -953,7 +953,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) ...@@ -953,7 +953,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
if (!(attr->ia_valid & ATTR_GID) || ogid == ngid) if (!(attr->ia_valid & ATTR_GID) || ogid == ngid)
ogid = ngid = NO_QUOTA_CHANGE; ogid = ngid = NO_QUOTA_CHANGE;
gfs2_alloc_get(ip); if (!gfs2_alloc_get(ip))
return -ENOMEM;
error = gfs2_quota_lock(ip, nuid, ngid); error = gfs2_quota_lock(ip, nuid, ngid);
if (error) if (error)
...@@ -981,8 +982,9 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) ...@@ -981,8 +982,9 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
brelse(dibh); brelse(dibh);
if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
gfs2_quota_change(ip, -ip->i_di.di_blocks, ouid, ogid); u64 blocks = gfs2_get_inode_blocks(&ip->i_inode);
gfs2_quota_change(ip, ip->i_di.di_blocks, nuid, ngid); gfs2_quota_change(ip, -blocks, ouid, ogid);
gfs2_quota_change(ip, blocks, nuid, ngid);
} }
out_end_trans: out_end_trans:
...@@ -1064,7 +1066,7 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, ...@@ -1064,7 +1066,7 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
int error; int error;
int unlock = 0; int unlock = 0;
if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) { if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
if (error) if (error)
return error; return error;
...@@ -1148,16 +1150,6 @@ const struct inode_operations gfs2_file_iops = { ...@@ -1148,16 +1150,6 @@ const struct inode_operations gfs2_file_iops = {
.removexattr = gfs2_removexattr, .removexattr = gfs2_removexattr,
}; };
const struct inode_operations gfs2_dev_iops = {
.permission = gfs2_permission,
.setattr = gfs2_setattr,
.getattr = gfs2_getattr,
.setxattr = gfs2_setxattr,
.getxattr = gfs2_getxattr,
.listxattr = gfs2_listxattr,
.removexattr = gfs2_removexattr,
};
const struct inode_operations gfs2_dir_iops = { const struct inode_operations gfs2_dir_iops = {
.create = gfs2_create, .create = gfs2_create,
.lookup = gfs2_lookup, .lookup = gfs2_lookup,
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
extern const struct inode_operations gfs2_file_iops; extern const struct inode_operations gfs2_file_iops;
extern const struct inode_operations gfs2_dir_iops; extern const struct inode_operations gfs2_dir_iops;
extern const struct inode_operations gfs2_symlink_iops; extern const struct inode_operations gfs2_symlink_iops;
extern const struct inode_operations gfs2_dev_iops;
extern const struct file_operations gfs2_file_fops; extern const struct file_operations gfs2_file_fops;
extern const struct file_operations gfs2_dir_fops; extern const struct file_operations gfs2_dir_fops;
extern const struct file_operations gfs2_file_fops_nolock; extern const struct file_operations gfs2_file_fops_nolock;
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "incore.h" #include "incore.h"
#include "glock.h" #include "glock.h"
#include "inode.h" #include "inode.h"
#include "lm.h"
#include "log.h" #include "log.h"
#include "mount.h" #include "mount.h"
#include "ops_super.h" #include "ops_super.h"
......
...@@ -94,7 +94,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id, ...@@ -94,7 +94,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id,
struct gfs2_quota_data *qd; struct gfs2_quota_data *qd;
int error; int error;
qd = kzalloc(sizeof(struct gfs2_quota_data), GFP_KERNEL); qd = kzalloc(sizeof(struct gfs2_quota_data), GFP_NOFS);
if (!qd) if (!qd)
return -ENOMEM; return -ENOMEM;
...@@ -616,16 +616,9 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, ...@@ -616,16 +616,9 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
s64 value; s64 value;
int err = -EIO; int err = -EIO;
if (gfs2_is_stuffed(ip)) { if (gfs2_is_stuffed(ip))
struct gfs2_alloc *al = NULL;
al = gfs2_alloc_get(ip);
/* just request 1 blk */
al->al_requested = 1;
gfs2_inplace_reserve(ip);
gfs2_unstuff_dinode(ip, NULL); gfs2_unstuff_dinode(ip, NULL);
gfs2_inplace_release(ip);
gfs2_alloc_put(ip);
}
page = grab_cache_page(mapping, index); page = grab_cache_page(mapping, index);
if (!page) if (!page)
return -ENOMEM; return -ENOMEM;
...@@ -690,14 +683,14 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) ...@@ -690,14 +683,14 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
unsigned int qx, x; unsigned int qx, x;
struct gfs2_quota_data *qd; struct gfs2_quota_data *qd;
loff_t offset; loff_t offset;
unsigned int nalloc = 0; unsigned int nalloc = 0, blocks;
struct gfs2_alloc *al = NULL; struct gfs2_alloc *al = NULL;
int error; int error;
gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota), gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
&data_blocks, &ind_blocks); &data_blocks, &ind_blocks);
ghs = kcalloc(num_qd, sizeof(struct gfs2_holder), GFP_KERNEL); ghs = kcalloc(num_qd, sizeof(struct gfs2_holder), GFP_NOFS);
if (!ghs) if (!ghs)
return -ENOMEM; return -ENOMEM;
...@@ -727,30 +720,33 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) ...@@ -727,30 +720,33 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
nalloc++; nalloc++;
} }
if (nalloc) { al = gfs2_alloc_get(ip);
al = gfs2_alloc_get(ip); if (!al) {
error = -ENOMEM;
goto out_gunlock;
}
/*
* 1 blk for unstuffing inode if stuffed. We add this extra
* block to the reservation unconditionally. If the inode
* doesn't need unstuffing, the block will be released to the
* rgrp since it won't be allocated during the transaction
*/
al->al_requested = 1;
/* +1 in the end for block requested above for unstuffing */
blocks = num_qd * data_blocks + RES_DINODE + num_qd + 1;
al->al_requested = nalloc * (data_blocks + ind_blocks); if (nalloc)
al->al_requested += nalloc * (data_blocks + ind_blocks);
error = gfs2_inplace_reserve(ip);
if (error)
goto out_alloc;
error = gfs2_inplace_reserve(ip); if (nalloc)
if (error) blocks += al->al_rgd->rd_length + nalloc * ind_blocks + RES_STATFS;
goto out_alloc;
error = gfs2_trans_begin(sdp, blocks, 0);
error = gfs2_trans_begin(sdp, if (error)
al->al_rgd->rd_length + goto out_ipres;
num_qd * data_blocks +
nalloc * ind_blocks +
RES_DINODE + num_qd +
RES_STATFS, 0);
if (error)
goto out_ipres;
} else {
error = gfs2_trans_begin(sdp,
num_qd * data_blocks +
RES_DINODE + num_qd, 0);
if (error)
goto out_gunlock;
}
for (x = 0; x < num_qd; x++) { for (x = 0; x < num_qd; x++) {
qd = qda[x]; qd = qda[x];
...@@ -769,11 +765,9 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) ...@@ -769,11 +765,9 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
out_end_trans: out_end_trans:
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
out_ipres: out_ipres:
if (nalloc) gfs2_inplace_release(ip);
gfs2_inplace_release(ip);
out_alloc: out_alloc:
if (nalloc) gfs2_alloc_put(ip);
gfs2_alloc_put(ip);
out_gunlock: out_gunlock:
gfs2_glock_dq_uninit(&i_gh); gfs2_glock_dq_uninit(&i_gh);
out: out:
...@@ -1124,12 +1118,12 @@ int gfs2_quota_init(struct gfs2_sbd *sdp) ...@@ -1124,12 +1118,12 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
error = -ENOMEM; error = -ENOMEM;
sdp->sd_quota_bitmap = kcalloc(sdp->sd_quota_chunks, sdp->sd_quota_bitmap = kcalloc(sdp->sd_quota_chunks,
sizeof(unsigned char *), GFP_KERNEL); sizeof(unsigned char *), GFP_NOFS);
if (!sdp->sd_quota_bitmap) if (!sdp->sd_quota_bitmap)
return error; return error;
for (x = 0; x < sdp->sd_quota_chunks; x++) { for (x = 0; x < sdp->sd_quota_chunks; x++) {
sdp->sd_quota_bitmap[x] = kzalloc(PAGE_SIZE, GFP_KERNEL); sdp->sd_quota_bitmap[x] = kzalloc(PAGE_SIZE, GFP_NOFS);
if (!sdp->sd_quota_bitmap[x]) if (!sdp->sd_quota_bitmap[x])
goto fail; goto fail;
} }
......
...@@ -32,4 +32,21 @@ int gfs2_quota_init(struct gfs2_sbd *sdp); ...@@ -32,4 +32,21 @@ int gfs2_quota_init(struct gfs2_sbd *sdp);
void gfs2_quota_scan(struct gfs2_sbd *sdp); void gfs2_quota_scan(struct gfs2_sbd *sdp);
void gfs2_quota_cleanup(struct gfs2_sbd *sdp); void gfs2_quota_cleanup(struct gfs2_sbd *sdp);
static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
int ret;
if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
return 0;
ret = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
if (ret)
return ret;
if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
return 0;
ret = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
if (ret)
gfs2_quota_unlock(ip);
return ret;
}
#endif /* __QUOTA_DOT_H__ */ #endif /* __QUOTA_DOT_H__ */
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include "bmap.h" #include "bmap.h"
#include "glock.h" #include "glock.h"
#include "glops.h" #include "glops.h"
#include "lm.h"
#include "lops.h" #include "lops.h"
#include "meta_io.h" #include "meta_io.h"
#include "recovery.h" #include "recovery.h"
...@@ -69,7 +68,7 @@ int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where) ...@@ -69,7 +68,7 @@ int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where)
return 0; return 0;
} }
rr = kmalloc(sizeof(struct gfs2_revoke_replay), GFP_KERNEL); rr = kmalloc(sizeof(struct gfs2_revoke_replay), GFP_NOFS);
if (!rr) if (!rr)
return -ENOMEM; return -ENOMEM;
...@@ -150,7 +149,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk, ...@@ -150,7 +149,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
struct gfs2_log_header_host *head) struct gfs2_log_header_host *head)
{ {
struct buffer_head *bh; struct buffer_head *bh;
struct gfs2_log_header_host lh; struct gfs2_log_header_host uninitialized_var(lh);
const u32 nothing = 0; const u32 nothing = 0;
u32 hash; u32 hash;
int error; int error;
...@@ -425,6 +424,16 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea ...@@ -425,6 +424,16 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea
return error; return error;
} }
static void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,
unsigned int message)
{
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
sdp->sd_lockstruct.ls_ops->lm_recovery_done(
sdp->sd_lockstruct.ls_lockspace, jid, message);
}
/** /**
* gfs2_recover_journal - recovery a given journal * gfs2_recover_journal - recovery a given journal
* @jd: the struct gfs2_jdesc describing the journal * @jd: the struct gfs2_jdesc describing the journal
......
This diff is collapsed.
/* /*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
* *
* This copyrighted material is made available to anyone wishing to use, * This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions * modify, copy, or redistribute it subject to the terms and conditions
...@@ -46,8 +46,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip); ...@@ -46,8 +46,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip);
unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block); unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block);
u64 gfs2_alloc_data(struct gfs2_inode *ip); u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n);
u64 gfs2_alloc_meta(struct gfs2_inode *ip);
u64 gfs2_alloc_di(struct gfs2_inode *ip, u64 *generation); u64 gfs2_alloc_di(struct gfs2_inode *ip, u64 *generation);
void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen); void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);
...@@ -64,8 +63,7 @@ struct gfs2_rgrp_list { ...@@ -64,8 +63,7 @@ struct gfs2_rgrp_list {
void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist, void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist,
u64 block); u64 block);
void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state, void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state);
int flags);
void gfs2_rlist_free(struct gfs2_rgrp_list *rlist); void gfs2_rlist_free(struct gfs2_rgrp_list *rlist);
u64 gfs2_ri_total(struct gfs2_sbd *sdp); u64 gfs2_ri_total(struct gfs2_sbd *sdp);
......
...@@ -210,7 +210,7 @@ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) ...@@ -210,7 +210,7 @@ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector)
struct page *page; struct page *page;
struct bio *bio; struct bio *bio;
page = alloc_page(GFP_KERNEL); page = alloc_page(GFP_NOFS);
if (unlikely(!page)) if (unlikely(!page))
return -ENOBUFS; return -ENOBUFS;
...@@ -218,7 +218,7 @@ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) ...@@ -218,7 +218,7 @@ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector)
ClearPageDirty(page); ClearPageDirty(page);
lock_page(page); lock_page(page);
bio = bio_alloc(GFP_KERNEL, 1); bio = bio_alloc(GFP_NOFS, 1);
if (unlikely(!bio)) { if (unlikely(!bio)) {
__free_page(page); __free_page(page);
return -ENOBUFS; return -ENOBUFS;
...@@ -316,6 +316,7 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) ...@@ -316,6 +316,7 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent)
sdp->sd_heightsize[x] = space; sdp->sd_heightsize[x] = space;
} }
sdp->sd_max_height = x; sdp->sd_max_height = x;
sdp->sd_heightsize[x] = ~0;
gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT); gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT);
sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize - sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize -
...@@ -334,6 +335,7 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) ...@@ -334,6 +335,7 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent)
sdp->sd_jheightsize[x] = space; sdp->sd_jheightsize[x] = space;
} }
sdp->sd_max_jheight = x; sdp->sd_max_jheight = x;
sdp->sd_jheightsize[x] = ~0;
gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT); gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT);
return 0; return 0;
......
...@@ -17,6 +17,7 @@ void gfs2_tune_init(struct gfs2_tune *gt); ...@@ -17,6 +17,7 @@ void gfs2_tune_init(struct gfs2_tune *gt);
int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent); int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent);
int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent); int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent);
int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector); int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector);
void gfs2_lm_unmount(struct gfs2_sbd *sdp);
static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp) static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)
{ {
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include "gfs2.h" #include "gfs2.h"
#include "incore.h" #include "incore.h"
#include "lm.h"
#include "sys.h" #include "sys.h"
#include "super.h" #include "super.h"
#include "glock.h" #include "glock.h"
...@@ -328,15 +327,9 @@ static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf) \ ...@@ -328,15 +327,9 @@ static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf) \
} \ } \
static struct counters_attr counters_attr_##name = __ATTR_RO(name) static struct counters_attr counters_attr_##name = __ATTR_RO(name)
COUNTERS_ATTR(glock_count, "%u\n");
COUNTERS_ATTR(glock_held_count, "%u\n");
COUNTERS_ATTR(inode_count, "%u\n");
COUNTERS_ATTR(reclaimed, "%u\n"); COUNTERS_ATTR(reclaimed, "%u\n");
static struct attribute *counters_attrs[] = { static struct attribute *counters_attrs[] = {
&counters_attr_glock_count.attr,
&counters_attr_glock_held_count.attr,
&counters_attr_inode_count.attr,
&counters_attr_reclaimed.attr, &counters_attr_reclaimed.attr,
NULL, NULL,
}; };
......
...@@ -146,30 +146,25 @@ void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) ...@@ -146,30 +146,25 @@ void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
lops_add(sdp, &bd->bd_le); lops_add(sdp, &bd->bd_le);
} }
void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno) void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len)
{ {
struct gfs2_bufdata *bd; struct gfs2_bufdata *bd, *tmp;
int found = 0; struct gfs2_trans *tr = current->journal_info;
unsigned int n = len;
gfs2_log_lock(sdp); gfs2_log_lock(sdp);
list_for_each_entry_safe(bd, tmp, &sdp->sd_log_le_revoke, bd_le.le_list) {
list_for_each_entry(bd, &sdp->sd_log_le_revoke, bd_le.le_list) { if ((bd->bd_blkno >= blkno) && (bd->bd_blkno < (blkno + len))) {
if (bd->bd_blkno == blkno) {
list_del_init(&bd->bd_le.le_list); list_del_init(&bd->bd_le.le_list);
gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke); gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke);
sdp->sd_log_num_revoke--; sdp->sd_log_num_revoke--;
found = 1; kmem_cache_free(gfs2_bufdata_cachep, bd);
break; tr->tr_num_revoke_rm++;
if (--n == 0)
break;
} }
} }
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
if (found) {
struct gfs2_trans *tr = current->journal_info;
kmem_cache_free(gfs2_bufdata_cachep, bd);
tr->tr_num_revoke_rm++;
}
} }
void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd) void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd)
......
...@@ -32,7 +32,7 @@ void gfs2_trans_end(struct gfs2_sbd *sdp); ...@@ -32,7 +32,7 @@ void gfs2_trans_end(struct gfs2_sbd *sdp);
void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta); void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta);
void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd); void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno); void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len);
void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd); void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd);
#endif /* __TRANS_DOT_H__ */ #endif /* __TRANS_DOT_H__ */
...@@ -19,12 +19,12 @@ ...@@ -19,12 +19,12 @@
#include "gfs2.h" #include "gfs2.h"
#include "incore.h" #include "incore.h"
#include "glock.h" #include "glock.h"
#include "lm.h"
#include "util.h" #include "util.h"
struct kmem_cache *gfs2_glock_cachep __read_mostly; struct kmem_cache *gfs2_glock_cachep __read_mostly;
struct kmem_cache *gfs2_inode_cachep __read_mostly; struct kmem_cache *gfs2_inode_cachep __read_mostly;
struct kmem_cache *gfs2_bufdata_cachep __read_mostly; struct kmem_cache *gfs2_bufdata_cachep __read_mostly;
struct kmem_cache *gfs2_rgrpd_cachep __read_mostly;
void gfs2_assert_i(struct gfs2_sbd *sdp) void gfs2_assert_i(struct gfs2_sbd *sdp)
{ {
...@@ -32,6 +32,28 @@ void gfs2_assert_i(struct gfs2_sbd *sdp) ...@@ -32,6 +32,28 @@ void gfs2_assert_i(struct gfs2_sbd *sdp)
sdp->sd_fsname); sdp->sd_fsname);
} }
int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...)
{
va_list args;
if (test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags))
return 0;
va_start(args, fmt);
vprintk(fmt, args);
va_end(args);
fs_err(sdp, "about to withdraw this file system\n");
BUG_ON(sdp->sd_args.ar_debug);
fs_err(sdp, "telling LM to withdraw\n");
gfs2_withdraw_lockproto(&sdp->sd_lockstruct);
fs_err(sdp, "withdrawn\n");
dump_stack();
return -1;
}
/** /**
* gfs2_assert_withdraw_i - Cause the machine to withdraw if @assertion is false * gfs2_assert_withdraw_i - Cause the machine to withdraw if @assertion is false
* Returns: -1 if this call withdrew the machine, * Returns: -1 if this call withdrew the machine,
......
...@@ -147,6 +147,7 @@ gfs2_io_error_bh_i((sdp), (bh), __FUNCTION__, __FILE__, __LINE__); ...@@ -147,6 +147,7 @@ gfs2_io_error_bh_i((sdp), (bh), __FUNCTION__, __FILE__, __LINE__);
extern struct kmem_cache *gfs2_glock_cachep; extern struct kmem_cache *gfs2_glock_cachep;
extern struct kmem_cache *gfs2_inode_cachep; extern struct kmem_cache *gfs2_inode_cachep;
extern struct kmem_cache *gfs2_bufdata_cachep; extern struct kmem_cache *gfs2_bufdata_cachep;
extern struct kmem_cache *gfs2_rgrpd_cachep;
static inline unsigned int gfs2_tune_get_i(struct gfs2_tune *gt, static inline unsigned int gfs2_tune_get_i(struct gfs2_tune *gt,
unsigned int *p) unsigned int *p)
...@@ -163,6 +164,7 @@ gfs2_tune_get_i(&(sdp)->sd_tune, &(sdp)->sd_tune.field) ...@@ -163,6 +164,7 @@ gfs2_tune_get_i(&(sdp)->sd_tune, &(sdp)->sd_tune.field)
void gfs2_icbit_munge(struct gfs2_sbd *sdp, unsigned char **bitmap, void gfs2_icbit_munge(struct gfs2_sbd *sdp, unsigned char **bitmap,
unsigned int bit, int new_value); unsigned int bit, int new_value);
int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...);
#endif /* __UTIL_DOT_H__ */ #endif /* __UTIL_DOT_H__ */
...@@ -21,9 +21,15 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data); ...@@ -21,9 +21,15 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
* modify the filesystem. The lock module shouldn't assign a journal to the FS * modify the filesystem. The lock module shouldn't assign a journal to the FS
* mount. It shouldn't send recovery callbacks to the FS mount. If the node * mount. It shouldn't send recovery callbacks to the FS mount. If the node
* dies or withdraws, all locks can be wiped immediately. * dies or withdraws, all locks can be wiped immediately.
*
* LM_MFLAG_CONV_NODROP
* Do not allow the dlm to internally resolve conversion deadlocks by demoting
* the lock to unlocked and then reacquiring it in the requested mode. Instead,
* it should cancel the request and return LM_OUT_CONV_DEADLK.
*/ */
#define LM_MFLAG_SPECTATOR 0x00000001 #define LM_MFLAG_SPECTATOR 0x00000001
#define LM_MFLAG_CONV_NODROP 0x00000002
/* /*
* lm_lockstruct flags * lm_lockstruct flags
...@@ -110,6 +116,9 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data); ...@@ -110,6 +116,9 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
* *
* LM_OUT_ASYNC * LM_OUT_ASYNC
* The result of the request will be returned in an LM_CB_ASYNC callback. * The result of the request will be returned in an LM_CB_ASYNC callback.
*
* LM_OUT_CONV_DEADLK
* The lock request was canceled do to a conversion deadlock.
*/ */
#define LM_OUT_ST_MASK 0x00000003 #define LM_OUT_ST_MASK 0x00000003
...@@ -117,6 +126,7 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data); ...@@ -117,6 +126,7 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
#define LM_OUT_CANCELED 0x00000008 #define LM_OUT_CANCELED 0x00000008
#define LM_OUT_ASYNC 0x00000080 #define LM_OUT_ASYNC 0x00000080
#define LM_OUT_ERROR 0x00000100 #define LM_OUT_ERROR 0x00000100
#define LM_OUT_CONV_DEADLK 0x00000200
/* /*
* lm_callback_t types * lm_callback_t types
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment