mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 13:11:40 +00:00
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 ...
This commit is contained in:
commit
ef38ff9d37
@ -1,6 +1,6 @@
|
||||
config GFS2_FS
|
||||
tristate "GFS2 file system support"
|
||||
depends on EXPERIMENTAL
|
||||
depends on EXPERIMENTAL && (64BIT || (LSF && LBD))
|
||||
select FS_POSIX_ACL
|
||||
select CRC32
|
||||
help
|
||||
|
@ -1,6 +1,6 @@
|
||||
obj-$(CONFIG_GFS2_FS) += gfs2.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 \
|
||||
ops_fstype.o ops_inode.o ops_super.o quota.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,
|
||||
goto out;
|
||||
|
||||
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;
|
||||
if (!er.er_data)
|
||||
goto out;
|
||||
@ -222,7 +222,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip)
|
||||
return error;
|
||||
}
|
||||
|
||||
clone = posix_acl_clone(acl, GFP_KERNEL);
|
||||
clone = posix_acl_clone(acl, GFP_NOFS);
|
||||
error = -ENOMEM;
|
||||
if (!clone)
|
||||
goto out;
|
||||
@ -272,7 +272,7 @@ int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
|
||||
if (!acl)
|
||||
return gfs2_setattr_simple(ip, attr);
|
||||
|
||||
clone = posix_acl_clone(acl, GFP_KERNEL);
|
||||
clone = posix_acl_clone(acl, GFP_NOFS);
|
||||
error = -ENOMEM;
|
||||
if (!clone)
|
||||
goto out;
|
||||
|
682
fs/gfs2/bmap.c
682
fs/gfs2/bmap.c
@ -33,6 +33,7 @@
|
||||
* keep it small.
|
||||
*/
|
||||
struct metapath {
|
||||
struct buffer_head *mp_bh[GFS2_MAX_META_HEIGHT];
|
||||
__u16 mp_list[GFS2_MAX_META_HEIGHT];
|
||||
};
|
||||
|
||||
@ -135,9 +136,10 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
|
||||
/* Get a free block, fill it with the stuffed data,
|
||||
and write it out to disk */
|
||||
|
||||
unsigned int n = 1;
|
||||
block = gfs2_alloc_block(ip, &n);
|
||||
if (isdir) {
|
||||
block = gfs2_alloc_meta(ip);
|
||||
|
||||
gfs2_trans_add_unrevoke(GFS2_SB(&ip->i_inode), block, 1);
|
||||
error = gfs2_dir_get_new_buffer(ip, block, &bh);
|
||||
if (error)
|
||||
goto out_brelse;
|
||||
@ -145,8 +147,6 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
|
||||
dibh, sizeof(struct gfs2_dinode));
|
||||
brelse(bh);
|
||||
} else {
|
||||
block = gfs2_alloc_data(ip);
|
||||
|
||||
error = gfs2_unstuffer_page(ip, dibh, block, page);
|
||||
if (error)
|
||||
goto out_brelse;
|
||||
@ -161,12 +161,11 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
|
||||
|
||||
if (ip->i_di.di_size) {
|
||||
*(__be64 *)(di + 1) = cpu_to_be64(block);
|
||||
ip->i_di.di_blocks++;
|
||||
gfs2_set_inode_blocks(&ip->i_inode);
|
||||
di->di_blocks = cpu_to_be64(ip->i_di.di_blocks);
|
||||
gfs2_add_inode_blocks(&ip->i_inode, 1);
|
||||
di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
|
||||
}
|
||||
|
||||
ip->i_di.di_height = 1;
|
||||
ip->i_height = 1;
|
||||
di->di_height = cpu_to_be16(1);
|
||||
|
||||
out_brelse:
|
||||
@ -176,114 +175,13 @@ out:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* calc_tree_height - Calculate the height of a metadata tree
|
||||
* @ip: The GFS2 inode
|
||||
* @size: The proposed size of the file
|
||||
*
|
||||
* Work out how tall a metadata tree needs to be in order to accommodate a
|
||||
* file of a particular size. If size is less than the current size of
|
||||
* the inode, then the current size of the inode is used instead of the
|
||||
* supplied one.
|
||||
*
|
||||
* Returns: the height the tree should be
|
||||
*/
|
||||
|
||||
static unsigned int calc_tree_height(struct gfs2_inode *ip, u64 size)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
u64 *arr;
|
||||
unsigned int max, height;
|
||||
|
||||
if (ip->i_di.di_size > size)
|
||||
size = ip->i_di.di_size;
|
||||
|
||||
if (gfs2_is_dir(ip)) {
|
||||
arr = sdp->sd_jheightsize;
|
||||
max = sdp->sd_max_jheight;
|
||||
} else {
|
||||
arr = sdp->sd_heightsize;
|
||||
max = sdp->sd_max_height;
|
||||
}
|
||||
|
||||
for (height = 0; height < max; height++)
|
||||
if (arr[height] >= size)
|
||||
break;
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* build_height - Build a metadata tree of the requested height
|
||||
* @ip: The GFS2 inode
|
||||
* @height: The height to build to
|
||||
*
|
||||
*
|
||||
* Returns: errno
|
||||
*/
|
||||
|
||||
static int build_height(struct inode *inode, unsigned height)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
unsigned new_height = height - ip->i_di.di_height;
|
||||
struct buffer_head *dibh;
|
||||
struct buffer_head *blocks[GFS2_MAX_META_HEIGHT];
|
||||
struct gfs2_dinode *di;
|
||||
int error;
|
||||
__be64 *bp;
|
||||
u64 bn;
|
||||
unsigned n;
|
||||
|
||||
if (height <= ip->i_di.di_height)
|
||||
return 0;
|
||||
|
||||
error = gfs2_meta_inode_buffer(ip, &dibh);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
for(n = 0; n < new_height; n++) {
|
||||
bn = gfs2_alloc_meta(ip);
|
||||
blocks[n] = gfs2_meta_new(ip->i_gl, bn);
|
||||
gfs2_trans_add_bh(ip->i_gl, blocks[n], 1);
|
||||
}
|
||||
|
||||
n = 0;
|
||||
bn = blocks[0]->b_blocknr;
|
||||
if (new_height > 1) {
|
||||
for(; n < new_height-1; n++) {
|
||||
gfs2_metatype_set(blocks[n], GFS2_METATYPE_IN,
|
||||
GFS2_FORMAT_IN);
|
||||
gfs2_buffer_clear_tail(blocks[n],
|
||||
sizeof(struct gfs2_meta_header));
|
||||
bp = (__be64 *)(blocks[n]->b_data +
|
||||
sizeof(struct gfs2_meta_header));
|
||||
*bp = cpu_to_be64(blocks[n+1]->b_blocknr);
|
||||
brelse(blocks[n]);
|
||||
blocks[n] = NULL;
|
||||
}
|
||||
}
|
||||
gfs2_metatype_set(blocks[n], GFS2_METATYPE_IN, GFS2_FORMAT_IN);
|
||||
gfs2_buffer_copy_tail(blocks[n], sizeof(struct gfs2_meta_header),
|
||||
dibh, sizeof(struct gfs2_dinode));
|
||||
brelse(blocks[n]);
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
di = (struct gfs2_dinode *)dibh->b_data;
|
||||
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
|
||||
*(__be64 *)(di + 1) = cpu_to_be64(bn);
|
||||
ip->i_di.di_height += new_height;
|
||||
ip->i_di.di_blocks += new_height;
|
||||
gfs2_set_inode_blocks(&ip->i_inode);
|
||||
di->di_height = cpu_to_be16(ip->i_di.di_height);
|
||||
di->di_blocks = cpu_to_be64(ip->i_di.di_blocks);
|
||||
brelse(dibh);
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_metapath - Find path through the metadata tree
|
||||
* @ip: The inode pointer
|
||||
* @sdp: The superblock
|
||||
* @mp: The metapath to return the result in
|
||||
* @block: The disk block to look up
|
||||
* @height: The pre-calculated height of the metadata tree
|
||||
*
|
||||
* This routine returns a struct metapath structure that defines a path
|
||||
* through the metadata of inode "ip" to get to block "block".
|
||||
@ -338,21 +236,29 @@ static int build_height(struct inode *inode, unsigned height)
|
||||
*
|
||||
*/
|
||||
|
||||
static void find_metapath(struct gfs2_inode *ip, u64 block,
|
||||
struct metapath *mp)
|
||||
static void find_metapath(const struct gfs2_sbd *sdp, u64 block,
|
||||
struct metapath *mp, unsigned int height)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
u64 b = block;
|
||||
unsigned int i;
|
||||
|
||||
for (i = ip->i_di.di_height; i--;)
|
||||
mp->mp_list[i] = do_div(b, sdp->sd_inptrs);
|
||||
for (i = height; i--;)
|
||||
mp->mp_list[i] = do_div(block, sdp->sd_inptrs);
|
||||
|
||||
}
|
||||
|
||||
static inline unsigned int zero_metapath_length(const struct metapath *mp,
|
||||
unsigned height)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < height - 1; i++) {
|
||||
if (mp->mp_list[i] != 0)
|
||||
return i;
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* metapointer - Return pointer to start of metadata in a buffer
|
||||
* @bh: The buffer
|
||||
* @height: The metadata height (0 = dinode)
|
||||
* @mp: The metapath
|
||||
*
|
||||
@ -361,93 +267,302 @@ static void find_metapath(struct gfs2_inode *ip, u64 block,
|
||||
* metadata tree.
|
||||
*/
|
||||
|
||||
static inline __be64 *metapointer(struct buffer_head *bh, int *boundary,
|
||||
unsigned int height, const struct metapath *mp)
|
||||
static inline __be64 *metapointer(unsigned int height, const struct metapath *mp)
|
||||
{
|
||||
struct buffer_head *bh = mp->mp_bh[height];
|
||||
unsigned int head_size = (height > 0) ?
|
||||
sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode);
|
||||
__be64 *ptr;
|
||||
*boundary = 0;
|
||||
ptr = ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height];
|
||||
if (ptr + 1 == (__be64 *)(bh->b_data + bh->b_size))
|
||||
*boundary = 1;
|
||||
return ptr;
|
||||
return ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height];
|
||||
}
|
||||
|
||||
/**
|
||||
* lookup_block - Get the next metadata block in metadata tree
|
||||
* @ip: The GFS2 inode
|
||||
* @bh: Buffer containing the pointers to metadata blocks
|
||||
* @height: The height of the tree (0 = dinode)
|
||||
* lookup_metapath - Walk the metadata tree to a specific point
|
||||
* @ip: The inode
|
||||
* @mp: The metapath
|
||||
* @create: Non-zero if we may create a new meatdata block
|
||||
* @new: Used to indicate if we did create a new metadata block
|
||||
* @block: the returned disk block number
|
||||
*
|
||||
* Given a metatree, complete to a particular height, checks to see if the next
|
||||
* height of the tree exists. If not the next height of the tree is created.
|
||||
* The block number of the next height of the metadata tree is returned.
|
||||
* Assumes that the inode's buffer has already been looked up and
|
||||
* hooked onto mp->mp_bh[0] and that the metapath has been initialised
|
||||
* by find_metapath().
|
||||
*
|
||||
* If this function encounters part of the tree which has not been
|
||||
* allocated, it returns the current height of the tree at the point
|
||||
* at which it found the unallocated block. Blocks which are found are
|
||||
* added to the mp->mp_bh[] list.
|
||||
*
|
||||
* Returns: error or height of metadata tree
|
||||
*/
|
||||
|
||||
static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh,
|
||||
unsigned int height, struct metapath *mp, int create,
|
||||
int *new, u64 *block)
|
||||
static int lookup_metapath(struct gfs2_inode *ip, struct metapath *mp)
|
||||
{
|
||||
int boundary;
|
||||
__be64 *ptr = metapointer(bh, &boundary, height, mp);
|
||||
unsigned int end_of_metadata = ip->i_height - 1;
|
||||
unsigned int x;
|
||||
__be64 *ptr;
|
||||
u64 dblock;
|
||||
int ret;
|
||||
|
||||
if (*ptr) {
|
||||
*block = be64_to_cpu(*ptr);
|
||||
return boundary;
|
||||
for (x = 0; x < end_of_metadata; x++) {
|
||||
ptr = metapointer(x, mp);
|
||||
dblock = be64_to_cpu(*ptr);
|
||||
if (!dblock)
|
||||
return x + 1;
|
||||
|
||||
ret = gfs2_meta_indirect_buffer(ip, x+1, dblock, 0, &mp->mp_bh[x+1]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
*block = 0;
|
||||
|
||||
if (!create)
|
||||
return 0;
|
||||
|
||||
if (height == ip->i_di.di_height - 1 && !gfs2_is_dir(ip))
|
||||
*block = gfs2_alloc_data(ip);
|
||||
else
|
||||
*block = gfs2_alloc_meta(ip);
|
||||
|
||||
gfs2_trans_add_bh(ip->i_gl, bh, 1);
|
||||
|
||||
*ptr = cpu_to_be64(*block);
|
||||
ip->i_di.di_blocks++;
|
||||
gfs2_set_inode_blocks(&ip->i_inode);
|
||||
|
||||
*new = 1;
|
||||
return 0;
|
||||
return ip->i_height;
|
||||
}
|
||||
|
||||
static inline void bmap_lock(struct inode *inode, int create)
|
||||
static inline void release_metapath(struct metapath *mp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < GFS2_MAX_META_HEIGHT; i++) {
|
||||
if (mp->mp_bh[i] == NULL)
|
||||
break;
|
||||
brelse(mp->mp_bh[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_extent_length - Returns length of an extent of blocks
|
||||
* @start: Start of the buffer
|
||||
* @len: Length of the buffer in bytes
|
||||
* @ptr: Current position in the buffer
|
||||
* @limit: Max extent length to return (0 = unlimited)
|
||||
* @eob: Set to 1 if we hit "end of block"
|
||||
*
|
||||
* If the first block is zero (unallocated) it will return the number of
|
||||
* unallocated blocks in the extent, otherwise it will return the number
|
||||
* of contiguous blocks in the extent.
|
||||
*
|
||||
* Returns: The length of the extent (minimum of one block)
|
||||
*/
|
||||
|
||||
static inline unsigned int gfs2_extent_length(void *start, unsigned int len, __be64 *ptr, unsigned limit, int *eob)
|
||||
{
|
||||
const __be64 *end = (start + len);
|
||||
const __be64 *first = ptr;
|
||||
u64 d = be64_to_cpu(*ptr);
|
||||
|
||||
*eob = 0;
|
||||
do {
|
||||
ptr++;
|
||||
if (ptr >= end)
|
||||
break;
|
||||
if (limit && --limit == 0)
|
||||
break;
|
||||
if (d)
|
||||
d++;
|
||||
} while(be64_to_cpu(*ptr) == d);
|
||||
if (ptr >= end)
|
||||
*eob = 1;
|
||||
return (ptr - first);
|
||||
}
|
||||
|
||||
static inline void bmap_lock(struct gfs2_inode *ip, int create)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
if (create)
|
||||
down_write(&ip->i_rw_mutex);
|
||||
else
|
||||
down_read(&ip->i_rw_mutex);
|
||||
}
|
||||
|
||||
static inline void bmap_unlock(struct inode *inode, int create)
|
||||
static inline void bmap_unlock(struct gfs2_inode *ip, int create)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
if (create)
|
||||
up_write(&ip->i_rw_mutex);
|
||||
else
|
||||
up_read(&ip->i_rw_mutex);
|
||||
}
|
||||
|
||||
static inline __be64 *gfs2_indirect_init(struct metapath *mp,
|
||||
struct gfs2_glock *gl, unsigned int i,
|
||||
unsigned offset, u64 bn)
|
||||
{
|
||||
__be64 *ptr = (__be64 *)(mp->mp_bh[i - 1]->b_data +
|
||||
((i > 1) ? sizeof(struct gfs2_meta_header) :
|
||||
sizeof(struct gfs2_dinode)));
|
||||
BUG_ON(i < 1);
|
||||
BUG_ON(mp->mp_bh[i] != NULL);
|
||||
mp->mp_bh[i] = gfs2_meta_new(gl, bn);
|
||||
gfs2_trans_add_bh(gl, mp->mp_bh[i], 1);
|
||||
gfs2_metatype_set(mp->mp_bh[i], GFS2_METATYPE_IN, GFS2_FORMAT_IN);
|
||||
gfs2_buffer_clear_tail(mp->mp_bh[i], sizeof(struct gfs2_meta_header));
|
||||
ptr += offset;
|
||||
*ptr = cpu_to_be64(bn);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
enum alloc_state {
|
||||
ALLOC_DATA = 0,
|
||||
ALLOC_GROW_DEPTH = 1,
|
||||
ALLOC_GROW_HEIGHT = 2,
|
||||
/* ALLOC_UNSTUFF = 3, TBD and rather complicated */
|
||||
};
|
||||
|
||||
/**
|
||||
* gfs2_bmap_alloc - Build a metadata tree of the requested height
|
||||
* @inode: The GFS2 inode
|
||||
* @lblock: The logical starting block of the extent
|
||||
* @bh_map: This is used to return the mapping details
|
||||
* @mp: The metapath
|
||||
* @sheight: The starting height (i.e. whats already mapped)
|
||||
* @height: The height to build to
|
||||
* @maxlen: The max number of data blocks to alloc
|
||||
*
|
||||
* In this routine we may have to alloc:
|
||||
* i) Indirect blocks to grow the metadata tree height
|
||||
* ii) Indirect blocks to fill in lower part of the metadata tree
|
||||
* iii) Data blocks
|
||||
*
|
||||
* The function is in two parts. The first part works out the total
|
||||
* number of blocks which we need. The second part does the actual
|
||||
* allocation asking for an extent at a time (if enough contiguous free
|
||||
* blocks are available, there will only be one request per bmap call)
|
||||
* and uses the state machine to initialise the blocks in order.
|
||||
*
|
||||
* Returns: errno on error
|
||||
*/
|
||||
|
||||
static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock,
|
||||
struct buffer_head *bh_map, struct metapath *mp,
|
||||
const unsigned int sheight,
|
||||
const unsigned int height,
|
||||
const unsigned int maxlen)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
struct buffer_head *dibh = mp->mp_bh[0];
|
||||
u64 bn, dblock = 0;
|
||||
unsigned n, i, blks, alloced = 0, iblks = 0, zmpl = 0;
|
||||
unsigned dblks = 0;
|
||||
unsigned ptrs_per_blk;
|
||||
const unsigned end_of_metadata = height - 1;
|
||||
int eob = 0;
|
||||
enum alloc_state state;
|
||||
__be64 *ptr;
|
||||
__be64 zero_bn = 0;
|
||||
|
||||
BUG_ON(sheight < 1);
|
||||
BUG_ON(dibh == NULL);
|
||||
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
|
||||
if (height == sheight) {
|
||||
struct buffer_head *bh;
|
||||
/* Bottom indirect block exists, find unalloced extent size */
|
||||
ptr = metapointer(end_of_metadata, mp);
|
||||
bh = mp->mp_bh[end_of_metadata];
|
||||
dblks = gfs2_extent_length(bh->b_data, bh->b_size, ptr, maxlen,
|
||||
&eob);
|
||||
BUG_ON(dblks < 1);
|
||||
state = ALLOC_DATA;
|
||||
} else {
|
||||
/* Need to allocate indirect blocks */
|
||||
ptrs_per_blk = height > 1 ? sdp->sd_inptrs : sdp->sd_diptrs;
|
||||
dblks = min(maxlen, ptrs_per_blk - mp->mp_list[end_of_metadata]);
|
||||
if (height == ip->i_height) {
|
||||
/* Writing into existing tree, extend tree down */
|
||||
iblks = height - sheight;
|
||||
state = ALLOC_GROW_DEPTH;
|
||||
} else {
|
||||
/* Building up tree height */
|
||||
state = ALLOC_GROW_HEIGHT;
|
||||
iblks = height - ip->i_height;
|
||||
zmpl = zero_metapath_length(mp, height);
|
||||
iblks -= zmpl;
|
||||
iblks += height;
|
||||
}
|
||||
}
|
||||
|
||||
/* start of the second part of the function (state machine) */
|
||||
|
||||
blks = dblks + iblks;
|
||||
i = sheight;
|
||||
do {
|
||||
n = blks - alloced;
|
||||
bn = gfs2_alloc_block(ip, &n);
|
||||
alloced += n;
|
||||
if (state != ALLOC_DATA || gfs2_is_jdata(ip))
|
||||
gfs2_trans_add_unrevoke(sdp, bn, n);
|
||||
switch (state) {
|
||||
/* Growing height of tree */
|
||||
case ALLOC_GROW_HEIGHT:
|
||||
if (i == 1) {
|
||||
ptr = (__be64 *)(dibh->b_data +
|
||||
sizeof(struct gfs2_dinode));
|
||||
zero_bn = *ptr;
|
||||
}
|
||||
for (; i - 1 < height - ip->i_height && n > 0; i++, n--)
|
||||
gfs2_indirect_init(mp, ip->i_gl, i, 0, bn++);
|
||||
if (i - 1 == height - ip->i_height) {
|
||||
i--;
|
||||
gfs2_buffer_copy_tail(mp->mp_bh[i],
|
||||
sizeof(struct gfs2_meta_header),
|
||||
dibh, sizeof(struct gfs2_dinode));
|
||||
gfs2_buffer_clear_tail(dibh,
|
||||
sizeof(struct gfs2_dinode) +
|
||||
sizeof(__be64));
|
||||
ptr = (__be64 *)(mp->mp_bh[i]->b_data +
|
||||
sizeof(struct gfs2_meta_header));
|
||||
*ptr = zero_bn;
|
||||
state = ALLOC_GROW_DEPTH;
|
||||
for(i = zmpl; i < height; i++) {
|
||||
if (mp->mp_bh[i] == NULL)
|
||||
break;
|
||||
brelse(mp->mp_bh[i]);
|
||||
mp->mp_bh[i] = NULL;
|
||||
}
|
||||
i = zmpl;
|
||||
}
|
||||
if (n == 0)
|
||||
break;
|
||||
/* Branching from existing tree */
|
||||
case ALLOC_GROW_DEPTH:
|
||||
if (i > 1 && i < height)
|
||||
gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[i-1], 1);
|
||||
for (; i < height && n > 0; i++, n--)
|
||||
gfs2_indirect_init(mp, ip->i_gl, i,
|
||||
mp->mp_list[i-1], bn++);
|
||||
if (i == height)
|
||||
state = ALLOC_DATA;
|
||||
if (n == 0)
|
||||
break;
|
||||
/* Tree complete, adding data blocks */
|
||||
case ALLOC_DATA:
|
||||
BUG_ON(n > dblks);
|
||||
BUG_ON(mp->mp_bh[end_of_metadata] == NULL);
|
||||
gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[end_of_metadata], 1);
|
||||
dblks = n;
|
||||
ptr = metapointer(end_of_metadata, mp);
|
||||
dblock = bn;
|
||||
while (n-- > 0)
|
||||
*ptr++ = cpu_to_be64(bn++);
|
||||
break;
|
||||
}
|
||||
} while (state != ALLOC_DATA);
|
||||
|
||||
ip->i_height = height;
|
||||
gfs2_add_inode_blocks(&ip->i_inode, alloced);
|
||||
gfs2_dinode_out(ip, mp->mp_bh[0]->b_data);
|
||||
map_bh(bh_map, inode->i_sb, dblock);
|
||||
bh_map->b_size = dblks << inode->i_blkbits;
|
||||
set_buffer_new(bh_map);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_block_map - Map a block from an inode to a disk block
|
||||
* @inode: The inode
|
||||
* @lblock: The logical block number
|
||||
* @bh_map: The bh to be mapped
|
||||
* @create: True if its ok to alloc blocks to satify the request
|
||||
*
|
||||
* Find the block number on the current device which corresponds to an
|
||||
* inode's block. If the block had to be created, "new" will be set.
|
||||
* Sets buffer_mapped() if successful, sets buffer_boundary() if a
|
||||
* read of metadata will be required before the next block can be
|
||||
* mapped. Sets buffer_new() if new blocks were allocated.
|
||||
*
|
||||
* Returns: errno
|
||||
*/
|
||||
@ -457,97 +572,78 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
struct buffer_head *bh;
|
||||
unsigned int bsize;
|
||||
unsigned int height;
|
||||
unsigned int end_of_metadata;
|
||||
unsigned int x;
|
||||
int error = 0;
|
||||
int new = 0;
|
||||
u64 dblock = 0;
|
||||
int boundary;
|
||||
unsigned int maxlen = bh_map->b_size >> inode->i_blkbits;
|
||||
struct metapath mp;
|
||||
unsigned int bsize = sdp->sd_sb.sb_bsize;
|
||||
const unsigned int maxlen = bh_map->b_size >> inode->i_blkbits;
|
||||
const u64 *arr = sdp->sd_heightsize;
|
||||
__be64 *ptr;
|
||||
u64 size;
|
||||
struct buffer_head *dibh = NULL;
|
||||
struct metapath mp;
|
||||
int ret;
|
||||
int eob;
|
||||
unsigned int len;
|
||||
struct buffer_head *bh;
|
||||
u8 height;
|
||||
|
||||
BUG_ON(maxlen == 0);
|
||||
|
||||
if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip)))
|
||||
return 0;
|
||||
|
||||
bmap_lock(inode, create);
|
||||
memset(mp.mp_bh, 0, sizeof(mp.mp_bh));
|
||||
bmap_lock(ip, create);
|
||||
clear_buffer_mapped(bh_map);
|
||||
clear_buffer_new(bh_map);
|
||||
clear_buffer_boundary(bh_map);
|
||||
bsize = gfs2_is_dir(ip) ? sdp->sd_jbsize : sdp->sd_sb.sb_bsize;
|
||||
if (gfs2_is_dir(ip)) {
|
||||
bsize = sdp->sd_jbsize;
|
||||
arr = sdp->sd_jheightsize;
|
||||
}
|
||||
|
||||
ret = gfs2_meta_inode_buffer(ip, &mp.mp_bh[0]);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
height = ip->i_height;
|
||||
size = (lblock + 1) * bsize;
|
||||
while (size > arr[height])
|
||||
height++;
|
||||
find_metapath(sdp, lblock, &mp, height);
|
||||
ret = 1;
|
||||
if (height > ip->i_height || gfs2_is_stuffed(ip))
|
||||
goto do_alloc;
|
||||
ret = lookup_metapath(ip, &mp);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (ret != ip->i_height)
|
||||
goto do_alloc;
|
||||
ptr = metapointer(ip->i_height - 1, &mp);
|
||||
if (*ptr == 0)
|
||||
goto do_alloc;
|
||||
map_bh(bh_map, inode->i_sb, be64_to_cpu(*ptr));
|
||||
bh = mp.mp_bh[ip->i_height - 1];
|
||||
len = gfs2_extent_length(bh->b_data, bh->b_size, ptr, maxlen, &eob);
|
||||
bh_map->b_size = (len << inode->i_blkbits);
|
||||
if (eob)
|
||||
set_buffer_boundary(bh_map);
|
||||
ret = 0;
|
||||
out:
|
||||
release_metapath(&mp);
|
||||
bmap_unlock(ip, create);
|
||||
return ret;
|
||||
|
||||
if (size > ip->i_di.di_size) {
|
||||
height = calc_tree_height(ip, size);
|
||||
if (ip->i_di.di_height < height) {
|
||||
if (!create)
|
||||
goto out_ok;
|
||||
|
||||
error = build_height(inode, height);
|
||||
if (error)
|
||||
goto out_fail;
|
||||
}
|
||||
do_alloc:
|
||||
/* All allocations are done here, firstly check create flag */
|
||||
if (!create) {
|
||||
BUG_ON(gfs2_is_stuffed(ip));
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
find_metapath(ip, lblock, &mp);
|
||||
end_of_metadata = ip->i_di.di_height - 1;
|
||||
error = gfs2_meta_inode_buffer(ip, &bh);
|
||||
if (error)
|
||||
goto out_fail;
|
||||
dibh = bh;
|
||||
get_bh(dibh);
|
||||
|
||||
for (x = 0; x < end_of_metadata; x++) {
|
||||
lookup_block(ip, bh, x, &mp, create, &new, &dblock);
|
||||
brelse(bh);
|
||||
if (!dblock)
|
||||
goto out_ok;
|
||||
|
||||
error = gfs2_meta_indirect_buffer(ip, x+1, dblock, new, &bh);
|
||||
if (error)
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
boundary = lookup_block(ip, bh, end_of_metadata, &mp, create, &new, &dblock);
|
||||
if (dblock) {
|
||||
map_bh(bh_map, inode->i_sb, dblock);
|
||||
if (boundary)
|
||||
set_buffer_boundary(bh_map);
|
||||
if (new) {
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
set_buffer_new(bh_map);
|
||||
goto out_brelse;
|
||||
}
|
||||
while(--maxlen && !buffer_boundary(bh_map)) {
|
||||
u64 eblock;
|
||||
|
||||
mp.mp_list[end_of_metadata]++;
|
||||
boundary = lookup_block(ip, bh, end_of_metadata, &mp, 0, &new, &eblock);
|
||||
if (eblock != ++dblock)
|
||||
break;
|
||||
bh_map->b_size += (1 << inode->i_blkbits);
|
||||
if (boundary)
|
||||
set_buffer_boundary(bh_map);
|
||||
}
|
||||
}
|
||||
out_brelse:
|
||||
brelse(bh);
|
||||
out_ok:
|
||||
error = 0;
|
||||
out_fail:
|
||||
if (dibh)
|
||||
brelse(dibh);
|
||||
bmap_unlock(inode, create);
|
||||
return error;
|
||||
/* At this point ret is the tree depth of already allocated blocks */
|
||||
ret = gfs2_bmap_alloc(inode, lblock, bh_map, &mp, ret, height, maxlen);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deprecated: do not use in new code
|
||||
*/
|
||||
int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen)
|
||||
{
|
||||
struct buffer_head bh = { .b_state = 0, .b_blocknr = 0 };
|
||||
@ -558,7 +654,7 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi
|
||||
BUG_ON(!dblock);
|
||||
BUG_ON(!new);
|
||||
|
||||
bh.b_size = 1 << (inode->i_blkbits + 5);
|
||||
bh.b_size = 1 << (inode->i_blkbits + (create ? 0 : 5));
|
||||
ret = gfs2_block_map(inode, lblock, &bh, create);
|
||||
*extlen = bh.b_size >> inode->i_blkbits;
|
||||
*dblock = bh.b_blocknr;
|
||||
@ -621,7 +717,7 @@ static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh,
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
if (height < ip->i_di.di_height - 1)
|
||||
if (height < ip->i_height - 1)
|
||||
for (; top < bottom; top++, first = 0) {
|
||||
if (!*top)
|
||||
continue;
|
||||
@ -679,7 +775,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
|
||||
sm->sm_first = 0;
|
||||
}
|
||||
|
||||
metadata = (height != ip->i_di.di_height - 1);
|
||||
metadata = (height != ip->i_height - 1);
|
||||
if (metadata)
|
||||
revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs;
|
||||
|
||||
@ -713,7 +809,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
|
||||
else
|
||||
goto out; /* Nothing to do */
|
||||
|
||||
gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0);
|
||||
gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE);
|
||||
|
||||
for (x = 0; x < rlist.rl_rgrps; x++) {
|
||||
struct gfs2_rgrpd *rgd;
|
||||
@ -760,10 +856,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
|
||||
}
|
||||
|
||||
*p = 0;
|
||||
if (!ip->i_di.di_blocks)
|
||||
gfs2_consist_inode(ip);
|
||||
ip->i_di.di_blocks--;
|
||||
gfs2_set_inode_blocks(&ip->i_inode);
|
||||
gfs2_add_inode_blocks(&ip->i_inode, -1);
|
||||
}
|
||||
if (bstart) {
|
||||
if (metadata)
|
||||
@ -804,19 +897,16 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
struct gfs2_alloc *al;
|
||||
struct buffer_head *dibh;
|
||||
unsigned int h;
|
||||
int error;
|
||||
|
||||
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)
|
||||
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 = sdp->sd_max_height + RES_DATA;
|
||||
|
||||
error = gfs2_inplace_reserve(ip);
|
||||
@ -829,34 +919,25 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
|
||||
if (error)
|
||||
goto out_ipres;
|
||||
|
||||
error = gfs2_meta_inode_buffer(ip, &dibh);
|
||||
if (error)
|
||||
goto out_end_trans;
|
||||
|
||||
if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
|
||||
if (gfs2_is_stuffed(ip)) {
|
||||
error = gfs2_unstuff_dinode(ip, NULL);
|
||||
if (error)
|
||||
goto out_end_trans;
|
||||
}
|
||||
|
||||
h = calc_tree_height(ip, size);
|
||||
if (ip->i_di.di_height < h) {
|
||||
down_write(&ip->i_rw_mutex);
|
||||
error = build_height(&ip->i_inode, h);
|
||||
up_write(&ip->i_rw_mutex);
|
||||
if (error)
|
||||
goto out_end_trans;
|
||||
goto out_brelse;
|
||||
}
|
||||
}
|
||||
|
||||
ip->i_di.di_size = size;
|
||||
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
|
||||
|
||||
error = gfs2_meta_inode_buffer(ip, &dibh);
|
||||
if (error)
|
||||
goto out_end_trans;
|
||||
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
brelse(dibh);
|
||||
|
||||
out_brelse:
|
||||
brelse(dibh);
|
||||
out_end_trans:
|
||||
gfs2_trans_end(sdp);
|
||||
out_ipres:
|
||||
@ -986,7 +1067,8 @@ out:
|
||||
|
||||
static int trunc_dealloc(struct gfs2_inode *ip, u64 size)
|
||||
{
|
||||
unsigned int height = ip->i_di.di_height;
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
unsigned int height = ip->i_height;
|
||||
u64 lblock;
|
||||
struct metapath mp;
|
||||
int error;
|
||||
@ -994,10 +1076,11 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size)
|
||||
if (!size)
|
||||
lblock = 0;
|
||||
else
|
||||
lblock = (size - 1) >> GFS2_SB(&ip->i_inode)->sd_sb.sb_bsize_shift;
|
||||
lblock = (size - 1) >> sdp->sd_sb.sb_bsize_shift;
|
||||
|
||||
find_metapath(ip, lblock, &mp);
|
||||
gfs2_alloc_get(ip);
|
||||
find_metapath(sdp, lblock, &mp, ip->i_height);
|
||||
if (!gfs2_alloc_get(ip))
|
||||
return -ENOMEM;
|
||||
|
||||
error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
|
||||
if (error)
|
||||
@ -1037,10 +1120,8 @@ static int trunc_end(struct gfs2_inode *ip)
|
||||
goto out;
|
||||
|
||||
if (!ip->i_di.di_size) {
|
||||
ip->i_di.di_height = 0;
|
||||
ip->i_di.di_goal_meta =
|
||||
ip->i_di.di_goal_data =
|
||||
ip->i_no_addr;
|
||||
ip->i_height = 0;
|
||||
ip->i_goal = ip->i_no_addr;
|
||||
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
|
||||
}
|
||||
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
|
||||
@ -1197,10 +1278,9 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
|
||||
unsigned int len, int *alloc_required)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
u64 lblock, lblock_stop, dblock;
|
||||
u32 extlen;
|
||||
int new = 0;
|
||||
int error = 0;
|
||||
struct buffer_head bh;
|
||||
unsigned int shift;
|
||||
u64 lblock, lblock_stop, size;
|
||||
|
||||
*alloc_required = 0;
|
||||
|
||||
@ -1214,6 +1294,8 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
|
||||
return 0;
|
||||
}
|
||||
|
||||
*alloc_required = 1;
|
||||
shift = sdp->sd_sb.sb_bsize_shift;
|
||||
if (gfs2_is_dir(ip)) {
|
||||
unsigned int bsize = sdp->sd_jbsize;
|
||||
lblock = offset;
|
||||
@ -1221,27 +1303,25 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
|
||||
lblock_stop = offset + len + bsize - 1;
|
||||
do_div(lblock_stop, bsize);
|
||||
} else {
|
||||
unsigned int shift = sdp->sd_sb.sb_bsize_shift;
|
||||
u64 end_of_file = (ip->i_di.di_size + sdp->sd_sb.sb_bsize - 1) >> shift;
|
||||
lblock = offset >> shift;
|
||||
lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift;
|
||||
if (lblock_stop > end_of_file) {
|
||||
*alloc_required = 1;
|
||||
if (lblock_stop > end_of_file)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (; lblock < lblock_stop; lblock += extlen) {
|
||||
error = gfs2_extent_map(&ip->i_inode, lblock, &new, &dblock, &extlen);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (!dblock) {
|
||||
*alloc_required = 1;
|
||||
size = (lblock_stop - lblock) << shift;
|
||||
do {
|
||||
bh.b_state = 0;
|
||||
bh.b_size = size;
|
||||
gfs2_block_map(&ip->i_inode, lblock, &bh, 0);
|
||||
if (!buffer_mapped(&bh))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
size -= bh.b_size;
|
||||
lblock += (bh.b_size >> ip->i_inode.i_blkbits);
|
||||
} while(size > 0);
|
||||
|
||||
*alloc_required = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -159,6 +159,7 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
|
||||
unsigned int o;
|
||||
int copied = 0;
|
||||
int error = 0;
|
||||
int new = 0;
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
@ -183,7 +184,6 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
|
||||
while (copied < size) {
|
||||
unsigned int amount;
|
||||
struct buffer_head *bh;
|
||||
int new = 0;
|
||||
|
||||
amount = size - copied;
|
||||
if (amount > sdp->sd_sb.sb_bsize - o)
|
||||
@ -757,7 +757,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
|
||||
|
||||
if (ip->i_di.di_flags & GFS2_DIF_EXHASH) {
|
||||
struct gfs2_leaf *leaf;
|
||||
unsigned hsize = 1 << ip->i_di.di_depth;
|
||||
unsigned hsize = 1 << ip->i_depth;
|
||||
unsigned index;
|
||||
u64 ln;
|
||||
if (hsize * sizeof(u64) != ip->i_di.di_size) {
|
||||
@ -765,7 +765,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
|
||||
return ERR_PTR(-EIO);
|
||||
}
|
||||
|
||||
index = name->hash >> (32 - ip->i_di.di_depth);
|
||||
index = name->hash >> (32 - ip->i_depth);
|
||||
error = get_first_leaf(ip, index, &bh);
|
||||
if (error)
|
||||
return ERR_PTR(error);
|
||||
@ -803,14 +803,15 @@ got_dent:
|
||||
static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, u16 depth)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
u64 bn = gfs2_alloc_meta(ip);
|
||||
unsigned int n = 1;
|
||||
u64 bn = gfs2_alloc_block(ip, &n);
|
||||
struct buffer_head *bh = gfs2_meta_new(ip->i_gl, bn);
|
||||
struct gfs2_leaf *leaf;
|
||||
struct gfs2_dirent *dent;
|
||||
struct qstr name = { .name = "", .len = 0, .hash = 0 };
|
||||
if (!bh)
|
||||
return NULL;
|
||||
|
||||
gfs2_trans_add_unrevoke(GFS2_SB(inode), bn, 1);
|
||||
gfs2_trans_add_bh(ip->i_gl, bh, 1);
|
||||
gfs2_metatype_set(bh, GFS2_METATYPE_LF, GFS2_FORMAT_LF);
|
||||
leaf = (struct gfs2_leaf *)bh->b_data;
|
||||
@ -905,12 +906,11 @@ static int dir_make_exhash(struct inode *inode)
|
||||
*lp = cpu_to_be64(bn);
|
||||
|
||||
dip->i_di.di_size = sdp->sd_sb.sb_bsize / 2;
|
||||
dip->i_di.di_blocks++;
|
||||
gfs2_set_inode_blocks(&dip->i_inode);
|
||||
gfs2_add_inode_blocks(&dip->i_inode, 1);
|
||||
dip->i_di.di_flags |= GFS2_DIF_EXHASH;
|
||||
|
||||
for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ;
|
||||
dip->i_di.di_depth = y;
|
||||
dip->i_depth = y;
|
||||
|
||||
gfs2_dinode_out(dip, dibh->b_data);
|
||||
|
||||
@ -941,7 +941,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
|
||||
int x, moved = 0;
|
||||
int error;
|
||||
|
||||
index = name->hash >> (32 - dip->i_di.di_depth);
|
||||
index = name->hash >> (32 - dip->i_depth);
|
||||
error = get_leaf_nr(dip, index, &leaf_no);
|
||||
if (error)
|
||||
return error;
|
||||
@ -952,7 +952,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
|
||||
return error;
|
||||
|
||||
oleaf = (struct gfs2_leaf *)obh->b_data;
|
||||
if (dip->i_di.di_depth == be16_to_cpu(oleaf->lf_depth)) {
|
||||
if (dip->i_depth == be16_to_cpu(oleaf->lf_depth)) {
|
||||
brelse(obh);
|
||||
return 1; /* can't split */
|
||||
}
|
||||
@ -967,10 +967,10 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
|
||||
bn = nbh->b_blocknr;
|
||||
|
||||
/* Compute the start and len of leaf pointers in the hash table. */
|
||||
len = 1 << (dip->i_di.di_depth - be16_to_cpu(oleaf->lf_depth));
|
||||
len = 1 << (dip->i_depth - be16_to_cpu(oleaf->lf_depth));
|
||||
half_len = len >> 1;
|
||||
if (!half_len) {
|
||||
printk(KERN_WARNING "di_depth %u lf_depth %u index %u\n", dip->i_di.di_depth, be16_to_cpu(oleaf->lf_depth), index);
|
||||
printk(KERN_WARNING "i_depth %u lf_depth %u index %u\n", dip->i_depth, be16_to_cpu(oleaf->lf_depth), index);
|
||||
gfs2_consist_inode(dip);
|
||||
error = -EIO;
|
||||
goto fail_brelse;
|
||||
@ -997,7 +997,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
|
||||
kfree(lp);
|
||||
|
||||
/* Compute the divider */
|
||||
divider = (start + half_len) << (32 - dip->i_di.di_depth);
|
||||
divider = (start + half_len) << (32 - dip->i_depth);
|
||||
|
||||
/* Copy the entries */
|
||||
dirent_first(dip, obh, &dent);
|
||||
@ -1021,13 +1021,13 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
|
||||
|
||||
new->de_inum = dent->de_inum; /* No endian worries */
|
||||
new->de_type = dent->de_type; /* No endian worries */
|
||||
nleaf->lf_entries = cpu_to_be16(be16_to_cpu(nleaf->lf_entries)+1);
|
||||
be16_add_cpu(&nleaf->lf_entries, 1);
|
||||
|
||||
dirent_del(dip, obh, prev, dent);
|
||||
|
||||
if (!oleaf->lf_entries)
|
||||
gfs2_consist_inode(dip);
|
||||
oleaf->lf_entries = cpu_to_be16(be16_to_cpu(oleaf->lf_entries)-1);
|
||||
be16_add_cpu(&oleaf->lf_entries, -1);
|
||||
|
||||
if (!prev)
|
||||
prev = dent;
|
||||
@ -1044,8 +1044,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
|
||||
error = gfs2_meta_inode_buffer(dip, &dibh);
|
||||
if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) {
|
||||
gfs2_trans_add_bh(dip->i_gl, dibh, 1);
|
||||
dip->i_di.di_blocks++;
|
||||
gfs2_set_inode_blocks(&dip->i_inode);
|
||||
gfs2_add_inode_blocks(&dip->i_inode, 1);
|
||||
gfs2_dinode_out(dip, dibh->b_data);
|
||||
brelse(dibh);
|
||||
}
|
||||
@ -1082,7 +1081,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
|
||||
int x;
|
||||
int error = 0;
|
||||
|
||||
hsize = 1 << dip->i_di.di_depth;
|
||||
hsize = 1 << dip->i_depth;
|
||||
if (hsize * sizeof(u64) != dip->i_di.di_size) {
|
||||
gfs2_consist_inode(dip);
|
||||
return -EIO;
|
||||
@ -1090,7 +1089,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
|
||||
|
||||
/* Allocate both the "from" and "to" buffers in one big chunk */
|
||||
|
||||
buf = kcalloc(3, sdp->sd_hash_bsize, GFP_KERNEL | __GFP_NOFAIL);
|
||||
buf = kcalloc(3, sdp->sd_hash_bsize, GFP_NOFS | __GFP_NOFAIL);
|
||||
|
||||
for (block = dip->i_di.di_size >> sdp->sd_hash_bsize_shift; block--;) {
|
||||
error = gfs2_dir_read_data(dip, (char *)buf,
|
||||
@ -1125,7 +1124,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
|
||||
|
||||
error = gfs2_meta_inode_buffer(dip, &dibh);
|
||||
if (!gfs2_assert_withdraw(sdp, !error)) {
|
||||
dip->i_di.di_depth++;
|
||||
dip->i_depth++;
|
||||
gfs2_dinode_out(dip, dibh->b_data);
|
||||
brelse(dibh);
|
||||
}
|
||||
@ -1370,16 +1369,16 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
|
||||
int error = 0;
|
||||
unsigned depth = 0;
|
||||
|
||||
hsize = 1 << dip->i_di.di_depth;
|
||||
hsize = 1 << dip->i_depth;
|
||||
if (hsize * sizeof(u64) != dip->i_di.di_size) {
|
||||
gfs2_consist_inode(dip);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
hash = gfs2_dir_offset2hash(*offset);
|
||||
index = hash >> (32 - dip->i_di.di_depth);
|
||||
index = hash >> (32 - dip->i_depth);
|
||||
|
||||
lp = kmalloc(sdp->sd_hash_bsize, GFP_KERNEL);
|
||||
lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS);
|
||||
if (!lp)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -1405,7 +1404,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
|
||||
if (error)
|
||||
break;
|
||||
|
||||
len = 1 << (dip->i_di.di_depth - depth);
|
||||
len = 1 << (dip->i_depth - depth);
|
||||
index = (index & ~(len - 1)) + len;
|
||||
}
|
||||
|
||||
@ -1444,7 +1443,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
|
||||
|
||||
error = -ENOMEM;
|
||||
/* 96 is max number of dirents which can be stuffed into an inode */
|
||||
darr = kmalloc(96 * sizeof(struct gfs2_dirent *), GFP_KERNEL);
|
||||
darr = kmalloc(96 * sizeof(struct gfs2_dirent *), GFP_NOFS);
|
||||
if (darr) {
|
||||
g.pdent = darr;
|
||||
g.offset = 0;
|
||||
@ -1549,7 +1548,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
|
||||
u32 index;
|
||||
u64 bn;
|
||||
|
||||
index = name->hash >> (32 - ip->i_di.di_depth);
|
||||
index = name->hash >> (32 - ip->i_depth);
|
||||
error = get_first_leaf(ip, index, &obh);
|
||||
if (error)
|
||||
return error;
|
||||
@ -1579,8 +1578,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
|
||||
if (error)
|
||||
return error;
|
||||
gfs2_trans_add_bh(ip->i_gl, bh, 1);
|
||||
ip->i_di.di_blocks++;
|
||||
gfs2_set_inode_blocks(&ip->i_inode);
|
||||
gfs2_add_inode_blocks(&ip->i_inode, 1);
|
||||
gfs2_dinode_out(ip, bh->b_data);
|
||||
brelse(bh);
|
||||
return 0;
|
||||
@ -1616,7 +1614,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
|
||||
dent->de_type = cpu_to_be16(type);
|
||||
if (ip->i_di.di_flags & GFS2_DIF_EXHASH) {
|
||||
leaf = (struct gfs2_leaf *)bh->b_data;
|
||||
leaf->lf_entries = cpu_to_be16(be16_to_cpu(leaf->lf_entries) + 1);
|
||||
be16_add_cpu(&leaf->lf_entries, 1);
|
||||
}
|
||||
brelse(bh);
|
||||
error = gfs2_meta_inode_buffer(ip, &bh);
|
||||
@ -1641,7 +1639,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
|
||||
continue;
|
||||
if (error < 0)
|
||||
break;
|
||||
if (ip->i_di.di_depth < GFS2_DIR_MAX_DEPTH) {
|
||||
if (ip->i_depth < GFS2_DIR_MAX_DEPTH) {
|
||||
error = dir_double_exhash(ip);
|
||||
if (error)
|
||||
break;
|
||||
@ -1785,13 +1783,13 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
|
||||
u64 leaf_no;
|
||||
int error = 0;
|
||||
|
||||
hsize = 1 << dip->i_di.di_depth;
|
||||
hsize = 1 << dip->i_depth;
|
||||
if (hsize * sizeof(u64) != dip->i_di.di_size) {
|
||||
gfs2_consist_inode(dip);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
lp = kmalloc(sdp->sd_hash_bsize, GFP_KERNEL);
|
||||
lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS);
|
||||
if (!lp)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -1817,7 +1815,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
|
||||
if (error)
|
||||
goto out;
|
||||
leaf = (struct gfs2_leaf *)bh->b_data;
|
||||
len = 1 << (dip->i_di.di_depth - be16_to_cpu(leaf->lf_depth));
|
||||
len = 1 << (dip->i_depth - be16_to_cpu(leaf->lf_depth));
|
||||
brelse(bh);
|
||||
|
||||
error = lc(dip, index, len, leaf_no, data);
|
||||
@ -1866,15 +1864,18 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
|
||||
|
||||
memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
|
||||
|
||||
ht = kzalloc(size, GFP_KERNEL);
|
||||
ht = kzalloc(size, GFP_NOFS);
|
||||
if (!ht)
|
||||
return -ENOMEM;
|
||||
|
||||
gfs2_alloc_get(dip);
|
||||
if (!gfs2_alloc_get(dip)) {
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = gfs2_quota_hold(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
|
||||
if (error)
|
||||
goto out;
|
||||
goto out_put;
|
||||
|
||||
error = gfs2_rindex_hold(sdp, &dip->i_alloc->al_ri_gh);
|
||||
if (error)
|
||||
@ -1894,7 +1895,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
|
||||
l_blocks++;
|
||||
}
|
||||
|
||||
gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0);
|
||||
gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE);
|
||||
|
||||
for (x = 0; x < rlist.rl_rgrps; x++) {
|
||||
struct gfs2_rgrpd *rgd;
|
||||
@ -1921,11 +1922,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
|
||||
brelse(bh);
|
||||
|
||||
gfs2_free_meta(dip, blk, 1);
|
||||
|
||||
if (!dip->i_di.di_blocks)
|
||||
gfs2_consist_inode(dip);
|
||||
dip->i_di.di_blocks--;
|
||||
gfs2_set_inode_blocks(&dip->i_inode);
|
||||
gfs2_add_inode_blocks(&dip->i_inode, -1);
|
||||
}
|
||||
|
||||
error = gfs2_dir_write_data(dip, ht, index * sizeof(u64), size);
|
||||
@ -1952,8 +1949,9 @@ out_rlist:
|
||||
gfs2_glock_dq_uninit(&dip->i_alloc->al_ri_gh);
|
||||
out_qs:
|
||||
gfs2_quota_unhold(dip);
|
||||
out:
|
||||
out_put:
|
||||
gfs2_alloc_put(dip);
|
||||
out:
|
||||
kfree(ht);
|
||||
return error;
|
||||
}
|
||||
|
@ -277,10 +277,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
|
||||
}
|
||||
|
||||
*dataptrs = 0;
|
||||
if (!ip->i_di.di_blocks)
|
||||
gfs2_consist_inode(ip);
|
||||
ip->i_di.di_blocks--;
|
||||
gfs2_set_inode_blocks(&ip->i_inode);
|
||||
gfs2_add_inode_blocks(&ip->i_inode, -1);
|
||||
}
|
||||
if (bstart)
|
||||
gfs2_free_meta(ip, bstart, blen);
|
||||
@ -321,6 +318,8 @@ static int ea_remove_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
|
||||
int error;
|
||||
|
||||
al = gfs2_alloc_get(ip);
|
||||
if (!al)
|
||||
return -ENOMEM;
|
||||
|
||||
error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
|
||||
if (error)
|
||||
@ -449,7 +448,7 @@ static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
|
||||
unsigned int x;
|
||||
int error = 0;
|
||||
|
||||
bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_KERNEL);
|
||||
bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS);
|
||||
if (!bh)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -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_ea_header *ea;
|
||||
unsigned int n = 1;
|
||||
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);
|
||||
gfs2_trans_add_bh(ip->i_gl, *bhp, 1);
|
||||
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)
|
||||
ea->ea_flags = GFS2_EAFLAG_LAST;
|
||||
ea->ea_num_ptrs = 0;
|
||||
|
||||
ip->i_di.di_blocks++;
|
||||
gfs2_set_inode_blocks(&ip->i_inode);
|
||||
gfs2_add_inode_blocks(&ip->i_inode, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -642,15 +641,15 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
|
||||
struct buffer_head *bh;
|
||||
u64 block;
|
||||
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);
|
||||
gfs2_trans_add_bh(ip->i_gl, bh, 1);
|
||||
gfs2_metatype_set(bh, GFS2_METATYPE_ED, GFS2_FORMAT_ED);
|
||||
|
||||
ip->i_di.di_blocks++;
|
||||
gfs2_set_inode_blocks(&ip->i_inode);
|
||||
gfs2_add_inode_blocks(&ip->i_inode, 1);
|
||||
|
||||
copy = data_len > sdp->sd_jbsize ? sdp->sd_jbsize :
|
||||
data_len;
|
||||
@ -684,15 +683,13 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
|
||||
int error;
|
||||
|
||||
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)
|
||||
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;
|
||||
|
||||
error = gfs2_inplace_reserve(ip);
|
||||
@ -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);
|
||||
} else {
|
||||
u64 blk;
|
||||
|
||||
blk = gfs2_alloc_meta(ip);
|
||||
|
||||
unsigned int n = 1;
|
||||
blk = gfs2_alloc_block(ip, &n);
|
||||
gfs2_trans_add_unrevoke(sdp, blk, 1);
|
||||
indbh = gfs2_meta_new(ip->i_gl, blk);
|
||||
gfs2_trans_add_bh(ip->i_gl, indbh, 1);
|
||||
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,
|
||||
*eablk = cpu_to_be64(ip->i_di.di_eattr);
|
||||
ip->i_di.di_eattr = blk;
|
||||
ip->i_di.di_flags |= GFS2_DIF_EA_INDIRECT;
|
||||
ip->i_di.di_blocks++;
|
||||
gfs2_set_inode_blocks(&ip->i_inode);
|
||||
gfs2_add_inode_blocks(&ip->i_inode, 1);
|
||||
|
||||
eablk++;
|
||||
}
|
||||
@ -1210,7 +1206,7 @@ static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
|
||||
unsigned int x;
|
||||
int error;
|
||||
|
||||
bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_KERNEL);
|
||||
bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS);
|
||||
if (!bh)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -1347,7 +1343,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
|
||||
else
|
||||
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++) {
|
||||
struct gfs2_rgrpd *rgd;
|
||||
@ -1387,10 +1383,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
|
||||
}
|
||||
|
||||
*eablk = 0;
|
||||
if (!ip->i_di.di_blocks)
|
||||
gfs2_consist_inode(ip);
|
||||
ip->i_di.di_blocks--;
|
||||
gfs2_set_inode_blocks(&ip->i_inode);
|
||||
gfs2_add_inode_blocks(&ip->i_inode, -1);
|
||||
}
|
||||
if (bstart)
|
||||
gfs2_free_meta(ip, bstart, blen);
|
||||
@ -1442,10 +1435,7 @@ static int ea_dealloc_block(struct gfs2_inode *ip)
|
||||
gfs2_free_meta(ip, ip->i_di.di_eattr, 1);
|
||||
|
||||
ip->i_di.di_eattr = 0;
|
||||
if (!ip->i_di.di_blocks)
|
||||
gfs2_consist_inode(ip);
|
||||
ip->i_di.di_blocks--;
|
||||
gfs2_set_inode_blocks(&ip->i_inode);
|
||||
gfs2_add_inode_blocks(&ip->i_inode, -1);
|
||||
|
||||
error = gfs2_meta_inode_buffer(ip, &dibh);
|
||||
if (!error) {
|
||||
@ -1474,6 +1464,8 @@ int gfs2_ea_dealloc(struct gfs2_inode *ip)
|
||||
int error;
|
||||
|
||||
al = gfs2_alloc_get(ip);
|
||||
if (!al)
|
||||
return -ENOMEM;
|
||||
|
||||
error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
|
||||
if (error)
|
||||
|
188
fs/gfs2/glock.c
188
fs/gfs2/glock.c
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
@ -35,7 +35,6 @@
|
||||
#include "glock.h"
|
||||
#include "glops.h"
|
||||
#include "inode.h"
|
||||
#include "lm.h"
|
||||
#include "lops.h"
|
||||
#include "meta_io.h"
|
||||
#include "quota.h"
|
||||
@ -183,7 +182,8 @@ static void glock_free(struct gfs2_glock *gl)
|
||||
struct gfs2_sbd *sdp = gl->gl_sbd;
|
||||
struct inode *aspace = gl->gl_aspace;
|
||||
|
||||
gfs2_lm_put_lock(sdp, gl->gl_lock);
|
||||
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
|
||||
sdp->sd_lockstruct.ls_ops->lm_put_lock(gl->gl_lock);
|
||||
|
||||
if (aspace)
|
||||
gfs2_aspace_put(aspace);
|
||||
@ -197,7 +197,7 @@ static void glock_free(struct gfs2_glock *gl)
|
||||
*
|
||||
*/
|
||||
|
||||
void gfs2_glock_hold(struct gfs2_glock *gl)
|
||||
static void gfs2_glock_hold(struct gfs2_glock *gl)
|
||||
{
|
||||
atomic_inc(&gl->gl_ref);
|
||||
}
|
||||
@ -293,6 +293,16 @@ static void glock_work_func(struct work_struct *work)
|
||||
gfs2_glock_put(gl);
|
||||
}
|
||||
|
||||
static 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_glock_get() - Get a glock, or create one if one doesn't exist
|
||||
* @sdp: The GFS2 superblock
|
||||
@ -338,8 +348,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
|
||||
gl->gl_ip = 0;
|
||||
gl->gl_ops = glops;
|
||||
gl->gl_req_gh = NULL;
|
||||
gl->gl_req_bh = NULL;
|
||||
gl->gl_vn = 0;
|
||||
gl->gl_stamp = jiffies;
|
||||
gl->gl_tchange = jiffies;
|
||||
gl->gl_object = NULL;
|
||||
@ -595,11 +603,12 @@ static void run_queue(struct gfs2_glock *gl)
|
||||
blocked = rq_mutex(gh);
|
||||
} else if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
|
||||
blocked = rq_demote(gl);
|
||||
if (gl->gl_waiters2 && !blocked) {
|
||||
if (test_bit(GLF_WAITERS2, &gl->gl_flags) &&
|
||||
!blocked) {
|
||||
set_bit(GLF_DEMOTE, &gl->gl_flags);
|
||||
gl->gl_demote_state = LM_ST_UNLOCKED;
|
||||
}
|
||||
gl->gl_waiters2 = 0;
|
||||
clear_bit(GLF_WAITERS2, &gl->gl_flags);
|
||||
} else if (!list_empty(&gl->gl_waiters3)) {
|
||||
gh = list_entry(gl->gl_waiters3.next,
|
||||
struct gfs2_holder, gh_list);
|
||||
@ -710,7 +719,7 @@ static void handle_callback(struct gfs2_glock *gl, unsigned int state,
|
||||
} else if (gl->gl_demote_state != LM_ST_UNLOCKED &&
|
||||
gl->gl_demote_state != state) {
|
||||
if (test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags))
|
||||
gl->gl_waiters2 = 1;
|
||||
set_bit(GLF_WAITERS2, &gl->gl_flags);
|
||||
else
|
||||
gl->gl_demote_state = LM_ST_UNLOCKED;
|
||||
}
|
||||
@ -742,6 +751,43 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state)
|
||||
gl->gl_tchange = jiffies;
|
||||
}
|
||||
|
||||
/**
|
||||
* drop_bh - Called after a lock module unlock completes
|
||||
* @gl: the glock
|
||||
* @ret: the return status
|
||||
*
|
||||
* Doesn't wake up the process waiting on the struct gfs2_holder (if any)
|
||||
* Doesn't drop the reference on the glock the top half took out
|
||||
*
|
||||
*/
|
||||
|
||||
static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
|
||||
{
|
||||
struct gfs2_sbd *sdp = gl->gl_sbd;
|
||||
struct gfs2_holder *gh = gl->gl_req_gh;
|
||||
|
||||
gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
|
||||
gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
|
||||
gfs2_assert_warn(sdp, !ret);
|
||||
|
||||
state_change(gl, LM_ST_UNLOCKED);
|
||||
|
||||
if (test_and_clear_bit(GLF_CONV_DEADLK, &gl->gl_flags)) {
|
||||
spin_lock(&gl->gl_spin);
|
||||
gh->gh_error = 0;
|
||||
spin_unlock(&gl->gl_spin);
|
||||
gfs2_glock_xmote_th(gl, gl->gl_req_gh);
|
||||
gfs2_glock_put(gl);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock(&gl->gl_spin);
|
||||
gfs2_demote_wake(gl);
|
||||
clear_bit(GLF_LOCK, &gl->gl_flags);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
gfs2_glock_put(gl);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmote_bh - Called after the lock module is done acquiring a lock
|
||||
* @gl: The glock in question
|
||||
@ -754,25 +800,19 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
|
||||
struct gfs2_sbd *sdp = gl->gl_sbd;
|
||||
const struct gfs2_glock_operations *glops = gl->gl_ops;
|
||||
struct gfs2_holder *gh = gl->gl_req_gh;
|
||||
int prev_state = gl->gl_state;
|
||||
int op_done = 1;
|
||||
|
||||
if (!gh && (ret & LM_OUT_ST_MASK) == LM_ST_UNLOCKED) {
|
||||
drop_bh(gl, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
|
||||
gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
|
||||
gfs2_assert_warn(sdp, !(ret & LM_OUT_ASYNC));
|
||||
|
||||
state_change(gl, ret & LM_OUT_ST_MASK);
|
||||
|
||||
if (prev_state != LM_ST_UNLOCKED && !(ret & LM_OUT_CACHEABLE)) {
|
||||
if (glops->go_inval)
|
||||
glops->go_inval(gl, DIO_METADATA);
|
||||
} else if (gl->gl_state == LM_ST_DEFERRED) {
|
||||
/* We might not want to do this here.
|
||||
Look at moving to the inode glops. */
|
||||
if (glops->go_inval)
|
||||
glops->go_inval(gl, 0);
|
||||
}
|
||||
|
||||
/* Deal with each possible exit condition */
|
||||
|
||||
if (!gh) {
|
||||
@ -782,7 +822,6 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
|
||||
} else {
|
||||
spin_lock(&gl->gl_spin);
|
||||
if (gl->gl_state != gl->gl_demote_state) {
|
||||
gl->gl_req_bh = NULL;
|
||||
spin_unlock(&gl->gl_spin);
|
||||
gfs2_glock_drop_th(gl);
|
||||
gfs2_glock_put(gl);
|
||||
@ -793,6 +832,14 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
|
||||
}
|
||||
} else {
|
||||
spin_lock(&gl->gl_spin);
|
||||
if (ret & LM_OUT_CONV_DEADLK) {
|
||||
gh->gh_error = 0;
|
||||
set_bit(GLF_CONV_DEADLK, &gl->gl_flags);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
gfs2_glock_drop_th(gl);
|
||||
gfs2_glock_put(gl);
|
||||
return;
|
||||
}
|
||||
list_del_init(&gh->gh_list);
|
||||
gh->gh_error = -EIO;
|
||||
if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
|
||||
@ -824,7 +871,6 @@ out:
|
||||
if (op_done) {
|
||||
spin_lock(&gl->gl_spin);
|
||||
gl->gl_req_gh = NULL;
|
||||
gl->gl_req_bh = NULL;
|
||||
clear_bit(GLF_LOCK, &gl->gl_flags);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
}
|
||||
@ -835,6 +881,17 @@ out:
|
||||
gfs2_holder_wake(gh);
|
||||
}
|
||||
|
||||
static 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_glock_xmote_th - Call into the lock module to acquire or change a glock
|
||||
* @gl: The glock in question
|
||||
@ -856,6 +913,8 @@ static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
|
||||
|
||||
if (glops->go_xmote_th)
|
||||
glops->go_xmote_th(gl);
|
||||
if (state == LM_ST_DEFERRED && glops->go_inval)
|
||||
glops->go_inval(gl, DIO_METADATA);
|
||||
|
||||
gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
|
||||
gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
|
||||
@ -863,7 +922,6 @@ static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
|
||||
gfs2_assert_warn(sdp, state != gl->gl_state);
|
||||
|
||||
gfs2_glock_hold(gl);
|
||||
gl->gl_req_bh = xmote_bh;
|
||||
|
||||
lck_ret = gfs2_lm_lock(sdp, gl->gl_lock, gl->gl_state, state, lck_flags);
|
||||
|
||||
@ -876,49 +934,13 @@ static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
|
||||
xmote_bh(gl, lck_ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* drop_bh - Called after a lock module unlock completes
|
||||
* @gl: the glock
|
||||
* @ret: the return status
|
||||
*
|
||||
* Doesn't wake up the process waiting on the struct gfs2_holder (if any)
|
||||
* Doesn't drop the reference on the glock the top half took out
|
||||
*
|
||||
*/
|
||||
|
||||
static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
|
||||
static unsigned int gfs2_lm_unlock(struct gfs2_sbd *sdp, void *lock,
|
||||
unsigned int cur_state)
|
||||
{
|
||||
struct gfs2_sbd *sdp = gl->gl_sbd;
|
||||
const struct gfs2_glock_operations *glops = gl->gl_ops;
|
||||
struct gfs2_holder *gh = gl->gl_req_gh;
|
||||
|
||||
gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
|
||||
gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
|
||||
gfs2_assert_warn(sdp, !ret);
|
||||
|
||||
state_change(gl, LM_ST_UNLOCKED);
|
||||
|
||||
if (glops->go_inval)
|
||||
glops->go_inval(gl, DIO_METADATA);
|
||||
|
||||
if (gh) {
|
||||
spin_lock(&gl->gl_spin);
|
||||
list_del_init(&gh->gh_list);
|
||||
gh->gh_error = 0;
|
||||
spin_unlock(&gl->gl_spin);
|
||||
}
|
||||
|
||||
spin_lock(&gl->gl_spin);
|
||||
gfs2_demote_wake(gl);
|
||||
gl->gl_req_gh = NULL;
|
||||
gl->gl_req_bh = NULL;
|
||||
clear_bit(GLF_LOCK, &gl->gl_flags);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
|
||||
gfs2_glock_put(gl);
|
||||
|
||||
if (gh)
|
||||
gfs2_holder_wake(gh);
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -935,13 +957,14 @@ static void gfs2_glock_drop_th(struct gfs2_glock *gl)
|
||||
|
||||
if (glops->go_xmote_th)
|
||||
glops->go_xmote_th(gl);
|
||||
if (glops->go_inval)
|
||||
glops->go_inval(gl, DIO_METADATA);
|
||||
|
||||
gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
|
||||
gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
|
||||
gfs2_assert_warn(sdp, gl->gl_state != LM_ST_UNLOCKED);
|
||||
|
||||
gfs2_glock_hold(gl);
|
||||
gl->gl_req_bh = drop_bh;
|
||||
|
||||
ret = gfs2_lm_unlock(sdp, gl->gl_lock, gl->gl_state);
|
||||
|
||||
@ -964,16 +987,17 @@ static void gfs2_glock_drop_th(struct gfs2_glock *gl)
|
||||
static void do_cancels(struct gfs2_holder *gh)
|
||||
{
|
||||
struct gfs2_glock *gl = gh->gh_gl;
|
||||
struct gfs2_sbd *sdp = gl->gl_sbd;
|
||||
|
||||
spin_lock(&gl->gl_spin);
|
||||
|
||||
while (gl->gl_req_gh != gh &&
|
||||
!test_bit(HIF_HOLDER, &gh->gh_iflags) &&
|
||||
!list_empty(&gh->gh_list)) {
|
||||
if (gl->gl_req_bh && !(gl->gl_req_gh &&
|
||||
(gl->gl_req_gh->gh_flags & GL_NOCANCEL))) {
|
||||
if (!(gl->gl_req_gh && (gl->gl_req_gh->gh_flags & GL_NOCANCEL))) {
|
||||
spin_unlock(&gl->gl_spin);
|
||||
gfs2_lm_cancel(gl->gl_sbd, gl->gl_lock);
|
||||
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
|
||||
sdp->sd_lockstruct.ls_ops->lm_cancel(gl->gl_lock);
|
||||
msleep(100);
|
||||
spin_lock(&gl->gl_spin);
|
||||
} else {
|
||||
@ -1041,7 +1065,6 @@ static int glock_wait_internal(struct gfs2_holder *gh)
|
||||
|
||||
spin_lock(&gl->gl_spin);
|
||||
gl->gl_req_gh = NULL;
|
||||
gl->gl_req_bh = NULL;
|
||||
clear_bit(GLF_LOCK, &gl->gl_flags);
|
||||
run_queue(gl);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
@ -1428,6 +1451,14 @@ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs)
|
||||
gfs2_glock_dq_uninit(&ghs[x]);
|
||||
}
|
||||
|
||||
static 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_lvb_hold - attach a LVB from a glock
|
||||
* @gl: The glock in question
|
||||
@ -1463,12 +1494,15 @@ int gfs2_lvb_hold(struct gfs2_glock *gl)
|
||||
|
||||
void gfs2_lvb_unhold(struct gfs2_glock *gl)
|
||||
{
|
||||
struct gfs2_sbd *sdp = gl->gl_sbd;
|
||||
|
||||
gfs2_glock_hold(gl);
|
||||
gfs2_glmutex_lock(gl);
|
||||
|
||||
gfs2_assert(gl->gl_sbd, atomic_read(&gl->gl_lvb_count) > 0);
|
||||
if (atomic_dec_and_test(&gl->gl_lvb_count)) {
|
||||
gfs2_lm_unhold_lvb(gl->gl_sbd, gl->gl_lock, gl->gl_lvb);
|
||||
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
|
||||
sdp->sd_lockstruct.ls_ops->lm_unhold_lvb(gl->gl_lock, gl->gl_lvb);
|
||||
gl->gl_lvb = NULL;
|
||||
gfs2_glock_put(gl);
|
||||
}
|
||||
@ -1534,8 +1568,7 @@ void gfs2_glock_cb(void *cb_data, unsigned int type, void *data)
|
||||
gl = gfs2_glock_find(sdp, &async->lc_name);
|
||||
if (gfs2_assert_warn(sdp, gl))
|
||||
return;
|
||||
if (!gfs2_assert_warn(sdp, gl->gl_req_bh))
|
||||
gl->gl_req_bh(gl, async->lc_ret);
|
||||
xmote_bh(gl, async->lc_ret);
|
||||
if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
|
||||
gfs2_glock_put(gl);
|
||||
up_read(&gfs2_umount_flush_sem);
|
||||
@ -1594,10 +1627,10 @@ void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl)
|
||||
gfs2_glock_hold(gl);
|
||||
list_add(&gl->gl_reclaim, &sdp->sd_reclaim_list);
|
||||
atomic_inc(&sdp->sd_reclaim_count);
|
||||
}
|
||||
spin_unlock(&sdp->sd_reclaim_lock);
|
||||
|
||||
wake_up(&sdp->sd_reclaim_wq);
|
||||
spin_unlock(&sdp->sd_reclaim_lock);
|
||||
wake_up(&sdp->sd_reclaim_wq);
|
||||
} else
|
||||
spin_unlock(&sdp->sd_reclaim_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1897,7 +1930,6 @@ static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl)
|
||||
print_dbg(gi, " gl_owner = -1\n");
|
||||
print_dbg(gi, " gl_ip = %lu\n", gl->gl_ip);
|
||||
print_dbg(gi, " req_gh = %s\n", (gl->gl_req_gh) ? "yes" : "no");
|
||||
print_dbg(gi, " req_bh = %s\n", (gl->gl_req_bh) ? "yes" : "no");
|
||||
print_dbg(gi, " lvb_count = %d\n", atomic_read(&gl->gl_lvb_count));
|
||||
print_dbg(gi, " object = %s\n", (gl->gl_object) ? "yes" : "no");
|
||||
print_dbg(gi, " reclaim = %s\n",
|
||||
|
@ -32,24 +32,23 @@
|
||||
#define GLR_TRYFAILED 13
|
||||
#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;
|
||||
int locked = 0;
|
||||
struct pid *pid;
|
||||
|
||||
/* Look in glock's list of holders for one with current task as owner */
|
||||
spin_lock(&gl->gl_spin);
|
||||
pid = task_pid(current);
|
||||
list_for_each_entry(gh, &gl->gl_holders, gh_list) {
|
||||
if (gh->gh_owner_pid == pid) {
|
||||
locked = 1;
|
||||
break;
|
||||
}
|
||||
if (gh->gh_owner_pid == pid)
|
||||
goto out;
|
||||
}
|
||||
gh = NULL;
|
||||
out:
|
||||
spin_unlock(&gl->gl_spin);
|
||||
|
||||
return locked;
|
||||
return gh;
|
||||
}
|
||||
|
||||
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)
|
||||
int gfs2_glock_get(struct gfs2_sbd *sdp,
|
||||
u64 number, const struct gfs2_glock_operations *glops,
|
||||
int create, struct gfs2_glock **glp);
|
||||
void gfs2_glock_hold(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,
|
||||
struct gfs2_holder *gh);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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,
|
||||
* 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)
|
||||
return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
@ -44,7 +44,6 @@ struct gfs2_log_header_host {
|
||||
|
||||
struct gfs2_log_operations {
|
||||
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_after_commit) (struct gfs2_sbd *sdp, struct gfs2_ail *ai);
|
||||
void (*lo_before_scan) (struct gfs2_jdesc *jd,
|
||||
@ -70,7 +69,6 @@ struct gfs2_bitmap {
|
||||
};
|
||||
|
||||
struct gfs2_rgrp_host {
|
||||
u32 rg_flags;
|
||||
u32 rg_free;
|
||||
u32 rg_dinodes;
|
||||
u64 rg_igeneration;
|
||||
@ -87,17 +85,17 @@ struct gfs2_rgrpd {
|
||||
u32 rd_data; /* num of data blocks in rgrp */
|
||||
u32 rd_bitbytes; /* number of bytes in data bitmaps */
|
||||
struct gfs2_rgrp_host rd_rg;
|
||||
u64 rd_rg_vn;
|
||||
struct gfs2_bitmap *rd_bits;
|
||||
unsigned int rd_bh_count;
|
||||
struct mutex rd_mutex;
|
||||
u32 rd_free_clone;
|
||||
struct gfs2_log_element rd_le;
|
||||
u32 rd_last_alloc_data;
|
||||
u32 rd_last_alloc_meta;
|
||||
u32 rd_last_alloc;
|
||||
struct gfs2_sbd *rd_sbd;
|
||||
unsigned long rd_flags;
|
||||
#define GFS2_RDF_CHECK 0x0001 /* Need to check for unlinked inodes */
|
||||
unsigned char rd_flags;
|
||||
#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 {
|
||||
@ -168,6 +166,8 @@ enum {
|
||||
GLF_DIRTY = 5,
|
||||
GLF_DEMOTE_IN_PROGRESS = 6,
|
||||
GLF_LFLUSH = 7,
|
||||
GLF_WAITERS2 = 8,
|
||||
GLF_CONV_DEADLK = 9,
|
||||
};
|
||||
|
||||
struct gfs2_glock {
|
||||
@ -187,18 +187,15 @@ struct gfs2_glock {
|
||||
struct list_head gl_holders;
|
||||
struct list_head gl_waiters1; /* HIF_MUTEX */
|
||||
struct list_head gl_waiters3; /* HIF_PROMOTE */
|
||||
int gl_waiters2; /* GIF_DEMOTE */
|
||||
|
||||
const struct gfs2_glock_operations *gl_ops;
|
||||
|
||||
struct gfs2_holder *gl_req_gh;
|
||||
gfs2_glop_bh_t gl_req_bh;
|
||||
|
||||
void *gl_lock;
|
||||
char *gl_lvb;
|
||||
atomic_t gl_lvb_count;
|
||||
|
||||
u64 gl_vn;
|
||||
unsigned long gl_stamp;
|
||||
unsigned long gl_tchange;
|
||||
void *gl_object;
|
||||
@ -213,6 +210,8 @@ struct gfs2_glock {
|
||||
struct delayed_work gl_work;
|
||||
};
|
||||
|
||||
#define GFS2_MIN_LVB_SIZE 32 /* Min size of LVB that gfs2 supports */
|
||||
|
||||
struct gfs2_alloc {
|
||||
/* Quota stuff */
|
||||
|
||||
@ -241,14 +240,9 @@ enum {
|
||||
|
||||
struct gfs2_dinode_host {
|
||||
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 */
|
||||
u32 di_flags; /* GFS2_DIF_... */
|
||||
u16 di_height; /* height of metadata */
|
||||
/* These only apply to directories */
|
||||
u16 di_depth; /* Number of bits in the table */
|
||||
u32 di_entries; /* The number of entries in the directory */
|
||||
u64 di_eattr; /* extended attribute block number */
|
||||
};
|
||||
@ -265,9 +259,10 @@ struct gfs2_inode {
|
||||
struct gfs2_holder i_iopen_gh;
|
||||
struct gfs2_holder i_gh; /* for prepare/commit_write only */
|
||||
struct gfs2_alloc *i_alloc;
|
||||
u64 i_last_rg_alloc;
|
||||
|
||||
u64 i_goal; /* goal block for allocations */
|
||||
struct rw_semaphore i_rw_mutex;
|
||||
u8 i_height;
|
||||
u8 i_depth;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -490,9 +485,9 @@ struct gfs2_sbd {
|
||||
u32 sd_qc_per_block;
|
||||
u32 sd_max_dirres; /* Max blocks needed to add a directory entry */
|
||||
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 */
|
||||
u64 sd_jheightsize[GFS2_MAX_META_HEIGHT];
|
||||
u64 sd_jheightsize[GFS2_MAX_META_HEIGHT + 1];
|
||||
|
||||
struct gfs2_args sd_args; /* Mount arguments */
|
||||
struct gfs2_tune sd_tune; /* Filesystem tuning structure */
|
||||
@ -533,7 +528,7 @@ struct gfs2_sbd {
|
||||
|
||||
/* Resource group stuff */
|
||||
|
||||
u64 sd_rindex_vn;
|
||||
int sd_rindex_uptodate;
|
||||
spinlock_t sd_rindex_spin;
|
||||
struct mutex sd_rindex_mutex;
|
||||
struct list_head sd_rindex_list;
|
||||
@ -637,9 +632,6 @@ struct gfs2_sbd {
|
||||
|
||||
/* Counters */
|
||||
|
||||
atomic_t sd_glock_count;
|
||||
atomic_t sd_glock_held_count;
|
||||
atomic_t sd_inode_count;
|
||||
atomic_t sd_reclaimed;
|
||||
|
||||
char sd_fsname[GFS2_FSNAME_LEN];
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
@ -149,7 +149,8 @@ void gfs2_set_iop(struct inode *inode)
|
||||
} else if (S_ISLNK(mode)) {
|
||||
inode->i_op = &gfs2_symlink_iops;
|
||||
} 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);
|
||||
@ -248,12 +249,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
|
||||
{
|
||||
struct gfs2_dinode_host *di = &ip->i_di;
|
||||
const struct gfs2_dinode *str = buf;
|
||||
u16 height, depth;
|
||||
|
||||
if (ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)) {
|
||||
if (gfs2_consist_inode(ip))
|
||||
gfs2_dinode_print(ip);
|
||||
return -EIO;
|
||||
}
|
||||
if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)))
|
||||
goto corrupt;
|
||||
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_rdev = 0;
|
||||
@ -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);
|
||||
di->di_size = be64_to_cpu(str->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);
|
||||
gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
|
||||
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_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)
|
||||
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);
|
||||
|
||||
di->di_goal_meta = be64_to_cpu(str->di_goal_meta);
|
||||
di->di_goal_data = be64_to_cpu(str->di_goal_data);
|
||||
ip->i_goal = be64_to_cpu(str->di_goal_meta);
|
||||
di->di_generation = be64_to_cpu(str->di_generation);
|
||||
|
||||
di->di_flags = be32_to_cpu(str->di_flags);
|
||||
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))
|
||||
goto corrupt;
|
||||
ip->i_height = (u8)height;
|
||||
|
||||
di->di_depth = be16_to_cpu(str->di_depth);
|
||||
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_eattr = be64_to_cpu(str->di_eattr);
|
||||
@ -300,6 +303,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
|
||||
gfs2_set_aops(&ip->i_inode);
|
||||
|
||||
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)
|
||||
struct gfs2_rgrpd *rgd;
|
||||
int error;
|
||||
|
||||
if (ip->i_di.di_blocks != 1) {
|
||||
if (gfs2_get_inode_blocks(&ip->i_inode) != 1) {
|
||||
if (gfs2_consist_inode(ip))
|
||||
gfs2_dinode_print(ip);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
al = gfs2_alloc_get(ip);
|
||||
if (!al)
|
||||
return -ENOMEM;
|
||||
|
||||
error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
|
||||
if (error)
|
||||
@ -487,7 +496,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
|
||||
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);
|
||||
if (error)
|
||||
return ERR_PTR(error);
|
||||
@ -818,7 +827,8 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
|
||||
int error;
|
||||
|
||||
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);
|
||||
if (error)
|
||||
@ -853,6 +863,8 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
|
||||
int error;
|
||||
|
||||
al = gfs2_alloc_get(dip);
|
||||
if (!al)
|
||||
return -ENOMEM;
|
||||
|
||||
error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
|
||||
if (error)
|
||||
@ -1219,7 +1231,7 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len)
|
||||
|
||||
x = ip->i_di.di_size + 1;
|
||||
if (x > *len) {
|
||||
*buf = kmalloc(x, GFP_KERNEL);
|
||||
*buf = kmalloc(x, GFP_NOFS);
|
||||
if (!*buf) {
|
||||
error = -ENOMEM;
|
||||
goto out_brelse;
|
||||
@ -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_nlink = cpu_to_be32(ip->i_inode.i_nlink);
|
||||
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_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_goal_meta = cpu_to_be64(di->di_goal_meta);
|
||||
str->di_goal_data = cpu_to_be64(di->di_goal_data);
|
||||
str->di_goal_meta = cpu_to_be64(ip->i_goal);
|
||||
str->di_goal_data = cpu_to_be64(ip->i_goal);
|
||||
str->di_generation = cpu_to_be64(di->di_generation);
|
||||
|
||||
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) &&
|
||||
!(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?
|
||||
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_eattr = cpu_to_be64(di->di_eattr);
|
||||
@ -1423,15 +1435,13 @@ void gfs2_dinode_print(const struct gfs2_inode *ip)
|
||||
printk(KERN_INFO " no_addr = %llu\n",
|
||||
(unsigned long long)ip->i_no_addr);
|
||||
printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size);
|
||||
printk(KERN_INFO " di_blocks = %llu\n",
|
||||
(unsigned long long)di->di_blocks);
|
||||
printk(KERN_INFO " di_goal_meta = %llu\n",
|
||||
(unsigned long long)di->di_goal_meta);
|
||||
printk(KERN_INFO " di_goal_data = %llu\n",
|
||||
(unsigned long long)di->di_goal_data);
|
||||
printk(KERN_INFO " blocks = %llu\n",
|
||||
(unsigned long long)gfs2_get_inode_blocks(&ip->i_inode));
|
||||
printk(KERN_INFO " i_goal = %llu\n",
|
||||
(unsigned long long)ip->i_goal);
|
||||
printk(KERN_INFO " di_flags = 0x%.8X\n", di->di_flags);
|
||||
printk(KERN_INFO " di_height = %u\n", di->di_height);
|
||||
printk(KERN_INFO " di_depth = %u\n", di->di_depth);
|
||||
printk(KERN_INFO " i_height = %u\n", ip->i_height);
|
||||
printk(KERN_INFO " i_depth = %u\n", ip->i_depth);
|
||||
printk(KERN_INFO " di_entries = %u\n", di->di_entries);
|
||||
printk(KERN_INFO " di_eattr = %llu\n",
|
||||
(unsigned long long)di->di_eattr);
|
||||
|
@ -10,9 +10,11 @@
|
||||
#ifndef __INODE_DOT_H__
|
||||
#define __INODE_DOT_H__
|
||||
|
||||
#include "util.h"
|
||||
|
||||
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)
|
||||
@ -37,13 +39,25 @@ static inline int gfs2_is_dir(const struct gfs2_inode *ip)
|
||||
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)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
inode->i_blocks = ip->i_di.di_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)
|
||||
{
|
||||
return inode->i_blocks >>
|
||||
(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,
|
||||
u64 no_formal_ino)
|
||||
{
|
||||
|
210
fs/gfs2/lm.c
210
fs/gfs2/lm.c
@ -1,210 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
42
fs/gfs2/lm.h
42
fs/gfs2/lm.h
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* 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,
|
||||
|
||||
/* 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) &&
|
||||
cur > DLM_LOCK_NL && req > DLM_LOCK_NL && cur != req)
|
||||
lkf |= DLM_LKF_CONVDEADLK;
|
||||
@ -164,7 +165,7 @@ static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name,
|
||||
{
|
||||
struct gdlm_lock *lp;
|
||||
|
||||
lp = kzalloc(sizeof(struct gdlm_lock), GFP_KERNEL);
|
||||
lp = kzalloc(sizeof(struct gdlm_lock), GFP_NOFS);
|
||||
if (!lp)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -382,7 +383,7 @@ static int gdlm_add_lvb(struct gdlm_lock *lp)
|
||||
{
|
||||
char *lvb;
|
||||
|
||||
lvb = kzalloc(GDLM_LVB_SIZE, GFP_KERNEL);
|
||||
lvb = kzalloc(GDLM_LVB_SIZE, GFP_NOFS);
|
||||
if (!lvb)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -183,5 +183,10 @@ int gdlm_plock_get(void *, struct lm_lockname *, struct file *,
|
||||
struct file_lock *);
|
||||
int gdlm_punlock(void *, struct lm_lockname *, struct file *,
|
||||
struct file_lock *);
|
||||
|
||||
/* mount.c */
|
||||
|
||||
extern const struct lm_lockops gdlm_ops;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -11,8 +11,6 @@
|
||||
|
||||
#include "lock_dlm.h"
|
||||
|
||||
extern struct lm_lockops gdlm_ops;
|
||||
|
||||
static int __init init_lock_dlm(void)
|
||||
{
|
||||
int error;
|
||||
|
@ -12,8 +12,6 @@
|
||||
|
||||
#include "lock_dlm.h"
|
||||
|
||||
extern struct lm_lockops gdlm_ops;
|
||||
|
||||
static ssize_t proto_name_show(struct gdlm_ls *ls, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%s\n", gdlm_ops.lm_proto_name);
|
||||
|
@ -135,7 +135,15 @@ static void process_complete(struct gdlm_lock *lp)
|
||||
lp->lksb.sb_status, lp->lockname.ln_type,
|
||||
(unsigned long long)lp->lockname.ln_number,
|
||||
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)
|
||||
struct nolock_lockspace *nl = lock;
|
||||
int error = 0;
|
||||
|
||||
*lvbp = kzalloc(nl->nl_lvb_size, GFP_KERNEL);
|
||||
*lvbp = kzalloc(nl->nl_lvb_size, GFP_NOFS);
|
||||
if (!*lvbp)
|
||||
error = -ENOMEM;
|
||||
|
||||
|
@ -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;
|
||||
gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0);
|
||||
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;
|
||||
gfs2_assert_withdraw(sdp, unused >= 0);
|
||||
atomic_add(unused, &sdp->sd_log_blks_free);
|
||||
gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <=
|
||||
sdp->sd_jdesc->jd_blocks);
|
||||
@ -779,6 +779,21 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
|
||||
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
|
||||
* @sdp: the filesystem
|
||||
@ -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)
|
||||
{
|
||||
log_refund(sdp, tr);
|
||||
lops_incore_commit(sdp, tr);
|
||||
buf_lo_incore_commit(sdp, tr);
|
||||
|
||||
sdp->sd_vfs->s_dirt = 1;
|
||||
up_read(&sdp->sd_log_flush_lock);
|
||||
|
@ -152,21 +152,6 @@ out:
|
||||
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)
|
||||
{
|
||||
struct buffer_head *bh;
|
||||
@ -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));
|
||||
|
||||
error = gfs2_revoke_add(sdp, blkno, start);
|
||||
if (error < 0)
|
||||
if (error < 0) {
|
||||
brelse(bh);
|
||||
return error;
|
||||
}
|
||||
else if (error)
|
||||
sdp->sd_found_revokes++;
|
||||
|
||||
@ -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 = {
|
||||
.lo_add = buf_lo_add,
|
||||
.lo_incore_commit = buf_lo_incore_commit,
|
||||
.lo_before_commit = buf_lo_before_commit,
|
||||
.lo_after_commit = buf_lo_after_commit,
|
||||
.lo_before_scan = buf_lo_before_scan,
|
||||
@ -763,7 +749,6 @@ const struct gfs2_log_operations gfs2_rg_lops = {
|
||||
|
||||
const struct gfs2_log_operations gfs2_databuf_lops = {
|
||||
.lo_add = databuf_lo_add,
|
||||
.lo_incore_commit = buf_lo_incore_commit,
|
||||
.lo_before_commit = databuf_lo_before_commit,
|
||||
.lo_after_commit = databuf_lo_after_commit,
|
||||
.lo_scan_elements = databuf_lo_scan_elements,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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,
|
||||
* 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)
|
||||
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)
|
||||
{
|
||||
int x;
|
||||
|
@ -89,6 +89,12 @@ static int __init init_gfs2_fs(void)
|
||||
if (!gfs2_bufdata_cachep)
|
||||
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);
|
||||
if (error)
|
||||
goto fail;
|
||||
@ -108,6 +114,9 @@ fail_unregister:
|
||||
fail:
|
||||
gfs2_glock_exit();
|
||||
|
||||
if (gfs2_rgrpd_cachep)
|
||||
kmem_cache_destroy(gfs2_rgrpd_cachep);
|
||||
|
||||
if (gfs2_bufdata_cachep)
|
||||
kmem_cache_destroy(gfs2_bufdata_cachep);
|
||||
|
||||
@ -133,6 +142,7 @@ static void __exit exit_gfs2_fs(void)
|
||||
unregister_filesystem(&gfs2_fs_type);
|
||||
unregister_filesystem(&gfs2meta_fs_type);
|
||||
|
||||
kmem_cache_destroy(gfs2_rgrpd_cachep);
|
||||
kmem_cache_destroy(gfs2_bufdata_cachep);
|
||||
kmem_cache_destroy(gfs2_inode_cachep);
|
||||
kmem_cache_destroy(gfs2_glock_cachep);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
@ -21,7 +21,6 @@
|
||||
#include <linux/gfs2_ondisk.h>
|
||||
#include <linux/lm_interface.h>
|
||||
#include <linux/backing-dev.h>
|
||||
#include <linux/pagevec.h>
|
||||
|
||||
#include "gfs2.h"
|
||||
#include "incore.h"
|
||||
@ -104,11 +103,9 @@ static int gfs2_writepage_common(struct page *page,
|
||||
loff_t i_size = i_size_read(inode);
|
||||
pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
|
||||
unsigned offset;
|
||||
int ret = -EIO;
|
||||
|
||||
if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl)))
|
||||
goto out;
|
||||
ret = 0;
|
||||
if (current->journal_info)
|
||||
goto redirty;
|
||||
/* Is the page fully outside i_size? (truncate in progress) */
|
||||
@ -280,7 +277,7 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping,
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
ret = gfs2_trans_begin(sdp, nrblocks, 0);
|
||||
ret = gfs2_trans_begin(sdp, nrblocks, nrblocks);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -510,23 +507,26 @@ static int __gfs2_readpage(void *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_holder gh;
|
||||
struct gfs2_holder *gh;
|
||||
int error;
|
||||
|
||||
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh);
|
||||
error = gfs2_glock_nq_atime(&gh);
|
||||
if (unlikely(error)) {
|
||||
gh = gfs2_glock_is_locked_by_me(ip->i_gl);
|
||||
if (!gh) {
|
||||
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);
|
||||
goto out;
|
||||
}
|
||||
error = __gfs2_readpage(file, page);
|
||||
gfs2_glock_dq(&gh);
|
||||
out:
|
||||
gfs2_holder_uninit(&gh);
|
||||
if (error == GLR_TRYFAILED) {
|
||||
yield();
|
||||
error = gfs2_glock_nq_atime(gh);
|
||||
if (likely(error != 0))
|
||||
goto out;
|
||||
return AOP_TRUNCATED_PAGE;
|
||||
}
|
||||
error = __gfs2_readpage(file, page);
|
||||
gfs2_glock_dq(gh);
|
||||
out:
|
||||
gfs2_holder_uninit(gh);
|
||||
kfree(gh);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -648,15 +648,15 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
|
||||
|
||||
if (alloc_required) {
|
||||
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)
|
||||
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;
|
||||
error = gfs2_inplace_reserve(ip);
|
||||
if (error)
|
||||
@ -828,7 +828,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
|
||||
unsigned int to = from + len;
|
||||
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);
|
||||
if (unlikely(ret)) {
|
||||
|
@ -43,7 +43,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
struct gfs2_holder d_gh;
|
||||
struct gfs2_inode *ip = NULL;
|
||||
int error;
|
||||
int had_lock=0;
|
||||
int had_lock = 0;
|
||||
|
||||
if (inode) {
|
||||
if (is_bad_inode(inode))
|
||||
@ -54,7 +54,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
if (sdp->sd_args.ar_localcaching)
|
||||
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) {
|
||||
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
|
||||
if (error)
|
||||
|
@ -204,8 +204,6 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb,
|
||||
inode = gfs2_inode_lookup(sb, DT_UNKNOWN,
|
||||
inum->no_addr,
|
||||
0, 0);
|
||||
if (!inode)
|
||||
goto fail;
|
||||
if (IS_ERR(inode)) {
|
||||
error = PTR_ERR(inode);
|
||||
goto fail;
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "glock.h"
|
||||
#include "glops.h"
|
||||
#include "inode.h"
|
||||
#include "lm.h"
|
||||
#include "log.h"
|
||||
#include "meta_io.h"
|
||||
#include "quota.h"
|
||||
@ -39,6 +38,7 @@
|
||||
#include "util.h"
|
||||
#include "eaops.h"
|
||||
#include "ops_address.h"
|
||||
#include "ops_inode.h"
|
||||
|
||||
/**
|
||||
* 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)
|
||||
if (al == NULL)
|
||||
goto out_unlock;
|
||||
|
||||
ret = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
|
||||
ret = gfs2_quota_lock_check(ip);
|
||||
if (ret)
|
||||
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;
|
||||
ret = gfs2_inplace_reserve(ip);
|
||||
if (ret)
|
||||
@ -596,6 +593,36 @@ static int gfs2_setlease(struct file *file, long arg, struct file_lock **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
|
||||
* @file: the file pointer
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
@ -26,7 +26,6 @@
|
||||
#include "glock.h"
|
||||
#include "glops.h"
|
||||
#include "inode.h"
|
||||
#include "lm.h"
|
||||
#include "mount.h"
|
||||
#include "ops_fstype.h"
|
||||
#include "ops_dentry.h"
|
||||
@ -363,6 +362,13 @@ static int map_journal_extents(struct gfs2_sbd *sdp)
|
||||
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)
|
||||
{
|
||||
struct gfs2_holder ji_gh;
|
||||
@ -542,7 +548,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
|
||||
}
|
||||
ip = GFS2_I(sdp->sd_rindex);
|
||||
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 */
|
||||
sdp->sd_quota_inode = gfs2_lookup_simple(sdp->sd_master_dir, "quota");
|
||||
@ -704,6 +710,69 @@ fail:
|
||||
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
|
||||
* @sb: The VFS superblock
|
||||
@ -874,7 +943,6 @@ static struct super_block* get_gfs2_sb(const char *dev_name)
|
||||
{
|
||||
struct kstat stat;
|
||||
struct nameidata nd;
|
||||
struct file_system_type *fstype;
|
||||
struct super_block *sb = NULL, *s;
|
||||
int error;
|
||||
|
||||
@ -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);
|
||||
|
||||
fstype = get_fs_type("gfs2");
|
||||
list_for_each_entry(s, &fstype->fs_supers, s_instances) {
|
||||
list_for_each_entry(s, &gfs2_fs_type.fs_supers, s_instances) {
|
||||
if ((S_ISBLK(stat.mode) && s->s_dev == stat.rdev) ||
|
||||
(S_ISDIR(stat.mode) &&
|
||||
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,
|
||||
error = PTR_ERR(new);
|
||||
goto error;
|
||||
}
|
||||
module_put(fs_type->owner);
|
||||
new->s_flags = flags;
|
||||
strlcpy(new->s_id, sb->s_id, sizeof(new->s_id));
|
||||
sb_set_blocksize(new, sb->s_blocksize);
|
||||
|
@ -200,15 +200,15 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
|
||||
|
||||
if (alloc_required) {
|
||||
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)
|
||||
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;
|
||||
|
||||
error = gfs2_inplace_reserve(dip);
|
||||
@ -716,15 +716,15 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
|
||||
|
||||
if (alloc_required) {
|
||||
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)
|
||||
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;
|
||||
|
||||
error = gfs2_inplace_reserve(ndip);
|
||||
@ -898,7 +898,7 @@ static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd)
|
||||
int error;
|
||||
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);
|
||||
if (error)
|
||||
return error;
|
||||
@ -953,7 +953,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
|
||||
if (!(attr->ia_valid & ATTR_GID) || ogid == ngid)
|
||||
ogid = ngid = NO_QUOTA_CHANGE;
|
||||
|
||||
gfs2_alloc_get(ip);
|
||||
if (!gfs2_alloc_get(ip))
|
||||
return -ENOMEM;
|
||||
|
||||
error = gfs2_quota_lock(ip, nuid, ngid);
|
||||
if (error)
|
||||
@ -981,8 +982,9 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
|
||||
brelse(dibh);
|
||||
|
||||
if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
|
||||
gfs2_quota_change(ip, -ip->i_di.di_blocks, ouid, ogid);
|
||||
gfs2_quota_change(ip, ip->i_di.di_blocks, nuid, ngid);
|
||||
u64 blocks = gfs2_get_inode_blocks(&ip->i_inode);
|
||||
gfs2_quota_change(ip, -blocks, ouid, ogid);
|
||||
gfs2_quota_change(ip, blocks, nuid, ngid);
|
||||
}
|
||||
|
||||
out_end_trans:
|
||||
@ -1064,7 +1066,7 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
int error;
|
||||
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);
|
||||
if (error)
|
||||
return error;
|
||||
@ -1148,16 +1150,6 @@ const struct inode_operations gfs2_file_iops = {
|
||||
.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 = {
|
||||
.create = gfs2_create,
|
||||
.lookup = gfs2_lookup,
|
||||
|
@ -15,7 +15,6 @@
|
||||
extern const struct inode_operations gfs2_file_iops;
|
||||
extern const struct inode_operations gfs2_dir_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_dir_fops;
|
||||
extern const struct file_operations gfs2_file_fops_nolock;
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "incore.h"
|
||||
#include "glock.h"
|
||||
#include "inode.h"
|
||||
#include "lm.h"
|
||||
#include "log.h"
|
||||
#include "mount.h"
|
||||
#include "ops_super.h"
|
||||
|
@ -94,7 +94,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id,
|
||||
struct gfs2_quota_data *qd;
|
||||
int error;
|
||||
|
||||
qd = kzalloc(sizeof(struct gfs2_quota_data), GFP_KERNEL);
|
||||
qd = kzalloc(sizeof(struct gfs2_quota_data), GFP_NOFS);
|
||||
if (!qd)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -616,16 +616,9 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
|
||||
s64 value;
|
||||
int err = -EIO;
|
||||
|
||||
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);
|
||||
if (gfs2_is_stuffed(ip))
|
||||
gfs2_unstuff_dinode(ip, NULL);
|
||||
gfs2_inplace_release(ip);
|
||||
gfs2_alloc_put(ip);
|
||||
}
|
||||
|
||||
page = grab_cache_page(mapping, index);
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
@ -690,14 +683,14 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
|
||||
unsigned int qx, x;
|
||||
struct gfs2_quota_data *qd;
|
||||
loff_t offset;
|
||||
unsigned int nalloc = 0;
|
||||
unsigned int nalloc = 0, blocks;
|
||||
struct gfs2_alloc *al = NULL;
|
||||
int error;
|
||||
|
||||
gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
|
||||
&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)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -727,30 +720,33 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
|
||||
nalloc++;
|
||||
}
|
||||
|
||||
if (nalloc) {
|
||||
al = gfs2_alloc_get(ip);
|
||||
|
||||
al->al_requested = nalloc * (data_blocks + ind_blocks);
|
||||
|
||||
error = gfs2_inplace_reserve(ip);
|
||||
if (error)
|
||||
goto out_alloc;
|
||||
|
||||
error = gfs2_trans_begin(sdp,
|
||||
al->al_rgd->rd_length +
|
||||
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;
|
||||
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;
|
||||
|
||||
if (nalloc)
|
||||
al->al_requested += nalloc * (data_blocks + ind_blocks);
|
||||
error = gfs2_inplace_reserve(ip);
|
||||
if (error)
|
||||
goto out_alloc;
|
||||
|
||||
if (nalloc)
|
||||
blocks += al->al_rgd->rd_length + nalloc * ind_blocks + RES_STATFS;
|
||||
|
||||
error = gfs2_trans_begin(sdp, blocks, 0);
|
||||
if (error)
|
||||
goto out_ipres;
|
||||
|
||||
for (x = 0; x < num_qd; x++) {
|
||||
qd = qda[x];
|
||||
@ -769,11 +765,9 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
|
||||
out_end_trans:
|
||||
gfs2_trans_end(sdp);
|
||||
out_ipres:
|
||||
if (nalloc)
|
||||
gfs2_inplace_release(ip);
|
||||
gfs2_inplace_release(ip);
|
||||
out_alloc:
|
||||
if (nalloc)
|
||||
gfs2_alloc_put(ip);
|
||||
gfs2_alloc_put(ip);
|
||||
out_gunlock:
|
||||
gfs2_glock_dq_uninit(&i_gh);
|
||||
out:
|
||||
@ -1124,12 +1118,12 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
|
||||
error = -ENOMEM;
|
||||
|
||||
sdp->sd_quota_bitmap = kcalloc(sdp->sd_quota_chunks,
|
||||
sizeof(unsigned char *), GFP_KERNEL);
|
||||
sizeof(unsigned char *), GFP_NOFS);
|
||||
if (!sdp->sd_quota_bitmap)
|
||||
return error;
|
||||
|
||||
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])
|
||||
goto fail;
|
||||
}
|
||||
|
@ -32,4 +32,21 @@ int gfs2_quota_init(struct gfs2_sbd *sdp);
|
||||
void gfs2_quota_scan(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__ */
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "bmap.h"
|
||||
#include "glock.h"
|
||||
#include "glops.h"
|
||||
#include "lm.h"
|
||||
#include "lops.h"
|
||||
#include "meta_io.h"
|
||||
#include "recovery.h"
|
||||
@ -69,7 +68,7 @@ int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where)
|
||||
return 0;
|
||||
}
|
||||
|
||||
rr = kmalloc(sizeof(struct gfs2_revoke_replay), GFP_KERNEL);
|
||||
rr = kmalloc(sizeof(struct gfs2_revoke_replay), GFP_NOFS);
|
||||
if (!rr)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -150,7 +149,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
|
||||
struct gfs2_log_header_host *head)
|
||||
{
|
||||
struct buffer_head *bh;
|
||||
struct gfs2_log_header_host lh;
|
||||
struct gfs2_log_header_host uninitialized_var(lh);
|
||||
const u32 nothing = 0;
|
||||
u32 hash;
|
||||
int error;
|
||||
@ -425,6 +424,16 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea
|
||||
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
|
||||
* @jd: the struct gfs2_jdesc describing the journal
|
||||
|
368
fs/gfs2/rgrp.c
368
fs/gfs2/rgrp.c
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
@ -14,6 +14,7 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/gfs2_ondisk.h>
|
||||
#include <linux/lm_interface.h>
|
||||
#include <linux/prefetch.h>
|
||||
|
||||
#include "gfs2.h"
|
||||
#include "incore.h"
|
||||
@ -33,6 +34,16 @@
|
||||
#define BFITNOENT ((u32)~0)
|
||||
#define NO_BLOCK ((u64)~0)
|
||||
|
||||
#if BITS_PER_LONG == 32
|
||||
#define LBITMASK (0x55555555UL)
|
||||
#define LBITSKIP55 (0x55555555UL)
|
||||
#define LBITSKIP00 (0x00000000UL)
|
||||
#else
|
||||
#define LBITMASK (0x5555555555555555UL)
|
||||
#define LBITSKIP55 (0x5555555555555555UL)
|
||||
#define LBITSKIP00 (0x0000000000000000UL)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These routines are used by the resource group routines (rgrp.c)
|
||||
* to keep track of block allocation. Each block is represented by two
|
||||
@ -53,7 +64,8 @@ static const char valid_change[16] = {
|
||||
};
|
||||
|
||||
static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
|
||||
unsigned char old_state, unsigned char new_state);
|
||||
unsigned char old_state, unsigned char new_state,
|
||||
unsigned int *n);
|
||||
|
||||
/**
|
||||
* gfs2_setbit - Set a bit in the bitmaps
|
||||
@ -64,26 +76,32 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
|
||||
*
|
||||
*/
|
||||
|
||||
static void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
|
||||
unsigned int buflen, u32 block,
|
||||
unsigned char new_state)
|
||||
static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf1,
|
||||
unsigned char *buf2, unsigned int offset,
|
||||
unsigned int buflen, u32 block,
|
||||
unsigned char new_state)
|
||||
{
|
||||
unsigned char *byte, *end, cur_state;
|
||||
unsigned int bit;
|
||||
unsigned char *byte1, *byte2, *end, cur_state;
|
||||
const unsigned int bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE;
|
||||
|
||||
byte = buffer + (block / GFS2_NBBY);
|
||||
bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE;
|
||||
end = buffer + buflen;
|
||||
byte1 = buf1 + offset + (block / GFS2_NBBY);
|
||||
end = buf1 + offset + buflen;
|
||||
|
||||
gfs2_assert(rgd->rd_sbd, byte < end);
|
||||
BUG_ON(byte1 >= end);
|
||||
|
||||
cur_state = (*byte >> bit) & GFS2_BIT_MASK;
|
||||
cur_state = (*byte1 >> bit) & GFS2_BIT_MASK;
|
||||
|
||||
if (valid_change[new_state * 4 + cur_state]) {
|
||||
*byte ^= cur_state << bit;
|
||||
*byte |= new_state << bit;
|
||||
} else
|
||||
if (unlikely(!valid_change[new_state * 4 + cur_state])) {
|
||||
gfs2_consist_rgrpd(rgd);
|
||||
return;
|
||||
}
|
||||
*byte1 ^= (cur_state ^ new_state) << bit;
|
||||
|
||||
if (buf2) {
|
||||
byte2 = buf2 + offset + (block / GFS2_NBBY);
|
||||
cur_state = (*byte2 >> bit) & GFS2_BIT_MASK;
|
||||
*byte2 ^= (cur_state ^ new_state) << bit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,10 +112,12 @@ static void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
|
||||
*
|
||||
*/
|
||||
|
||||
static unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
|
||||
unsigned int buflen, u32 block)
|
||||
static inline unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd,
|
||||
const unsigned char *buffer,
|
||||
unsigned int buflen, u32 block)
|
||||
{
|
||||
unsigned char *byte, *end, cur_state;
|
||||
const unsigned char *byte, *end;
|
||||
unsigned char cur_state;
|
||||
unsigned int bit;
|
||||
|
||||
byte = buffer + (block / GFS2_NBBY);
|
||||
@ -126,47 +146,66 @@ static unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
|
||||
* Return: the block number (bitmap buffer scope) that was found
|
||||
*/
|
||||
|
||||
static u32 gfs2_bitfit(unsigned char *buffer, unsigned int buflen, u32 goal,
|
||||
unsigned char old_state)
|
||||
static u32 gfs2_bitfit(const u8 *buffer, unsigned int buflen, u32 goal,
|
||||
u8 old_state)
|
||||
{
|
||||
unsigned char *byte;
|
||||
u32 blk = goal;
|
||||
unsigned int bit, bitlong;
|
||||
unsigned long *plong, plong55;
|
||||
const u8 *byte, *start, *end;
|
||||
int bit, startbit;
|
||||
u32 g1, g2, misaligned;
|
||||
unsigned long *plong;
|
||||
unsigned long lskipval;
|
||||
|
||||
byte = buffer + (goal / GFS2_NBBY);
|
||||
plong = (unsigned long *)(buffer + (goal / GFS2_NBBY));
|
||||
bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE;
|
||||
bitlong = bit;
|
||||
#if BITS_PER_LONG == 32
|
||||
plong55 = 0x55555555;
|
||||
#else
|
||||
plong55 = 0x5555555555555555;
|
||||
#endif
|
||||
while (byte < buffer + buflen) {
|
||||
|
||||
if (bitlong == 0 && old_state == 0 && *plong == plong55) {
|
||||
plong++;
|
||||
byte += sizeof(unsigned long);
|
||||
blk += sizeof(unsigned long) * GFS2_NBBY;
|
||||
continue;
|
||||
lskipval = (old_state & GFS2_BLKST_USED) ? LBITSKIP00 : LBITSKIP55;
|
||||
g1 = (goal / GFS2_NBBY);
|
||||
start = buffer + g1;
|
||||
byte = start;
|
||||
end = buffer + buflen;
|
||||
g2 = ALIGN(g1, sizeof(unsigned long));
|
||||
plong = (unsigned long *)(buffer + g2);
|
||||
startbit = bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE;
|
||||
misaligned = g2 - g1;
|
||||
if (!misaligned)
|
||||
goto ulong_aligned;
|
||||
/* parse the bitmap a byte at a time */
|
||||
misaligned:
|
||||
while (byte < end) {
|
||||
if (((*byte >> bit) & GFS2_BIT_MASK) == old_state) {
|
||||
return goal +
|
||||
(((byte - start) * GFS2_NBBY) +
|
||||
((bit - startbit) >> 1));
|
||||
}
|
||||
if (((*byte >> bit) & GFS2_BIT_MASK) == old_state)
|
||||
return blk;
|
||||
bit += GFS2_BIT_SIZE;
|
||||
if (bit >= 8) {
|
||||
if (bit >= GFS2_NBBY * GFS2_BIT_SIZE) {
|
||||
bit = 0;
|
||||
byte++;
|
||||
misaligned--;
|
||||
if (!misaligned) {
|
||||
plong = (unsigned long *)byte;
|
||||
goto ulong_aligned;
|
||||
}
|
||||
}
|
||||
bitlong += GFS2_BIT_SIZE;
|
||||
if (bitlong >= sizeof(unsigned long) * 8) {
|
||||
bitlong = 0;
|
||||
plong++;
|
||||
}
|
||||
|
||||
blk++;
|
||||
}
|
||||
return BFITNOENT;
|
||||
|
||||
/* parse the bitmap a unsigned long at a time */
|
||||
ulong_aligned:
|
||||
/* Stop at "end - 1" or else prefetch can go past the end and segfault.
|
||||
We could "if" it but we'd lose some of the performance gained.
|
||||
This way will only slow down searching the very last 4/8 bytes
|
||||
depending on architecture. I've experimented with several ways
|
||||
of writing this section such as using an else before the goto
|
||||
but this one seems to be the fastest. */
|
||||
while ((unsigned char *)plong < end - 1) {
|
||||
prefetch(plong + 1);
|
||||
if (((*plong) & LBITMASK) != lskipval)
|
||||
break;
|
||||
plong++;
|
||||
}
|
||||
if ((unsigned char *)plong < end) {
|
||||
byte = (const u8 *)plong;
|
||||
misaligned += sizeof(unsigned long) - 1;
|
||||
goto misaligned;
|
||||
}
|
||||
return BFITNOENT;
|
||||
}
|
||||
|
||||
@ -179,14 +218,14 @@ static u32 gfs2_bitfit(unsigned char *buffer, unsigned int buflen, u32 goal,
|
||||
* Returns: The number of bits
|
||||
*/
|
||||
|
||||
static u32 gfs2_bitcount(struct gfs2_rgrpd *rgd, unsigned char *buffer,
|
||||
unsigned int buflen, unsigned char state)
|
||||
static u32 gfs2_bitcount(struct gfs2_rgrpd *rgd, const u8 *buffer,
|
||||
unsigned int buflen, u8 state)
|
||||
{
|
||||
unsigned char *byte = buffer;
|
||||
unsigned char *end = buffer + buflen;
|
||||
unsigned char state1 = state << 2;
|
||||
unsigned char state2 = state << 4;
|
||||
unsigned char state3 = state << 6;
|
||||
const u8 *byte = buffer;
|
||||
const u8 *end = buffer + buflen;
|
||||
const u8 state1 = state << 2;
|
||||
const u8 state2 = state << 4;
|
||||
const u8 state3 = state << 6;
|
||||
u32 count = 0;
|
||||
|
||||
for (; byte < end; byte++) {
|
||||
@ -353,7 +392,7 @@ static void clear_rgrpdi(struct gfs2_sbd *sdp)
|
||||
}
|
||||
|
||||
kfree(rgd->rd_bits);
|
||||
kfree(rgd);
|
||||
kmem_cache_free(gfs2_rgrpd_cachep, rgd);
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,7 +555,7 @@ static int read_rindex_entry(struct gfs2_inode *ip,
|
||||
return error;
|
||||
}
|
||||
|
||||
rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS);
|
||||
rgd = kmem_cache_zalloc(gfs2_rgrpd_cachep, GFP_NOFS);
|
||||
error = -ENOMEM;
|
||||
if (!rgd)
|
||||
return error;
|
||||
@ -539,7 +578,7 @@ static int read_rindex_entry(struct gfs2_inode *ip,
|
||||
return error;
|
||||
|
||||
rgd->rd_gl->gl_object = rgd;
|
||||
rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
|
||||
rgd->rd_flags &= ~GFS2_RDF_UPTODATE;
|
||||
rgd->rd_flags |= GFS2_RDF_CHECK;
|
||||
return error;
|
||||
}
|
||||
@ -575,7 +614,7 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
|
||||
}
|
||||
}
|
||||
|
||||
sdp->sd_rindex_vn = ip->i_gl->gl_vn;
|
||||
sdp->sd_rindex_uptodate = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -609,7 +648,7 @@ static int gfs2_ri_update_special(struct gfs2_inode *ip)
|
||||
}
|
||||
}
|
||||
|
||||
sdp->sd_rindex_vn = ip->i_gl->gl_vn;
|
||||
sdp->sd_rindex_uptodate = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -642,9 +681,9 @@ int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh)
|
||||
return error;
|
||||
|
||||
/* Read new copy from disk if we don't have the latest */
|
||||
if (sdp->sd_rindex_vn != gl->gl_vn) {
|
||||
if (!sdp->sd_rindex_uptodate) {
|
||||
mutex_lock(&sdp->sd_rindex_mutex);
|
||||
if (sdp->sd_rindex_vn != gl->gl_vn) {
|
||||
if (!sdp->sd_rindex_uptodate) {
|
||||
error = gfs2_ri_update(ip);
|
||||
if (error)
|
||||
gfs2_glock_dq_uninit(ri_gh);
|
||||
@ -655,21 +694,31 @@ int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh)
|
||||
return error;
|
||||
}
|
||||
|
||||
static void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf)
|
||||
static void gfs2_rgrp_in(struct gfs2_rgrpd *rgd, const void *buf)
|
||||
{
|
||||
const struct gfs2_rgrp *str = buf;
|
||||
struct gfs2_rgrp_host *rg = &rgd->rd_rg;
|
||||
u32 rg_flags;
|
||||
|
||||
rg->rg_flags = be32_to_cpu(str->rg_flags);
|
||||
rg_flags = be32_to_cpu(str->rg_flags);
|
||||
if (rg_flags & GFS2_RGF_NOALLOC)
|
||||
rgd->rd_flags |= GFS2_RDF_NOALLOC;
|
||||
else
|
||||
rgd->rd_flags &= ~GFS2_RDF_NOALLOC;
|
||||
rg->rg_free = be32_to_cpu(str->rg_free);
|
||||
rg->rg_dinodes = be32_to_cpu(str->rg_dinodes);
|
||||
rg->rg_igeneration = be64_to_cpu(str->rg_igeneration);
|
||||
}
|
||||
|
||||
static void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf)
|
||||
static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf)
|
||||
{
|
||||
struct gfs2_rgrp *str = buf;
|
||||
struct gfs2_rgrp_host *rg = &rgd->rd_rg;
|
||||
u32 rg_flags = 0;
|
||||
|
||||
str->rg_flags = cpu_to_be32(rg->rg_flags);
|
||||
if (rgd->rd_flags & GFS2_RDF_NOALLOC)
|
||||
rg_flags |= GFS2_RGF_NOALLOC;
|
||||
str->rg_flags = cpu_to_be32(rg_flags);
|
||||
str->rg_free = cpu_to_be32(rg->rg_free);
|
||||
str->rg_dinodes = cpu_to_be32(rg->rg_dinodes);
|
||||
str->__pad = cpu_to_be32(0);
|
||||
@ -726,9 +775,9 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
|
||||
}
|
||||
}
|
||||
|
||||
if (rgd->rd_rg_vn != gl->gl_vn) {
|
||||
gfs2_rgrp_in(&rgd->rd_rg, (rgd->rd_bits[0].bi_bh)->b_data);
|
||||
rgd->rd_rg_vn = gl->gl_vn;
|
||||
if (!(rgd->rd_flags & GFS2_RDF_UPTODATE)) {
|
||||
gfs2_rgrp_in(rgd, (rgd->rd_bits[0].bi_bh)->b_data);
|
||||
rgd->rd_flags |= GFS2_RDF_UPTODATE;
|
||||
}
|
||||
|
||||
spin_lock(&sdp->sd_rindex_spin);
|
||||
@ -840,7 +889,7 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al)
|
||||
struct gfs2_sbd *sdp = rgd->rd_sbd;
|
||||
int ret = 0;
|
||||
|
||||
if (rgd->rd_rg.rg_flags & GFS2_RGF_NOALLOC)
|
||||
if (rgd->rd_flags & GFS2_RDF_NOALLOC)
|
||||
return 0;
|
||||
|
||||
spin_lock(&sdp->sd_rindex_spin);
|
||||
@ -866,13 +915,15 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
|
||||
u32 goal = 0, block;
|
||||
u64 no_addr;
|
||||
struct gfs2_sbd *sdp = rgd->rd_sbd;
|
||||
unsigned int n;
|
||||
|
||||
for(;;) {
|
||||
if (goal >= rgd->rd_data)
|
||||
break;
|
||||
down_write(&sdp->sd_log_flush_lock);
|
||||
n = 1;
|
||||
block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED,
|
||||
GFS2_BLKST_UNLINKED);
|
||||
GFS2_BLKST_UNLINKED, &n);
|
||||
up_write(&sdp->sd_log_flush_lock);
|
||||
if (block == BFITNOENT)
|
||||
break;
|
||||
@ -904,24 +955,20 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
|
||||
static struct gfs2_rgrpd *recent_rgrp_first(struct gfs2_sbd *sdp,
|
||||
u64 rglast)
|
||||
{
|
||||
struct gfs2_rgrpd *rgd = NULL;
|
||||
struct gfs2_rgrpd *rgd;
|
||||
|
||||
spin_lock(&sdp->sd_rindex_spin);
|
||||
|
||||
if (list_empty(&sdp->sd_rindex_recent_list))
|
||||
goto out;
|
||||
|
||||
if (!rglast)
|
||||
goto first;
|
||||
|
||||
list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) {
|
||||
if (rgd->rd_addr == rglast)
|
||||
goto out;
|
||||
if (rglast) {
|
||||
list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) {
|
||||
if (rgrp_contains_block(rgd, rglast))
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
first:
|
||||
rgd = list_entry(sdp->sd_rindex_recent_list.next, struct gfs2_rgrpd,
|
||||
rd_recent);
|
||||
rgd = NULL;
|
||||
if (!list_empty(&sdp->sd_rindex_recent_list))
|
||||
rgd = list_entry(sdp->sd_rindex_recent_list.next,
|
||||
struct gfs2_rgrpd, rd_recent);
|
||||
out:
|
||||
spin_unlock(&sdp->sd_rindex_spin);
|
||||
return rgd;
|
||||
@ -1067,7 +1114,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
|
||||
|
||||
/* Try recently successful rgrps */
|
||||
|
||||
rgd = recent_rgrp_first(sdp, ip->i_last_rg_alloc);
|
||||
rgd = recent_rgrp_first(sdp, ip->i_goal);
|
||||
|
||||
while (rgd) {
|
||||
rg_locked = 0;
|
||||
@ -1151,8 +1198,6 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
|
||||
}
|
||||
|
||||
out:
|
||||
ip->i_last_rg_alloc = rgd->rd_addr;
|
||||
|
||||
if (begin) {
|
||||
recent_rgrp_add(rgd);
|
||||
rgd = gfs2_rgrpd_get_next(rgd);
|
||||
@ -1275,6 +1320,7 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
|
||||
* @goal: the goal block within the RG (start here to search for avail block)
|
||||
* @old_state: GFS2_BLKST_XXX the before-allocation state to find
|
||||
* @new_state: GFS2_BLKST_XXX the after-allocation block state
|
||||
* @n: The extent length
|
||||
*
|
||||
* Walk rgrp's bitmap to find bits that represent a block in @old_state.
|
||||
* Add the found bitmap buffer to the transaction.
|
||||
@ -1290,13 +1336,17 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
|
||||
*/
|
||||
|
||||
static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
|
||||
unsigned char old_state, unsigned char new_state)
|
||||
unsigned char old_state, unsigned char new_state,
|
||||
unsigned int *n)
|
||||
{
|
||||
struct gfs2_bitmap *bi = NULL;
|
||||
u32 length = rgd->rd_length;
|
||||
const u32 length = rgd->rd_length;
|
||||
u32 blk = 0;
|
||||
unsigned int buf, x;
|
||||
const unsigned int elen = *n;
|
||||
const u8 *buffer;
|
||||
|
||||
*n = 0;
|
||||
/* Find bitmap block that contains bits for goal block */
|
||||
for (buf = 0; buf < length; buf++) {
|
||||
bi = rgd->rd_bits + buf;
|
||||
@ -1317,12 +1367,11 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
|
||||
for (x = 0; x <= length; x++) {
|
||||
/* The GFS2_BLKST_UNLINKED state doesn't apply to the clone
|
||||
bitmaps, so we must search the originals for that. */
|
||||
buffer = bi->bi_bh->b_data + bi->bi_offset;
|
||||
if (old_state != GFS2_BLKST_UNLINKED && bi->bi_clone)
|
||||
blk = gfs2_bitfit(bi->bi_clone + bi->bi_offset,
|
||||
bi->bi_len, goal, old_state);
|
||||
else
|
||||
blk = gfs2_bitfit(bi->bi_bh->b_data + bi->bi_offset,
|
||||
bi->bi_len, goal, old_state);
|
||||
buffer = bi->bi_clone + bi->bi_offset;
|
||||
|
||||
blk = gfs2_bitfit(buffer, bi->bi_len, goal, old_state);
|
||||
if (blk != BFITNOENT)
|
||||
break;
|
||||
|
||||
@ -1333,12 +1382,23 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
|
||||
}
|
||||
|
||||
if (blk != BFITNOENT && old_state != new_state) {
|
||||
*n = 1;
|
||||
gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
|
||||
gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
|
||||
gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset,
|
||||
bi->bi_len, blk, new_state);
|
||||
if (bi->bi_clone)
|
||||
gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
|
||||
bi->bi_len, blk, new_state);
|
||||
goal = blk;
|
||||
while (*n < elen) {
|
||||
goal++;
|
||||
if (goal >= (bi->bi_len * GFS2_NBBY))
|
||||
break;
|
||||
if (gfs2_testbit(rgd, buffer, bi->bi_len, goal) !=
|
||||
GFS2_BLKST_FREE)
|
||||
break;
|
||||
gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone,
|
||||
bi->bi_offset, bi->bi_len, goal,
|
||||
new_state);
|
||||
(*n)++;
|
||||
}
|
||||
}
|
||||
|
||||
return (blk == BFITNOENT) ? blk : (bi->bi_start * GFS2_NBBY) + blk;
|
||||
@ -1393,7 +1453,7 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
|
||||
bi->bi_len);
|
||||
}
|
||||
gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
|
||||
gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
|
||||
gfs2_setbit(rgd, bi->bi_bh->b_data, NULL, bi->bi_offset,
|
||||
bi->bi_len, buf_blk, new_state);
|
||||
}
|
||||
|
||||
@ -1401,13 +1461,13 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_alloc_data - Allocate a data block
|
||||
* @ip: the inode to allocate the data block for
|
||||
* gfs2_alloc_block - Allocate a block
|
||||
* @ip: the inode to allocate the block for
|
||||
*
|
||||
* Returns: the allocated block
|
||||
*/
|
||||
|
||||
u64 gfs2_alloc_data(struct gfs2_inode *ip)
|
||||
u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
struct gfs2_alloc *al = ip->i_alloc;
|
||||
@ -1415,77 +1475,31 @@ u64 gfs2_alloc_data(struct gfs2_inode *ip)
|
||||
u32 goal, blk;
|
||||
u64 block;
|
||||
|
||||
if (rgrp_contains_block(rgd, ip->i_di.di_goal_data))
|
||||
goal = ip->i_di.di_goal_data - rgd->rd_data0;
|
||||
if (rgrp_contains_block(rgd, ip->i_goal))
|
||||
goal = ip->i_goal - rgd->rd_data0;
|
||||
else
|
||||
goal = rgd->rd_last_alloc_data;
|
||||
goal = rgd->rd_last_alloc;
|
||||
|
||||
blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
|
||||
blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED, n);
|
||||
BUG_ON(blk == BFITNOENT);
|
||||
rgd->rd_last_alloc_data = blk;
|
||||
|
||||
rgd->rd_last_alloc = blk;
|
||||
block = rgd->rd_data0 + blk;
|
||||
ip->i_di.di_goal_data = block;
|
||||
ip->i_goal = block;
|
||||
|
||||
gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
|
||||
rgd->rd_rg.rg_free--;
|
||||
gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free >= *n);
|
||||
rgd->rd_rg.rg_free -= *n;
|
||||
|
||||
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
|
||||
gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
|
||||
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
|
||||
|
||||
al->al_alloced++;
|
||||
al->al_alloced += *n;
|
||||
|
||||
gfs2_statfs_change(sdp, 0, -1, 0);
|
||||
gfs2_quota_change(ip, +1, ip->i_inode.i_uid, ip->i_inode.i_gid);
|
||||
gfs2_statfs_change(sdp, 0, -*n, 0);
|
||||
gfs2_quota_change(ip, *n, ip->i_inode.i_uid, ip->i_inode.i_gid);
|
||||
|
||||
spin_lock(&sdp->sd_rindex_spin);
|
||||
rgd->rd_free_clone--;
|
||||
spin_unlock(&sdp->sd_rindex_spin);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_alloc_meta - Allocate a metadata block
|
||||
* @ip: the inode to allocate the metadata block for
|
||||
*
|
||||
* Returns: the allocated block
|
||||
*/
|
||||
|
||||
u64 gfs2_alloc_meta(struct gfs2_inode *ip)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
struct gfs2_alloc *al = ip->i_alloc;
|
||||
struct gfs2_rgrpd *rgd = al->al_rgd;
|
||||
u32 goal, blk;
|
||||
u64 block;
|
||||
|
||||
if (rgrp_contains_block(rgd, ip->i_di.di_goal_meta))
|
||||
goal = ip->i_di.di_goal_meta - rgd->rd_data0;
|
||||
else
|
||||
goal = rgd->rd_last_alloc_meta;
|
||||
|
||||
blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
|
||||
BUG_ON(blk == BFITNOENT);
|
||||
rgd->rd_last_alloc_meta = blk;
|
||||
|
||||
block = rgd->rd_data0 + blk;
|
||||
ip->i_di.di_goal_meta = block;
|
||||
|
||||
gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
|
||||
rgd->rd_rg.rg_free--;
|
||||
|
||||
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
|
||||
gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
|
||||
|
||||
al->al_alloced++;
|
||||
|
||||
gfs2_statfs_change(sdp, 0, -1, 0);
|
||||
gfs2_quota_change(ip, +1, ip->i_inode.i_uid, ip->i_inode.i_gid);
|
||||
gfs2_trans_add_unrevoke(sdp, block);
|
||||
|
||||
spin_lock(&sdp->sd_rindex_spin);
|
||||
rgd->rd_free_clone--;
|
||||
rgd->rd_free_clone -= *n;
|
||||
spin_unlock(&sdp->sd_rindex_spin);
|
||||
|
||||
return block;
|
||||
@ -1505,12 +1519,13 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
|
||||
struct gfs2_rgrpd *rgd = al->al_rgd;
|
||||
u32 blk;
|
||||
u64 block;
|
||||
unsigned int n = 1;
|
||||
|
||||
blk = rgblk_search(rgd, rgd->rd_last_alloc_meta,
|
||||
GFS2_BLKST_FREE, GFS2_BLKST_DINODE);
|
||||
blk = rgblk_search(rgd, rgd->rd_last_alloc,
|
||||
GFS2_BLKST_FREE, GFS2_BLKST_DINODE, &n);
|
||||
BUG_ON(blk == BFITNOENT);
|
||||
|
||||
rgd->rd_last_alloc_meta = blk;
|
||||
rgd->rd_last_alloc = blk;
|
||||
|
||||
block = rgd->rd_data0 + blk;
|
||||
|
||||
@ -1519,12 +1534,12 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
|
||||
rgd->rd_rg.rg_dinodes++;
|
||||
*generation = rgd->rd_rg.rg_igeneration++;
|
||||
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
|
||||
gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
|
||||
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
|
||||
|
||||
al->al_alloced++;
|
||||
|
||||
gfs2_statfs_change(sdp, 0, -1, +1);
|
||||
gfs2_trans_add_unrevoke(sdp, block);
|
||||
gfs2_trans_add_unrevoke(sdp, block, 1);
|
||||
|
||||
spin_lock(&sdp->sd_rindex_spin);
|
||||
rgd->rd_free_clone--;
|
||||
@ -1553,7 +1568,7 @@ void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
|
||||
rgd->rd_rg.rg_free += blen;
|
||||
|
||||
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
|
||||
gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
|
||||
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
|
||||
|
||||
gfs2_trans_add_rg(rgd);
|
||||
|
||||
@ -1581,7 +1596,7 @@ void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
|
||||
rgd->rd_rg.rg_free += blen;
|
||||
|
||||
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
|
||||
gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
|
||||
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
|
||||
|
||||
gfs2_trans_add_rg(rgd);
|
||||
|
||||
@ -1601,7 +1616,7 @@ void gfs2_unlink_di(struct inode *inode)
|
||||
if (!rgd)
|
||||
return;
|
||||
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
|
||||
gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
|
||||
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
|
||||
gfs2_trans_add_rg(rgd);
|
||||
}
|
||||
|
||||
@ -1621,7 +1636,7 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno)
|
||||
rgd->rd_rg.rg_free++;
|
||||
|
||||
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
|
||||
gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
|
||||
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
|
||||
|
||||
gfs2_statfs_change(sdp, 0, +1, -1);
|
||||
gfs2_trans_add_rg(rgd);
|
||||
@ -1699,8 +1714,7 @@ void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist,
|
||||
*
|
||||
*/
|
||||
|
||||
void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state,
|
||||
int flags)
|
||||
void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state)
|
||||
{
|
||||
unsigned int x;
|
||||
|
||||
@ -1708,7 +1722,7 @@ void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state,
|
||||
GFP_NOFS | __GFP_NOFAIL);
|
||||
for (x = 0; x < rlist->rl_rgrps; x++)
|
||||
gfs2_holder_init(rlist->rl_rgd[x]->rd_gl,
|
||||
state, flags,
|
||||
state, 0,
|
||||
&rlist->rl_ghs[x]);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
@ -46,8 +46,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip);
|
||||
|
||||
unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block);
|
||||
|
||||
u64 gfs2_alloc_data(struct gfs2_inode *ip);
|
||||
u64 gfs2_alloc_meta(struct gfs2_inode *ip);
|
||||
u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n);
|
||||
u64 gfs2_alloc_di(struct gfs2_inode *ip, u64 *generation);
|
||||
|
||||
void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);
|
||||
@ -64,8 +63,7 @@ struct gfs2_rgrp_list {
|
||||
|
||||
void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist,
|
||||
u64 block);
|
||||
void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state,
|
||||
int flags);
|
||||
void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state);
|
||||
void gfs2_rlist_free(struct gfs2_rgrp_list *rlist);
|
||||
u64 gfs2_ri_total(struct gfs2_sbd *sdp);
|
||||
|
||||
|
@ -210,7 +210,7 @@ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector)
|
||||
struct page *page;
|
||||
struct bio *bio;
|
||||
|
||||
page = alloc_page(GFP_KERNEL);
|
||||
page = alloc_page(GFP_NOFS);
|
||||
if (unlikely(!page))
|
||||
return -ENOBUFS;
|
||||
|
||||
@ -218,7 +218,7 @@ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector)
|
||||
ClearPageDirty(page);
|
||||
lock_page(page);
|
||||
|
||||
bio = bio_alloc(GFP_KERNEL, 1);
|
||||
bio = bio_alloc(GFP_NOFS, 1);
|
||||
if (unlikely(!bio)) {
|
||||
__free_page(page);
|
||||
return -ENOBUFS;
|
||||
@ -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_max_height = x;
|
||||
sdp->sd_heightsize[x] = ~0;
|
||||
gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT);
|
||||
|
||||
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)
|
||||
sdp->sd_jheightsize[x] = space;
|
||||
}
|
||||
sdp->sd_max_jheight = x;
|
||||
sdp->sd_jheightsize[x] = ~0;
|
||||
gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT);
|
||||
|
||||
return 0;
|
||||
|
@ -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_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent);
|
||||
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)
|
||||
{
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include "gfs2.h"
|
||||
#include "incore.h"
|
||||
#include "lm.h"
|
||||
#include "sys.h"
|
||||
#include "super.h"
|
||||
#include "glock.h"
|
||||
@ -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)
|
||||
|
||||
COUNTERS_ATTR(glock_count, "%u\n");
|
||||
COUNTERS_ATTR(glock_held_count, "%u\n");
|
||||
COUNTERS_ATTR(inode_count, "%u\n");
|
||||
COUNTERS_ATTR(reclaimed, "%u\n");
|
||||
|
||||
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,
|
||||
NULL,
|
||||
};
|
||||
|
@ -146,30 +146,25 @@ void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
|
||||
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;
|
||||
int found = 0;
|
||||
struct gfs2_bufdata *bd, *tmp;
|
||||
struct gfs2_trans *tr = current->journal_info;
|
||||
unsigned int n = len;
|
||||
|
||||
gfs2_log_lock(sdp);
|
||||
|
||||
list_for_each_entry(bd, &sdp->sd_log_le_revoke, bd_le.le_list) {
|
||||
if (bd->bd_blkno == blkno) {
|
||||
list_for_each_entry_safe(bd, tmp, &sdp->sd_log_le_revoke, bd_le.le_list) {
|
||||
if ((bd->bd_blkno >= blkno) && (bd->bd_blkno < (blkno + len))) {
|
||||
list_del_init(&bd->bd_le.le_list);
|
||||
gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke);
|
||||
sdp->sd_log_num_revoke--;
|
||||
found = 1;
|
||||
break;
|
||||
kmem_cache_free(gfs2_bufdata_cachep, bd);
|
||||
tr->tr_num_revoke_rm++;
|
||||
if (--n == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -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_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);
|
||||
|
||||
#endif /* __TRANS_DOT_H__ */
|
||||
|
@ -19,12 +19,12 @@
|
||||
#include "gfs2.h"
|
||||
#include "incore.h"
|
||||
#include "glock.h"
|
||||
#include "lm.h"
|
||||
#include "util.h"
|
||||
|
||||
struct kmem_cache *gfs2_glock_cachep __read_mostly;
|
||||
struct kmem_cache *gfs2_inode_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)
|
||||
{
|
||||
@ -32,6 +32,28 @@ void gfs2_assert_i(struct gfs2_sbd *sdp)
|
||||
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
|
||||
* Returns: -1 if this call withdrew the machine,
|
||||
|
@ -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_inode_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,
|
||||
unsigned int *p)
|
||||
@ -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,
|
||||
unsigned int bit, int new_value);
|
||||
int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...);
|
||||
|
||||
#endif /* __UTIL_DOT_H__ */
|
||||
|
||||
|
@ -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
|
||||
* mount. It shouldn't send recovery callbacks to the FS mount. If the node
|
||||
* 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_CONV_NODROP 0x00000002
|
||||
|
||||
/*
|
||||
* lm_lockstruct flags
|
||||
@ -110,6 +116,9 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
|
||||
*
|
||||
* LM_OUT_ASYNC
|
||||
* 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
|
||||
@ -117,6 +126,7 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
|
||||
#define LM_OUT_CANCELED 0x00000008
|
||||
#define LM_OUT_ASYNC 0x00000080
|
||||
#define LM_OUT_ERROR 0x00000100
|
||||
#define LM_OUT_CONV_DEADLK 0x00000200
|
||||
|
||||
/*
|
||||
* lm_callback_t types
|
||||
|
Loading…
Reference in New Issue
Block a user