mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-02 10:56:45 +07: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: (22 commits) GFS2: fixed typo GFS2: Fix type mapping for demote_rq interface GFS2 fatal: filesystem consistency error on rename GFS2: Improve journal allocation via sysfs GFS2: Add "norecovery" mount option as a synonym for "spectator" GFS2: Fix spectator umount issue GFS2: Fix compiler warning from previous patch GFS2: reserve more blocks for transactions GFS2: Fix journal check for spectator mounts GFS2: Remove upgrade mount option GFS2: Remove localcaching mount option GFS2: Remove ignore_local_fs mount argument GFS2: Make . and .. qstrs constant GFS2: Use new workqueue scheme GFS2: Update handling of DLM return codes to match reality GFS2: Don't enforce min hold time when two demotes occur in rapid succession GFS2: Fix whitespace in previous patch GFS2: fallocate support GFS2: Add a bug trap in allocation code GFS2: No longer experimental ...
This commit is contained in:
commit
f6f0a6d6a7
@ -1,6 +1,6 @@
|
||||
config GFS2_FS
|
||||
tristate "GFS2 file system support"
|
||||
depends on EXPERIMENTAL && (64BIT || LBDAF)
|
||||
depends on (64BIT || LBDAF)
|
||||
select DLM if GFS2_FS_LOCKING_DLM
|
||||
select CONFIGFS_FS if GFS2_FS_LOCKING_DLM
|
||||
select SYSFS if GFS2_FS_LOCKING_DLM
|
||||
|
@ -36,8 +36,8 @@
|
||||
#include "glops.h"
|
||||
|
||||
|
||||
static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
|
||||
unsigned int from, unsigned int to)
|
||||
void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
|
||||
unsigned int from, unsigned int to)
|
||||
{
|
||||
struct buffer_head *head = page_buffers(page);
|
||||
unsigned int bsize = head->b_size;
|
||||
@ -615,7 +615,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
|
||||
unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
|
||||
int alloc_required;
|
||||
int error = 0;
|
||||
struct gfs2_alloc *al;
|
||||
struct gfs2_alloc *al = NULL;
|
||||
pgoff_t index = pos >> PAGE_CACHE_SHIFT;
|
||||
unsigned from = pos & (PAGE_CACHE_SIZE - 1);
|
||||
unsigned to = from + len;
|
||||
@ -663,6 +663,8 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
|
||||
rblocks += RES_STATFS + RES_QUOTA;
|
||||
if (&ip->i_inode == sdp->sd_rindex)
|
||||
rblocks += 2 * RES_STATFS;
|
||||
if (alloc_required)
|
||||
rblocks += gfs2_rg_blocks(al);
|
||||
|
||||
error = gfs2_trans_begin(sdp, rblocks,
|
||||
PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize);
|
||||
@ -696,13 +698,11 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
|
||||
|
||||
page_cache_release(page);
|
||||
|
||||
/*
|
||||
* XXX(truncate): the call below should probably be replaced with
|
||||
* a call to the gfs2-specific truncate blocks helper to actually
|
||||
* release disk blocks..
|
||||
*/
|
||||
gfs2_trans_end(sdp);
|
||||
if (pos + len > ip->i_inode.i_size)
|
||||
truncate_setsize(&ip->i_inode, ip->i_inode.i_size);
|
||||
gfs2_trim_blocks(&ip->i_inode);
|
||||
goto out_trans_fail;
|
||||
|
||||
out_endtrans:
|
||||
gfs2_trans_end(sdp);
|
||||
out_trans_fail:
|
||||
@ -802,10 +802,8 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
|
||||
page_cache_release(page);
|
||||
|
||||
if (copied) {
|
||||
if (inode->i_size < to) {
|
||||
if (inode->i_size < to)
|
||||
i_size_write(inode, to);
|
||||
ip->i_disksize = inode->i_size;
|
||||
}
|
||||
gfs2_dinode_out(ip, di);
|
||||
mark_inode_dirty(inode);
|
||||
}
|
||||
@ -876,8 +874,6 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
|
||||
|
||||
ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
|
||||
if (ret > 0) {
|
||||
if (inode->i_size > ip->i_disksize)
|
||||
ip->i_disksize = inode->i_size;
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
mark_inode_dirty(inode);
|
||||
}
|
||||
|
259
fs/gfs2/bmap.c
259
fs/gfs2/bmap.c
@ -50,7 +50,7 @@ struct strip_mine {
|
||||
* @ip: the inode
|
||||
* @dibh: the dinode buffer
|
||||
* @block: the block number that was allocated
|
||||
* @private: any locked page held by the caller process
|
||||
* @page: The (optional) page. This is looked up if @page is NULL
|
||||
*
|
||||
* Returns: errno
|
||||
*/
|
||||
@ -109,8 +109,7 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
|
||||
/**
|
||||
* gfs2_unstuff_dinode - Unstuff a dinode when the data has grown too big
|
||||
* @ip: The GFS2 inode to unstuff
|
||||
* @unstuffer: the routine that handles unstuffing a non-zero length file
|
||||
* @private: private data for the unstuffer
|
||||
* @page: The (optional) page. This is looked up if the @page is NULL
|
||||
*
|
||||
* This routine unstuffs a dinode and returns it to a "normal" state such
|
||||
* that the height can be grown in the traditional way.
|
||||
@ -132,7 +131,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
if (ip->i_disksize) {
|
||||
if (i_size_read(&ip->i_inode)) {
|
||||
/* Get a free block, fill it with the stuffed data,
|
||||
and write it out to disk */
|
||||
|
||||
@ -161,7 +160,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
|
||||
di = (struct gfs2_dinode *)dibh->b_data;
|
||||
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
|
||||
|
||||
if (ip->i_disksize) {
|
||||
if (i_size_read(&ip->i_inode)) {
|
||||
*(__be64 *)(di + 1) = cpu_to_be64(block);
|
||||
gfs2_add_inode_blocks(&ip->i_inode, 1);
|
||||
di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
|
||||
@ -884,84 +883,15 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* do_grow - Make a file look bigger than it is
|
||||
* @ip: the inode
|
||||
* @size: the size to set the file to
|
||||
*
|
||||
* Called with an exclusive lock on @ip.
|
||||
*
|
||||
* Returns: errno
|
||||
*/
|
||||
|
||||
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;
|
||||
int error;
|
||||
|
||||
al = gfs2_alloc_get(ip);
|
||||
if (!al)
|
||||
return -ENOMEM;
|
||||
|
||||
error = gfs2_quota_lock_check(ip);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
al->al_requested = sdp->sd_max_height + RES_DATA;
|
||||
|
||||
error = gfs2_inplace_reserve(ip);
|
||||
if (error)
|
||||
goto out_gunlock_q;
|
||||
|
||||
error = gfs2_trans_begin(sdp,
|
||||
sdp->sd_max_height + al->al_rgd->rd_length +
|
||||
RES_JDATA + RES_DINODE + RES_STATFS + RES_QUOTA, 0);
|
||||
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_brelse;
|
||||
}
|
||||
}
|
||||
|
||||
ip->i_disksize = size;
|
||||
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
|
||||
out_brelse:
|
||||
brelse(dibh);
|
||||
out_end_trans:
|
||||
gfs2_trans_end(sdp);
|
||||
out_ipres:
|
||||
gfs2_inplace_release(ip);
|
||||
out_gunlock_q:
|
||||
gfs2_quota_unlock(ip);
|
||||
out:
|
||||
gfs2_alloc_put(ip);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gfs2_block_truncate_page - Deal with zeroing out data for truncate
|
||||
*
|
||||
* This is partly borrowed from ext3.
|
||||
*/
|
||||
static int gfs2_block_truncate_page(struct address_space *mapping)
|
||||
static int gfs2_block_truncate_page(struct address_space *mapping, loff_t from)
|
||||
{
|
||||
struct inode *inode = mapping->host;
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
loff_t from = inode->i_size;
|
||||
unsigned long index = from >> PAGE_CACHE_SHIFT;
|
||||
unsigned offset = from & (PAGE_CACHE_SIZE-1);
|
||||
unsigned blocksize, iblock, length, pos;
|
||||
@ -1023,9 +953,11 @@ static int gfs2_block_truncate_page(struct address_space *mapping)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int trunc_start(struct gfs2_inode *ip, u64 size)
|
||||
static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
struct address_space *mapping = inode->i_mapping;
|
||||
struct buffer_head *dibh;
|
||||
int journaled = gfs2_is_jdata(ip);
|
||||
int error;
|
||||
@ -1039,31 +971,26 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
if (gfs2_is_stuffed(ip)) {
|
||||
u64 dsize = size + sizeof(struct gfs2_dinode);
|
||||
ip->i_disksize = size;
|
||||
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
if (dsize > dibh->b_size)
|
||||
dsize = dibh->b_size;
|
||||
gfs2_buffer_clear_tail(dibh, dsize);
|
||||
error = 1;
|
||||
} else {
|
||||
if (size & (u64)(sdp->sd_sb.sb_bsize - 1))
|
||||
error = gfs2_block_truncate_page(ip->i_inode.i_mapping);
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
|
||||
if (!error) {
|
||||
ip->i_disksize = size;
|
||||
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
|
||||
ip->i_diskflags |= GFS2_DIF_TRUNC_IN_PROG;
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
if (gfs2_is_stuffed(ip)) {
|
||||
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + newsize);
|
||||
} else {
|
||||
if (newsize & (u64)(sdp->sd_sb.sb_bsize - 1)) {
|
||||
error = gfs2_block_truncate_page(mapping, newsize);
|
||||
if (error)
|
||||
goto out_brelse;
|
||||
}
|
||||
ip->i_diskflags |= GFS2_DIF_TRUNC_IN_PROG;
|
||||
}
|
||||
|
||||
brelse(dibh);
|
||||
i_size_write(inode, newsize);
|
||||
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
|
||||
truncate_pagecache(inode, oldsize, newsize);
|
||||
out_brelse:
|
||||
brelse(dibh);
|
||||
out:
|
||||
gfs2_trans_end(sdp);
|
||||
return error;
|
||||
@ -1123,7 +1050,7 @@ static int trunc_end(struct gfs2_inode *ip)
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
if (!ip->i_disksize) {
|
||||
if (!i_size_read(&ip->i_inode)) {
|
||||
ip->i_height = 0;
|
||||
ip->i_goal = ip->i_no_addr;
|
||||
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
|
||||
@ -1143,92 +1070,154 @@ static int trunc_end(struct gfs2_inode *ip)
|
||||
|
||||
/**
|
||||
* do_shrink - make a file smaller
|
||||
* @ip: the inode
|
||||
* @size: the size to make the file
|
||||
* @truncator: function to truncate the last partial block
|
||||
* @inode: the inode
|
||||
* @oldsize: the current inode size
|
||||
* @newsize: the size to make the file
|
||||
*
|
||||
* Called with an exclusive lock on @ip.
|
||||
* Called with an exclusive lock on @inode. The @size must
|
||||
* be equal to or smaller than the current inode size.
|
||||
*
|
||||
* Returns: errno
|
||||
*/
|
||||
|
||||
static int do_shrink(struct gfs2_inode *ip, u64 size)
|
||||
static int do_shrink(struct inode *inode, u64 oldsize, u64 newsize)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
int error;
|
||||
|
||||
error = trunc_start(ip, size);
|
||||
error = trunc_start(inode, oldsize, newsize);
|
||||
if (error < 0)
|
||||
return error;
|
||||
if (error > 0)
|
||||
if (gfs2_is_stuffed(ip))
|
||||
return 0;
|
||||
|
||||
error = trunc_dealloc(ip, size);
|
||||
if (!error)
|
||||
error = trunc_dealloc(ip, newsize);
|
||||
if (error == 0)
|
||||
error = trunc_end(ip);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int do_touch(struct gfs2_inode *ip, u64 size)
|
||||
void gfs2_trim_blocks(struct inode *inode)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
u64 size = inode->i_size;
|
||||
int ret;
|
||||
|
||||
ret = do_shrink(inode, size, size);
|
||||
WARN_ON(ret != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* do_grow - Touch and update inode size
|
||||
* @inode: The inode
|
||||
* @size: The new size
|
||||
*
|
||||
* This function updates the timestamps on the inode and
|
||||
* may also increase the size of the inode. This function
|
||||
* must not be called with @size any smaller than the current
|
||||
* inode size.
|
||||
*
|
||||
* Although it is not strictly required to unstuff files here,
|
||||
* earlier versions of GFS2 have a bug in the stuffed file reading
|
||||
* code which will result in a buffer overrun if the size is larger
|
||||
* than the max stuffed file size. In order to prevent this from
|
||||
* occuring, such files are unstuffed, but in other cases we can
|
||||
* just update the inode size directly.
|
||||
*
|
||||
* Returns: 0 on success, or -ve on error
|
||||
*/
|
||||
|
||||
static int do_grow(struct inode *inode, u64 size)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
struct buffer_head *dibh;
|
||||
struct gfs2_alloc *al = NULL;
|
||||
int error;
|
||||
|
||||
error = gfs2_trans_begin(sdp, RES_DINODE, 0);
|
||||
if (error)
|
||||
return error;
|
||||
if (gfs2_is_stuffed(ip) &&
|
||||
(size > (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)))) {
|
||||
al = gfs2_alloc_get(ip);
|
||||
if (al == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
down_write(&ip->i_rw_mutex);
|
||||
error = gfs2_quota_lock_check(ip);
|
||||
if (error)
|
||||
goto do_grow_alloc_put;
|
||||
|
||||
al->al_requested = 1;
|
||||
error = gfs2_inplace_reserve(ip);
|
||||
if (error)
|
||||
goto do_grow_qunlock;
|
||||
}
|
||||
|
||||
error = gfs2_trans_begin(sdp, RES_DINODE + RES_STATFS + RES_RG_BIT, 0);
|
||||
if (error)
|
||||
goto do_grow_release;
|
||||
|
||||
if (al) {
|
||||
error = gfs2_unstuff_dinode(ip, NULL);
|
||||
if (error)
|
||||
goto do_end_trans;
|
||||
}
|
||||
|
||||
error = gfs2_meta_inode_buffer(ip, &dibh);
|
||||
if (error)
|
||||
goto do_touch_out;
|
||||
goto do_end_trans;
|
||||
|
||||
i_size_write(inode, size);
|
||||
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
brelse(dibh);
|
||||
|
||||
do_touch_out:
|
||||
up_write(&ip->i_rw_mutex);
|
||||
do_end_trans:
|
||||
gfs2_trans_end(sdp);
|
||||
do_grow_release:
|
||||
if (al) {
|
||||
gfs2_inplace_release(ip);
|
||||
do_grow_qunlock:
|
||||
gfs2_quota_unlock(ip);
|
||||
do_grow_alloc_put:
|
||||
gfs2_alloc_put(ip);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_truncatei - make a file a given size
|
||||
* @ip: the inode
|
||||
* @size: the size to make the file
|
||||
* @truncator: function to truncate the last partial block
|
||||
* gfs2_setattr_size - make a file a given size
|
||||
* @inode: the inode
|
||||
* @newsize: the size to make the file
|
||||
*
|
||||
* The file size can grow, shrink, or stay the same size.
|
||||
* The file size can grow, shrink, or stay the same size. This
|
||||
* is called holding i_mutex and an exclusive glock on the inode
|
||||
* in question.
|
||||
*
|
||||
* Returns: errno
|
||||
*/
|
||||
|
||||
int gfs2_truncatei(struct gfs2_inode *ip, u64 size)
|
||||
int gfs2_setattr_size(struct inode *inode, u64 newsize)
|
||||
{
|
||||
int error;
|
||||
int ret;
|
||||
u64 oldsize;
|
||||
|
||||
if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), S_ISREG(ip->i_inode.i_mode)))
|
||||
return -EINVAL;
|
||||
BUG_ON(!S_ISREG(inode->i_mode));
|
||||
|
||||
if (size > ip->i_disksize)
|
||||
error = do_grow(ip, size);
|
||||
else if (size < ip->i_disksize)
|
||||
error = do_shrink(ip, size);
|
||||
else
|
||||
/* update time stamps */
|
||||
error = do_touch(ip, size);
|
||||
ret = inode_newsize_ok(inode, newsize);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return error;
|
||||
oldsize = inode->i_size;
|
||||
if (newsize >= oldsize)
|
||||
return do_grow(inode, newsize);
|
||||
|
||||
return do_shrink(inode, oldsize, newsize);
|
||||
}
|
||||
|
||||
int gfs2_truncatei_resume(struct gfs2_inode *ip)
|
||||
{
|
||||
int error;
|
||||
error = trunc_dealloc(ip, ip->i_disksize);
|
||||
error = trunc_dealloc(ip, i_size_read(&ip->i_inode));
|
||||
if (!error)
|
||||
error = trunc_end(ip);
|
||||
return error;
|
||||
@ -1269,7 +1258,7 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
|
||||
|
||||
shift = sdp->sd_sb.sb_bsize_shift;
|
||||
BUG_ON(gfs2_is_dir(ip));
|
||||
end_of_file = (ip->i_disksize + sdp->sd_sb.sb_bsize - 1) >> shift;
|
||||
end_of_file = (i_size_read(&ip->i_inode) + 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)
|
||||
|
@ -44,14 +44,16 @@ static inline void gfs2_write_calc_reserv(const struct gfs2_inode *ip,
|
||||
}
|
||||
}
|
||||
|
||||
int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page);
|
||||
int gfs2_block_map(struct inode *inode, sector_t lblock, struct buffer_head *bh, int create);
|
||||
int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen);
|
||||
|
||||
int gfs2_truncatei(struct gfs2_inode *ip, u64 size);
|
||||
int gfs2_truncatei_resume(struct gfs2_inode *ip);
|
||||
int gfs2_file_dealloc(struct gfs2_inode *ip);
|
||||
int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
|
||||
unsigned int len);
|
||||
extern int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page);
|
||||
extern int gfs2_block_map(struct inode *inode, sector_t lblock,
|
||||
struct buffer_head *bh, int create);
|
||||
extern int gfs2_extent_map(struct inode *inode, u64 lblock, int *new,
|
||||
u64 *dblock, unsigned *extlen);
|
||||
extern int gfs2_setattr_size(struct inode *inode, u64 size);
|
||||
extern void gfs2_trim_blocks(struct inode *inode);
|
||||
extern int gfs2_truncatei_resume(struct gfs2_inode *ip);
|
||||
extern int gfs2_file_dealloc(struct gfs2_inode *ip);
|
||||
extern int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
|
||||
unsigned int len);
|
||||
|
||||
#endif /* __BMAP_DOT_H__ */
|
||||
|
@ -49,7 +49,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
ip = GFS2_I(inode);
|
||||
}
|
||||
|
||||
if (sdp->sd_args.ar_localcaching)
|
||||
if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
|
||||
goto valid;
|
||||
|
||||
had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL);
|
||||
|
@ -79,6 +79,9 @@
|
||||
#define gfs2_disk_hash2offset(h) (((u64)(h)) >> 1)
|
||||
#define gfs2_dir_offset2hash(p) ((u32)(((u64)(p)) << 1))
|
||||
|
||||
struct qstr gfs2_qdot __read_mostly;
|
||||
struct qstr gfs2_qdotdot __read_mostly;
|
||||
|
||||
typedef int (*leaf_call_t) (struct gfs2_inode *dip, u32 index, u32 len,
|
||||
u64 leaf_no, void *data);
|
||||
typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent,
|
||||
@ -127,8 +130,8 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
|
||||
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
|
||||
if (ip->i_disksize < offset + size)
|
||||
ip->i_disksize = offset + size;
|
||||
if (ip->i_inode.i_size < offset + size)
|
||||
i_size_write(&ip->i_inode, offset + size);
|
||||
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
|
||||
@ -225,8 +228,8 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (ip->i_disksize < offset + copied)
|
||||
ip->i_disksize = offset + copied;
|
||||
if (ip->i_inode.i_size < offset + copied)
|
||||
i_size_write(&ip->i_inode, offset + copied);
|
||||
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
|
||||
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
@ -275,12 +278,13 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf, u64 offset,
|
||||
unsigned int o;
|
||||
int copied = 0;
|
||||
int error = 0;
|
||||
u64 disksize = i_size_read(&ip->i_inode);
|
||||
|
||||
if (offset >= ip->i_disksize)
|
||||
if (offset >= disksize)
|
||||
return 0;
|
||||
|
||||
if (offset + size > ip->i_disksize)
|
||||
size = ip->i_disksize - offset;
|
||||
if (offset + size > disksize)
|
||||
size = disksize - offset;
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
@ -727,7 +731,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
|
||||
unsigned hsize = 1 << ip->i_depth;
|
||||
unsigned index;
|
||||
u64 ln;
|
||||
if (hsize * sizeof(u64) != ip->i_disksize) {
|
||||
if (hsize * sizeof(u64) != i_size_read(inode)) {
|
||||
gfs2_consist_inode(ip);
|
||||
return ERR_PTR(-EIO);
|
||||
}
|
||||
@ -879,7 +883,7 @@ static int dir_make_exhash(struct inode *inode)
|
||||
for (x = sdp->sd_hash_ptrs; x--; lp++)
|
||||
*lp = cpu_to_be64(bn);
|
||||
|
||||
dip->i_disksize = sdp->sd_sb.sb_bsize / 2;
|
||||
i_size_write(inode, sdp->sd_sb.sb_bsize / 2);
|
||||
gfs2_add_inode_blocks(&dip->i_inode, 1);
|
||||
dip->i_diskflags |= GFS2_DIF_EXHASH;
|
||||
|
||||
@ -1057,11 +1061,12 @@ static int dir_double_exhash(struct gfs2_inode *dip)
|
||||
u64 *buf;
|
||||
u64 *from, *to;
|
||||
u64 block;
|
||||
u64 disksize = i_size_read(&dip->i_inode);
|
||||
int x;
|
||||
int error = 0;
|
||||
|
||||
hsize = 1 << dip->i_depth;
|
||||
if (hsize * sizeof(u64) != dip->i_disksize) {
|
||||
if (hsize * sizeof(u64) != disksize) {
|
||||
gfs2_consist_inode(dip);
|
||||
return -EIO;
|
||||
}
|
||||
@ -1072,7 +1077,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
for (block = dip->i_disksize >> sdp->sd_hash_bsize_shift; block--;) {
|
||||
for (block = disksize >> sdp->sd_hash_bsize_shift; block--;) {
|
||||
error = gfs2_dir_read_data(dip, (char *)buf,
|
||||
block * sdp->sd_hash_bsize,
|
||||
sdp->sd_hash_bsize, 1);
|
||||
@ -1370,7 +1375,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
|
||||
unsigned depth = 0;
|
||||
|
||||
hsize = 1 << dip->i_depth;
|
||||
if (hsize * sizeof(u64) != dip->i_disksize) {
|
||||
if (hsize * sizeof(u64) != i_size_read(inode)) {
|
||||
gfs2_consist_inode(dip);
|
||||
return -EIO;
|
||||
}
|
||||
@ -1784,7 +1789,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
|
||||
int error = 0;
|
||||
|
||||
hsize = 1 << dip->i_depth;
|
||||
if (hsize * sizeof(u64) != dip->i_disksize) {
|
||||
if (hsize * sizeof(u64) != i_size_read(&dip->i_inode)) {
|
||||
gfs2_consist_inode(dip);
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -17,23 +17,24 @@ struct inode;
|
||||
struct gfs2_inode;
|
||||
struct gfs2_inum;
|
||||
|
||||
struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *filename);
|
||||
int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
|
||||
const struct gfs2_inode *ip);
|
||||
int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
|
||||
const struct gfs2_inode *ip, unsigned int type);
|
||||
int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
|
||||
int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
|
||||
filldir_t filldir);
|
||||
int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
|
||||
const struct gfs2_inode *nip, unsigned int new_type);
|
||||
extern struct inode *gfs2_dir_search(struct inode *dir,
|
||||
const struct qstr *filename);
|
||||
extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
|
||||
const struct gfs2_inode *ip);
|
||||
extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
|
||||
const struct gfs2_inode *ip, unsigned int type);
|
||||
extern int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
|
||||
extern int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
|
||||
filldir_t filldir);
|
||||
extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
|
||||
const struct gfs2_inode *nip, unsigned int new_type);
|
||||
|
||||
int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
|
||||
extern int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
|
||||
|
||||
int gfs2_diradd_alloc_required(struct inode *dir,
|
||||
const struct qstr *filename);
|
||||
int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
|
||||
struct buffer_head **bhp);
|
||||
extern int gfs2_diradd_alloc_required(struct inode *dir,
|
||||
const struct qstr *filename);
|
||||
extern int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
|
||||
struct buffer_head **bhp);
|
||||
|
||||
static inline u32 gfs2_disk_hash(const char *data, int len)
|
||||
{
|
||||
@ -61,4 +62,7 @@ static inline void gfs2_qstr2dirent(const struct qstr *name, u16 reclen, struct
|
||||
memcpy(dent + 1, name->name, name->len);
|
||||
}
|
||||
|
||||
extern struct qstr gfs2_qdot;
|
||||
extern struct qstr gfs2_qdotdot;
|
||||
|
||||
#endif /* __DIR_DOT_H__ */
|
||||
|
@ -126,16 +126,9 @@ static int gfs2_get_name(struct dentry *parent, char *name,
|
||||
|
||||
static struct dentry *gfs2_get_parent(struct dentry *child)
|
||||
{
|
||||
struct qstr dotdot;
|
||||
struct dentry *dentry;
|
||||
|
||||
/*
|
||||
* XXX(hch): it would be a good idea to keep this around as a
|
||||
* static variable.
|
||||
*/
|
||||
gfs2_str2qstr(&dotdot, "..");
|
||||
|
||||
dentry = d_obtain_alias(gfs2_lookupi(child->d_inode, &dotdot, 1));
|
||||
dentry = d_obtain_alias(gfs2_lookupi(child->d_inode, &gfs2_qdotdot, 1));
|
||||
if (!IS_ERR(dentry))
|
||||
dentry->d_op = &gfs2_dops;
|
||||
return dentry;
|
||||
|
@ -382,8 +382,10 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
rblocks = RES_DINODE + ind_blocks;
|
||||
if (gfs2_is_jdata(ip))
|
||||
rblocks += data_blocks ? data_blocks : 1;
|
||||
if (ind_blocks || data_blocks)
|
||||
if (ind_blocks || data_blocks) {
|
||||
rblocks += RES_STATFS + RES_QUOTA;
|
||||
rblocks += gfs2_rg_blocks(al);
|
||||
}
|
||||
ret = gfs2_trans_begin(sdp, rblocks, 0);
|
||||
if (ret)
|
||||
goto out_trans_fail;
|
||||
@ -491,7 +493,7 @@ static int gfs2_open(struct inode *inode, struct file *file)
|
||||
goto fail;
|
||||
|
||||
if (!(file->f_flags & O_LARGEFILE) &&
|
||||
ip->i_disksize > MAX_NON_LFS) {
|
||||
i_size_read(inode) > MAX_NON_LFS) {
|
||||
error = -EOVERFLOW;
|
||||
goto fail_gunlock;
|
||||
}
|
||||
|
@ -441,6 +441,8 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state)
|
||||
else
|
||||
gfs2_glock_put_nolock(gl);
|
||||
}
|
||||
if (held1 && held2 && list_empty(&gl->gl_holders))
|
||||
clear_bit(GLF_QUEUED, &gl->gl_flags);
|
||||
|
||||
gl->gl_state = new_state;
|
||||
gl->gl_tchange = jiffies;
|
||||
@ -1012,6 +1014,7 @@ __acquires(&gl->gl_spin)
|
||||
if (unlikely((gh->gh_flags & LM_FLAG_PRIORITY) && !insert_pt))
|
||||
insert_pt = &gh2->gh_list;
|
||||
}
|
||||
set_bit(GLF_QUEUED, &gl->gl_flags);
|
||||
if (likely(insert_pt == NULL)) {
|
||||
list_add_tail(&gh->gh_list, &gl->gl_holders);
|
||||
if (unlikely(gh->gh_flags & LM_FLAG_PRIORITY))
|
||||
@ -1310,10 +1313,12 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
|
||||
|
||||
gfs2_glock_hold(gl);
|
||||
holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time;
|
||||
if (time_before(now, holdtime))
|
||||
delay = holdtime - now;
|
||||
if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
|
||||
delay = gl->gl_ops->go_min_hold_time;
|
||||
if (test_bit(GLF_QUEUED, &gl->gl_flags)) {
|
||||
if (time_before(now, holdtime))
|
||||
delay = holdtime - now;
|
||||
if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
|
||||
delay = gl->gl_ops->go_min_hold_time;
|
||||
}
|
||||
|
||||
spin_lock(&gl->gl_spin);
|
||||
handle_callback(gl, state, delay);
|
||||
@ -1512,7 +1517,7 @@ static void clear_glock(struct gfs2_glock *gl)
|
||||
spin_unlock(&lru_lock);
|
||||
|
||||
spin_lock(&gl->gl_spin);
|
||||
if (find_first_holder(gl) == NULL && gl->gl_state != LM_ST_UNLOCKED)
|
||||
if (gl->gl_state != LM_ST_UNLOCKED)
|
||||
handle_callback(gl, LM_ST_UNLOCKED, 0);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
gfs2_glock_hold(gl);
|
||||
@ -1660,6 +1665,8 @@ static const char *gflags2str(char *buf, const unsigned long *gflags)
|
||||
*p++ = 'I';
|
||||
if (test_bit(GLF_FROZEN, gflags))
|
||||
*p++ = 'F';
|
||||
if (test_bit(GLF_QUEUED, gflags))
|
||||
*p++ = 'q';
|
||||
*p = 0;
|
||||
return buf;
|
||||
}
|
||||
@ -1776,10 +1783,12 @@ int __init gfs2_glock_init(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
glock_workqueue = create_workqueue("glock_workqueue");
|
||||
glock_workqueue = alloc_workqueue("glock_workqueue", WQ_RESCUER |
|
||||
WQ_HIGHPRI | WQ_FREEZEABLE, 0);
|
||||
if (IS_ERR(glock_workqueue))
|
||||
return PTR_ERR(glock_workqueue);
|
||||
gfs2_delete_workqueue = create_workqueue("delete_workqueue");
|
||||
gfs2_delete_workqueue = alloc_workqueue("delete_workqueue", WQ_RESCUER |
|
||||
WQ_FREEZEABLE, 0);
|
||||
if (IS_ERR(gfs2_delete_workqueue)) {
|
||||
destroy_workqueue(glock_workqueue);
|
||||
return PTR_ERR(gfs2_delete_workqueue);
|
||||
|
@ -215,7 +215,7 @@ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
|
||||
void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* gfs2_glock_nq_init - intialize a holder and enqueue it on a glock
|
||||
* gfs2_glock_nq_init - initialize a holder and enqueue it on a glock
|
||||
* @gl: the glock
|
||||
* @state: the state we're requesting
|
||||
* @flags: the modifier flags
|
||||
|
@ -262,13 +262,12 @@ static int inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)
|
||||
const struct gfs2_inode *ip = gl->gl_object;
|
||||
if (ip == NULL)
|
||||
return 0;
|
||||
gfs2_print_dbg(seq, " I: n:%llu/%llu t:%u f:0x%02lx d:0x%08x s:%llu/%llu\n",
|
||||
gfs2_print_dbg(seq, " I: n:%llu/%llu t:%u f:0x%02lx d:0x%08x s:%llu\n",
|
||||
(unsigned long long)ip->i_no_formal_ino,
|
||||
(unsigned long long)ip->i_no_addr,
|
||||
IF2DT(ip->i_inode.i_mode), ip->i_flags,
|
||||
(unsigned int)ip->i_diskflags,
|
||||
(unsigned long long)ip->i_inode.i_size,
|
||||
(unsigned long long)ip->i_disksize);
|
||||
(unsigned long long)i_size_read(&ip->i_inode));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -453,7 +452,6 @@ const struct gfs2_glock_operations *gfs2_glops_list[] = {
|
||||
[LM_TYPE_META] = &gfs2_meta_glops,
|
||||
[LM_TYPE_INODE] = &gfs2_inode_glops,
|
||||
[LM_TYPE_RGRP] = &gfs2_rgrp_glops,
|
||||
[LM_TYPE_NONDISK] = &gfs2_trans_glops,
|
||||
[LM_TYPE_IOPEN] = &gfs2_iopen_glops,
|
||||
[LM_TYPE_FLOCK] = &gfs2_flock_glops,
|
||||
[LM_TYPE_NONDISK] = &gfs2_nondisk_glops,
|
||||
|
@ -196,6 +196,7 @@ enum {
|
||||
GLF_REPLY_PENDING = 9,
|
||||
GLF_INITIAL = 10,
|
||||
GLF_FROZEN = 11,
|
||||
GLF_QUEUED = 12,
|
||||
};
|
||||
|
||||
struct gfs2_glock {
|
||||
@ -267,7 +268,6 @@ struct gfs2_inode {
|
||||
u64 i_no_formal_ino;
|
||||
u64 i_generation;
|
||||
u64 i_eattr;
|
||||
loff_t i_disksize;
|
||||
unsigned long i_flags; /* GIF_... */
|
||||
struct gfs2_glock *i_gl; /* Move into i_gh? */
|
||||
struct gfs2_holder i_iopen_gh;
|
||||
@ -416,11 +416,8 @@ struct gfs2_args {
|
||||
char ar_locktable[GFS2_LOCKNAME_LEN]; /* Name of the Lock Table */
|
||||
char ar_hostdata[GFS2_LOCKNAME_LEN]; /* Host specific data */
|
||||
unsigned int ar_spectator:1; /* Don't get a journal */
|
||||
unsigned int ar_ignore_local_fs:1; /* Ignore optimisations */
|
||||
unsigned int ar_localflocks:1; /* Let the VFS do flock|fcntl */
|
||||
unsigned int ar_localcaching:1; /* Local caching */
|
||||
unsigned int ar_debug:1; /* Oops on errors */
|
||||
unsigned int ar_upgrade:1; /* Upgrade ondisk format */
|
||||
unsigned int ar_posix_acl:1; /* Enable posix acls */
|
||||
unsigned int ar_quota:2; /* off/account/on */
|
||||
unsigned int ar_suiddir:1; /* suiddir support */
|
||||
@ -497,7 +494,7 @@ struct gfs2_sb_host {
|
||||
*/
|
||||
|
||||
struct lm_lockstruct {
|
||||
unsigned int ls_jid;
|
||||
int ls_jid;
|
||||
unsigned int ls_first;
|
||||
unsigned int ls_first_done;
|
||||
unsigned int ls_nodir;
|
||||
@ -572,6 +569,7 @@ struct gfs2_sbd {
|
||||
struct list_head sd_rindex_mru_list;
|
||||
struct gfs2_rgrpd *sd_rindex_forward;
|
||||
unsigned int sd_rgrps;
|
||||
unsigned int sd_max_rg_data;
|
||||
|
||||
/* Journal index stuff */
|
||||
|
||||
|
@ -359,8 +359,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
|
||||
* to do that.
|
||||
*/
|
||||
ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink);
|
||||
ip->i_disksize = be64_to_cpu(str->di_size);
|
||||
i_size_write(&ip->i_inode, ip->i_disksize);
|
||||
i_size_write(&ip->i_inode, be64_to_cpu(str->di_size));
|
||||
gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
|
||||
atime.tv_sec = be64_to_cpu(str->di_atime);
|
||||
atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
|
||||
@ -1055,7 +1054,7 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
|
||||
str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
|
||||
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(ip->i_disksize);
|
||||
str->di_size = cpu_to_be64(i_size_read(&ip->i_inode));
|
||||
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);
|
||||
@ -1085,8 +1084,8 @@ void gfs2_dinode_print(const struct gfs2_inode *ip)
|
||||
(unsigned long long)ip->i_no_formal_ino);
|
||||
printk(KERN_INFO " no_addr = %llu\n",
|
||||
(unsigned long long)ip->i_no_addr);
|
||||
printk(KERN_INFO " i_disksize = %llu\n",
|
||||
(unsigned long long)ip->i_disksize);
|
||||
printk(KERN_INFO " i_size = %llu\n",
|
||||
(unsigned long long)i_size_read(&ip->i_inode));
|
||||
printk(KERN_INFO " blocks = %llu\n",
|
||||
(unsigned long long)gfs2_get_inode_blocks(&ip->i_inode));
|
||||
printk(KERN_INFO " i_goal = %llu\n",
|
||||
|
@ -19,6 +19,8 @@ extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask);
|
||||
extern int gfs2_internal_read(struct gfs2_inode *ip,
|
||||
struct file_ra_state *ra_state,
|
||||
char *buf, loff_t *pos, unsigned size);
|
||||
extern void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
|
||||
unsigned int from, unsigned int to);
|
||||
extern void gfs2_set_aops(struct inode *inode);
|
||||
|
||||
static inline int gfs2_is_stuffed(const struct gfs2_inode *ip)
|
||||
@ -80,6 +82,19 @@ static inline void gfs2_inum_out(const struct gfs2_inode *ip,
|
||||
dent->de_inum.no_addr = cpu_to_be64(ip->i_no_addr);
|
||||
}
|
||||
|
||||
static inline int gfs2_check_internal_file_size(struct inode *inode,
|
||||
u64 minsize, u64 maxsize)
|
||||
{
|
||||
u64 size = i_size_read(inode);
|
||||
if (size < minsize || size > maxsize)
|
||||
goto err;
|
||||
if (size & ((1 << inode->i_blkbits) - 1))
|
||||
goto err;
|
||||
return 0;
|
||||
err:
|
||||
gfs2_consist_inode(GFS2_I(inode));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
extern void gfs2_set_iop(struct inode *inode);
|
||||
extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type,
|
||||
|
@ -42,9 +42,9 @@ static void gdlm_ast(void *arg)
|
||||
ret |= LM_OUT_CANCELED;
|
||||
goto out;
|
||||
case -EAGAIN: /* Try lock fails */
|
||||
case -EDEADLK: /* Deadlock detected */
|
||||
goto out;
|
||||
case -EINVAL: /* Invalid */
|
||||
case -ENOMEM: /* Out of memory */
|
||||
case -ETIMEDOUT: /* Canceled due to timeout */
|
||||
ret |= LM_OUT_ERROR;
|
||||
goto out;
|
||||
case 0: /* Success */
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "glock.h"
|
||||
#include "quota.h"
|
||||
#include "recovery.h"
|
||||
#include "dir.h"
|
||||
|
||||
static struct shrinker qd_shrinker = {
|
||||
.shrink = gfs2_shrink_qd_memory,
|
||||
@ -78,6 +79,9 @@ static int __init init_gfs2_fs(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
gfs2_str2qstr(&gfs2_qdot, ".");
|
||||
gfs2_str2qstr(&gfs2_qdotdot, "..");
|
||||
|
||||
error = gfs2_sys_init();
|
||||
if (error)
|
||||
return error;
|
||||
@ -140,7 +144,7 @@ static int __init init_gfs2_fs(void)
|
||||
|
||||
error = -ENOMEM;
|
||||
gfs_recovery_wq = alloc_workqueue("gfs_recovery",
|
||||
WQ_NON_REENTRANT | WQ_RESCUER, 0);
|
||||
WQ_RESCUER | WQ_FREEZEABLE, 0);
|
||||
if (!gfs_recovery_wq)
|
||||
goto fail_wq;
|
||||
|
||||
|
@ -38,14 +38,6 @@
|
||||
#define DO 0
|
||||
#define UNDO 1
|
||||
|
||||
static const u32 gfs2_old_fs_formats[] = {
|
||||
0
|
||||
};
|
||||
|
||||
static const u32 gfs2_old_multihost_formats[] = {
|
||||
0
|
||||
};
|
||||
|
||||
/**
|
||||
* gfs2_tune_init - Fill a gfs2_tune structure with default values
|
||||
* @gt: tune
|
||||
@ -135,8 +127,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
|
||||
|
||||
static int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent)
|
||||
{
|
||||
unsigned int x;
|
||||
|
||||
if (sb->sb_magic != GFS2_MAGIC ||
|
||||
sb->sb_type != GFS2_METATYPE_SB) {
|
||||
if (!silent)
|
||||
@ -150,55 +140,9 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int sile
|
||||
sb->sb_multihost_format == GFS2_FORMAT_MULTI)
|
||||
return 0;
|
||||
|
||||
if (sb->sb_fs_format != GFS2_FORMAT_FS) {
|
||||
for (x = 0; gfs2_old_fs_formats[x]; x++)
|
||||
if (gfs2_old_fs_formats[x] == sb->sb_fs_format)
|
||||
break;
|
||||
fs_warn(sdp, "Unknown on-disk format, unable to mount\n");
|
||||
|
||||
if (!gfs2_old_fs_formats[x]) {
|
||||
printk(KERN_WARNING
|
||||
"GFS2: code version (%u, %u) is incompatible "
|
||||
"with ondisk format (%u, %u)\n",
|
||||
GFS2_FORMAT_FS, GFS2_FORMAT_MULTI,
|
||||
sb->sb_fs_format, sb->sb_multihost_format);
|
||||
printk(KERN_WARNING
|
||||
"GFS2: I don't know how to upgrade this FS\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (sb->sb_multihost_format != GFS2_FORMAT_MULTI) {
|
||||
for (x = 0; gfs2_old_multihost_formats[x]; x++)
|
||||
if (gfs2_old_multihost_formats[x] ==
|
||||
sb->sb_multihost_format)
|
||||
break;
|
||||
|
||||
if (!gfs2_old_multihost_formats[x]) {
|
||||
printk(KERN_WARNING
|
||||
"GFS2: code version (%u, %u) is incompatible "
|
||||
"with ondisk format (%u, %u)\n",
|
||||
GFS2_FORMAT_FS, GFS2_FORMAT_MULTI,
|
||||
sb->sb_fs_format, sb->sb_multihost_format);
|
||||
printk(KERN_WARNING
|
||||
"GFS2: I don't know how to upgrade this FS\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sdp->sd_args.ar_upgrade) {
|
||||
printk(KERN_WARNING
|
||||
"GFS2: code version (%u, %u) is incompatible "
|
||||
"with ondisk format (%u, %u)\n",
|
||||
GFS2_FORMAT_FS, GFS2_FORMAT_MULTI,
|
||||
sb->sb_fs_format, sb->sb_multihost_format);
|
||||
printk(KERN_INFO
|
||||
"GFS2: Use the \"upgrade\" mount option to upgrade "
|
||||
"the FS\n");
|
||||
printk(KERN_INFO "GFS2: See the manual for more details\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void end_bio_io_page(struct bio *bio, int error)
|
||||
@ -586,7 +530,7 @@ static int map_journal_extents(struct gfs2_sbd *sdp)
|
||||
|
||||
prev_db = 0;
|
||||
|
||||
for (lb = 0; lb < ip->i_disksize >> sdp->sd_sb.sb_bsize_shift; lb++) {
|
||||
for (lb = 0; lb < i_size_read(jd->jd_inode) >> sdp->sd_sb.sb_bsize_shift; lb++) {
|
||||
bh.b_state = 0;
|
||||
bh.b_blocknr = 0;
|
||||
bh.b_size = 1 << ip->i_inode.i_blkbits;
|
||||
@ -1022,7 +966,6 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
|
||||
if (!strcmp("lock_nolock", proto)) {
|
||||
lm = &nolock_ops;
|
||||
sdp->sd_args.ar_localflocks = 1;
|
||||
sdp->sd_args.ar_localcaching = 1;
|
||||
#ifdef CONFIG_GFS2_FS_LOCKING_DLM
|
||||
} else if (!strcmp("lock_dlm", proto)) {
|
||||
lm = &gfs2_dlm_ops;
|
||||
@ -1113,8 +1056,6 @@ static int gfs2_journalid_wait(void *word)
|
||||
|
||||
static int wait_on_journal(struct gfs2_sbd *sdp)
|
||||
{
|
||||
if (sdp->sd_args.ar_spectator)
|
||||
return 0;
|
||||
if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
|
||||
return 0;
|
||||
|
||||
@ -1217,6 +1158,20 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent
|
||||
if (error)
|
||||
goto fail_sb;
|
||||
|
||||
/*
|
||||
* If user space has failed to join the cluster or some similar
|
||||
* failure has occurred, then the journal id will contain a
|
||||
* negative (error) number. This will then be returned to the
|
||||
* caller (of the mount syscall). We do this even for spectator
|
||||
* mounts (which just write a jid of 0 to indicate "ok" even though
|
||||
* the jid is unused in the spectator case)
|
||||
*/
|
||||
if (sdp->sd_lockstruct.ls_jid < 0) {
|
||||
error = sdp->sd_lockstruct.ls_jid;
|
||||
sdp->sd_lockstruct.ls_jid = 0;
|
||||
goto fail_sb;
|
||||
}
|
||||
|
||||
error = init_inodes(sdp, DO);
|
||||
if (error)
|
||||
goto fail_sb;
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include <linux/gfs2_ondisk.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/fiemap.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/falloc.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "gfs2.h"
|
||||
@ -217,7 +219,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
|
||||
goto out_gunlock_q;
|
||||
|
||||
error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
|
||||
al->al_rgd->rd_length +
|
||||
gfs2_rg_blocks(al) +
|
||||
2 * RES_DINODE + RES_STATFS +
|
||||
RES_QUOTA, 0);
|
||||
if (error)
|
||||
@ -406,7 +408,6 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
|
||||
|
||||
ip = ghs[1].gh_gl->gl_object;
|
||||
|
||||
ip->i_disksize = size;
|
||||
i_size_write(inode, size);
|
||||
|
||||
error = gfs2_meta_inode_buffer(ip, &dibh);
|
||||
@ -461,7 +462,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
||||
ip = ghs[1].gh_gl->gl_object;
|
||||
|
||||
ip->i_inode.i_nlink = 2;
|
||||
ip->i_disksize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
|
||||
i_size_write(inode, sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode));
|
||||
ip->i_diskflags |= GFS2_DIF_JDATA;
|
||||
ip->i_entries = 2;
|
||||
|
||||
@ -470,18 +471,15 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
||||
if (!gfs2_assert_withdraw(sdp, !error)) {
|
||||
struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data;
|
||||
struct gfs2_dirent *dent = (struct gfs2_dirent *)(di+1);
|
||||
struct qstr str;
|
||||
|
||||
gfs2_str2qstr(&str, ".");
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
gfs2_qstr2dirent(&str, GFS2_DIRENT_SIZE(str.len), dent);
|
||||
gfs2_qstr2dirent(&gfs2_qdot, GFS2_DIRENT_SIZE(gfs2_qdot.len), dent);
|
||||
dent->de_inum = di->di_num; /* already GFS2 endian */
|
||||
dent->de_type = cpu_to_be16(DT_DIR);
|
||||
di->di_entries = cpu_to_be32(1);
|
||||
|
||||
gfs2_str2qstr(&str, "..");
|
||||
dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1));
|
||||
gfs2_qstr2dirent(&str, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent);
|
||||
gfs2_qstr2dirent(&gfs2_qdotdot, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent);
|
||||
|
||||
gfs2_inum_out(dip, dent);
|
||||
dent->de_type = cpu_to_be16(DT_DIR);
|
||||
@ -522,7 +520,6 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
||||
static int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
|
||||
struct gfs2_inode *ip)
|
||||
{
|
||||
struct qstr dotname;
|
||||
int error;
|
||||
|
||||
if (ip->i_entries != 2) {
|
||||
@ -539,13 +536,11 @@ static int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
gfs2_str2qstr(&dotname, ".");
|
||||
error = gfs2_dir_del(ip, &dotname);
|
||||
error = gfs2_dir_del(ip, &gfs2_qdot);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
gfs2_str2qstr(&dotname, "..");
|
||||
error = gfs2_dir_del(ip, &dotname);
|
||||
error = gfs2_dir_del(ip, &gfs2_qdotdot);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -694,11 +689,8 @@ static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
|
||||
struct inode *dir = &to->i_inode;
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct inode *tmp;
|
||||
struct qstr dotdot;
|
||||
int error = 0;
|
||||
|
||||
gfs2_str2qstr(&dotdot, "..");
|
||||
|
||||
igrab(dir);
|
||||
|
||||
for (;;) {
|
||||
@ -711,7 +703,7 @@ static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
|
||||
break;
|
||||
}
|
||||
|
||||
tmp = gfs2_lookupi(dir, &dotdot, 1);
|
||||
tmp = gfs2_lookupi(dir, &gfs2_qdotdot, 1);
|
||||
if (IS_ERR(tmp)) {
|
||||
error = PTR_ERR(tmp);
|
||||
break;
|
||||
@ -744,7 +736,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
|
||||
struct gfs2_inode *ip = GFS2_I(odentry->d_inode);
|
||||
struct gfs2_inode *nip = NULL;
|
||||
struct gfs2_sbd *sdp = GFS2_SB(odir);
|
||||
struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, };
|
||||
struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, }, ri_gh;
|
||||
struct gfs2_rgrpd *nrgd;
|
||||
unsigned int num_gh;
|
||||
int dir_rename = 0;
|
||||
@ -758,6 +750,9 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
|
||||
return 0;
|
||||
}
|
||||
|
||||
error = gfs2_rindex_hold(sdp, &ri_gh);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (odip != ndip) {
|
||||
error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE,
|
||||
@ -887,12 +882,12 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
|
||||
|
||||
al->al_requested = sdp->sd_max_dirres;
|
||||
|
||||
error = gfs2_inplace_reserve(ndip);
|
||||
error = gfs2_inplace_reserve_ri(ndip);
|
||||
if (error)
|
||||
goto out_gunlock_q;
|
||||
|
||||
error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
|
||||
al->al_rgd->rd_length +
|
||||
gfs2_rg_blocks(al) +
|
||||
4 * RES_DINODE + 4 * RES_LEAF +
|
||||
RES_STATFS + RES_QUOTA + 4, 0);
|
||||
if (error)
|
||||
@ -920,9 +915,6 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
|
||||
}
|
||||
|
||||
if (dir_rename) {
|
||||
struct qstr name;
|
||||
gfs2_str2qstr(&name, "..");
|
||||
|
||||
error = gfs2_change_nlink(ndip, +1);
|
||||
if (error)
|
||||
goto out_end_trans;
|
||||
@ -930,7 +922,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
|
||||
if (error)
|
||||
goto out_end_trans;
|
||||
|
||||
error = gfs2_dir_mvino(ip, &name, ndip, DT_DIR);
|
||||
error = gfs2_dir_mvino(ip, &gfs2_qdotdot, ndip, DT_DIR);
|
||||
if (error)
|
||||
goto out_end_trans;
|
||||
} else {
|
||||
@ -972,6 +964,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
|
||||
if (r_gh.gh_gl)
|
||||
gfs2_glock_dq_uninit(&r_gh);
|
||||
out:
|
||||
gfs2_glock_dq_uninit(&ri_gh);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -990,7 +983,7 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
|
||||
struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
|
||||
struct gfs2_holder i_gh;
|
||||
struct buffer_head *dibh;
|
||||
unsigned int x;
|
||||
unsigned int x, size;
|
||||
char *buf;
|
||||
int error;
|
||||
|
||||
@ -1002,7 +995,8 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ip->i_disksize) {
|
||||
size = (unsigned int)i_size_read(&ip->i_inode);
|
||||
if (size == 0) {
|
||||
gfs2_consist_inode(ip);
|
||||
buf = ERR_PTR(-EIO);
|
||||
goto out;
|
||||
@ -1014,7 +1008,7 @@ static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
x = ip->i_disksize + 1;
|
||||
x = size + 1;
|
||||
buf = kmalloc(x, GFP_NOFS);
|
||||
if (!buf)
|
||||
buf = ERR_PTR(-ENOMEM);
|
||||
@ -1071,30 +1065,6 @@ int gfs2_permission(struct inode *inode, int mask)
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX(truncate): the truncate_setsize calls should be moved to the end.
|
||||
*/
|
||||
static int setattr_size(struct inode *inode, struct iattr *attr)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
int error;
|
||||
|
||||
if (attr->ia_size != ip->i_disksize) {
|
||||
error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks);
|
||||
if (error)
|
||||
return error;
|
||||
truncate_setsize(inode, attr->ia_size);
|
||||
gfs2_trans_end(sdp);
|
||||
}
|
||||
|
||||
error = gfs2_truncatei(ip, attr->ia_size);
|
||||
if (error && (inode->i_size != ip->i_disksize))
|
||||
i_size_write(inode, ip->i_disksize);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int setattr_chown(struct inode *inode, struct iattr *attr)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
@ -1195,7 +1165,7 @@ static int gfs2_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
goto out;
|
||||
|
||||
if (attr->ia_valid & ATTR_SIZE)
|
||||
error = setattr_size(inode, attr);
|
||||
error = gfs2_setattr_size(inode, attr->ia_size);
|
||||
else if (attr->ia_valid & (ATTR_UID | ATTR_GID))
|
||||
error = setattr_chown(inode, attr);
|
||||
else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode))
|
||||
@ -1301,6 +1271,257 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void empty_write_end(struct page *page, unsigned from,
|
||||
unsigned to)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(page->mapping->host);
|
||||
|
||||
page_zero_new_buffers(page, from, to);
|
||||
flush_dcache_page(page);
|
||||
mark_page_accessed(page);
|
||||
|
||||
if (!gfs2_is_writeback(ip))
|
||||
gfs2_page_add_databufs(ip, page, from, to);
|
||||
|
||||
block_commit_write(page, from, to);
|
||||
}
|
||||
|
||||
|
||||
static int write_empty_blocks(struct page *page, unsigned from, unsigned to)
|
||||
{
|
||||
unsigned start, end, next;
|
||||
struct buffer_head *bh, *head;
|
||||
int error;
|
||||
|
||||
if (!page_has_buffers(page)) {
|
||||
error = block_prepare_write(page, from, to, gfs2_block_map);
|
||||
if (unlikely(error))
|
||||
return error;
|
||||
|
||||
empty_write_end(page, from, to);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bh = head = page_buffers(page);
|
||||
next = end = 0;
|
||||
while (next < from) {
|
||||
next += bh->b_size;
|
||||
bh = bh->b_this_page;
|
||||
}
|
||||
start = next;
|
||||
do {
|
||||
next += bh->b_size;
|
||||
if (buffer_mapped(bh)) {
|
||||
if (end) {
|
||||
error = block_prepare_write(page, start, end,
|
||||
gfs2_block_map);
|
||||
if (unlikely(error))
|
||||
return error;
|
||||
empty_write_end(page, start, end);
|
||||
end = 0;
|
||||
}
|
||||
start = next;
|
||||
}
|
||||
else
|
||||
end = next;
|
||||
bh = bh->b_this_page;
|
||||
} while (next < to);
|
||||
|
||||
if (end) {
|
||||
error = block_prepare_write(page, start, end, gfs2_block_map);
|
||||
if (unlikely(error))
|
||||
return error;
|
||||
empty_write_end(page, start, end);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
|
||||
int mode)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct buffer_head *dibh;
|
||||
int error;
|
||||
u64 start = offset >> PAGE_CACHE_SHIFT;
|
||||
unsigned int start_offset = offset & ~PAGE_CACHE_MASK;
|
||||
u64 end = (offset + len - 1) >> PAGE_CACHE_SHIFT;
|
||||
pgoff_t curr;
|
||||
struct page *page;
|
||||
unsigned int end_offset = (offset + len) & ~PAGE_CACHE_MASK;
|
||||
unsigned int from, to;
|
||||
|
||||
if (!end_offset)
|
||||
end_offset = PAGE_CACHE_SIZE;
|
||||
|
||||
error = gfs2_meta_inode_buffer(ip, &dibh);
|
||||
if (unlikely(error))
|
||||
goto out;
|
||||
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
|
||||
if (gfs2_is_stuffed(ip)) {
|
||||
error = gfs2_unstuff_dinode(ip, NULL);
|
||||
if (unlikely(error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
curr = start;
|
||||
offset = start << PAGE_CACHE_SHIFT;
|
||||
from = start_offset;
|
||||
to = PAGE_CACHE_SIZE;
|
||||
while (curr <= end) {
|
||||
page = grab_cache_page_write_begin(inode->i_mapping, curr,
|
||||
AOP_FLAG_NOFS);
|
||||
if (unlikely(!page)) {
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (curr == end)
|
||||
to = end_offset;
|
||||
error = write_empty_blocks(page, from, to);
|
||||
if (!error && offset + to > inode->i_size &&
|
||||
!(mode & FALLOC_FL_KEEP_SIZE)) {
|
||||
i_size_write(inode, offset + to);
|
||||
}
|
||||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
if (error)
|
||||
goto out;
|
||||
curr++;
|
||||
offset += PAGE_CACHE_SIZE;
|
||||
from = 0;
|
||||
}
|
||||
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
mark_inode_dirty(inode);
|
||||
|
||||
brelse(dibh);
|
||||
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
static void calc_max_reserv(struct gfs2_inode *ip, loff_t max, loff_t *len,
|
||||
unsigned int *data_blocks, unsigned int *ind_blocks)
|
||||
{
|
||||
const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
unsigned int max_blocks = ip->i_alloc->al_rgd->rd_free_clone;
|
||||
unsigned int tmp, max_data = max_blocks - 3 * (sdp->sd_max_height - 1);
|
||||
|
||||
for (tmp = max_data; tmp > sdp->sd_diptrs;) {
|
||||
tmp = DIV_ROUND_UP(tmp, sdp->sd_inptrs);
|
||||
max_data -= tmp;
|
||||
}
|
||||
/* This calculation isn't the exact reverse of gfs2_write_calc_reserve,
|
||||
so it might end up with fewer data blocks */
|
||||
if (max_data <= *data_blocks)
|
||||
return;
|
||||
*data_blocks = max_data;
|
||||
*ind_blocks = max_blocks - max_data;
|
||||
*len = ((loff_t)max_data - 3) << sdp->sd_sb.sb_bsize_shift;
|
||||
if (*len > max) {
|
||||
*len = max;
|
||||
gfs2_write_calc_reserv(ip, max, data_blocks, ind_blocks);
|
||||
}
|
||||
}
|
||||
|
||||
static long gfs2_fallocate(struct inode *inode, int mode, loff_t offset,
|
||||
loff_t len)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
|
||||
loff_t bytes, max_bytes;
|
||||
struct gfs2_alloc *al;
|
||||
int error;
|
||||
loff_t next = (offset + len - 1) >> sdp->sd_sb.sb_bsize_shift;
|
||||
next = (next + 1) << sdp->sd_sb.sb_bsize_shift;
|
||||
|
||||
offset = (offset >> sdp->sd_sb.sb_bsize_shift) <<
|
||||
sdp->sd_sb.sb_bsize_shift;
|
||||
|
||||
len = next - offset;
|
||||
bytes = sdp->sd_max_rg_data * sdp->sd_sb.sb_bsize / 2;
|
||||
if (!bytes)
|
||||
bytes = UINT_MAX;
|
||||
|
||||
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh);
|
||||
error = gfs2_glock_nq(&ip->i_gh);
|
||||
if (unlikely(error))
|
||||
goto out_uninit;
|
||||
|
||||
if (!gfs2_write_alloc_required(ip, offset, len))
|
||||
goto out_unlock;
|
||||
|
||||
while (len > 0) {
|
||||
if (len < bytes)
|
||||
bytes = len;
|
||||
al = gfs2_alloc_get(ip);
|
||||
if (!al) {
|
||||
error = -ENOMEM;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
error = gfs2_quota_lock_check(ip);
|
||||
if (error)
|
||||
goto out_alloc_put;
|
||||
|
||||
retry:
|
||||
gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks);
|
||||
|
||||
al->al_requested = data_blocks + ind_blocks;
|
||||
error = gfs2_inplace_reserve(ip);
|
||||
if (error) {
|
||||
if (error == -ENOSPC && bytes > sdp->sd_sb.sb_bsize) {
|
||||
bytes >>= 1;
|
||||
goto retry;
|
||||
}
|
||||
goto out_qunlock;
|
||||
}
|
||||
max_bytes = bytes;
|
||||
calc_max_reserv(ip, len, &max_bytes, &data_blocks, &ind_blocks);
|
||||
al->al_requested = data_blocks + ind_blocks;
|
||||
|
||||
rblocks = RES_DINODE + ind_blocks + RES_STATFS + RES_QUOTA +
|
||||
RES_RG_HDR + gfs2_rg_blocks(al);
|
||||
if (gfs2_is_jdata(ip))
|
||||
rblocks += data_blocks ? data_blocks : 1;
|
||||
|
||||
error = gfs2_trans_begin(sdp, rblocks,
|
||||
PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize);
|
||||
if (error)
|
||||
goto out_trans_fail;
|
||||
|
||||
error = fallocate_chunk(inode, offset, max_bytes, mode);
|
||||
gfs2_trans_end(sdp);
|
||||
|
||||
if (error)
|
||||
goto out_trans_fail;
|
||||
|
||||
len -= max_bytes;
|
||||
offset += max_bytes;
|
||||
gfs2_inplace_release(ip);
|
||||
gfs2_quota_unlock(ip);
|
||||
gfs2_alloc_put(ip);
|
||||
}
|
||||
goto out_unlock;
|
||||
|
||||
out_trans_fail:
|
||||
gfs2_inplace_release(ip);
|
||||
out_qunlock:
|
||||
gfs2_quota_unlock(ip);
|
||||
out_alloc_put:
|
||||
gfs2_alloc_put(ip);
|
||||
out_unlock:
|
||||
gfs2_glock_dq(&ip->i_gh);
|
||||
out_uninit:
|
||||
gfs2_holder_uninit(&ip->i_gh);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
||||
u64 start, u64 len)
|
||||
{
|
||||
@ -1351,6 +1572,7 @@ const struct inode_operations gfs2_file_iops = {
|
||||
.getxattr = gfs2_getxattr,
|
||||
.listxattr = gfs2_listxattr,
|
||||
.removexattr = gfs2_removexattr,
|
||||
.fallocate = gfs2_fallocate,
|
||||
.fiemap = gfs2_fiemap,
|
||||
};
|
||||
|
||||
|
@ -735,10 +735,8 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
|
||||
goto out;
|
||||
|
||||
size = loc + sizeof(struct gfs2_quota);
|
||||
if (size > inode->i_size) {
|
||||
ip->i_disksize = size;
|
||||
if (size > inode->i_size)
|
||||
i_size_write(inode, size);
|
||||
}
|
||||
inode->i_mtime = inode->i_atime = CURRENT_TIME;
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
@ -817,7 +815,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
|
||||
goto out_alloc;
|
||||
|
||||
if (nalloc)
|
||||
blocks += al->al_rgd->rd_length + nalloc * ind_blocks + RES_STATFS;
|
||||
blocks += gfs2_rg_blocks(al) + nalloc * ind_blocks + RES_STATFS;
|
||||
|
||||
error = gfs2_trans_begin(sdp, blocks, 0);
|
||||
if (error)
|
||||
@ -1190,18 +1188,17 @@ static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *
|
||||
int gfs2_quota_init(struct gfs2_sbd *sdp)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
|
||||
unsigned int blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift;
|
||||
u64 size = i_size_read(sdp->sd_qc_inode);
|
||||
unsigned int blocks = size >> sdp->sd_sb.sb_bsize_shift;
|
||||
unsigned int x, slot = 0;
|
||||
unsigned int found = 0;
|
||||
u64 dblock;
|
||||
u32 extlen = 0;
|
||||
int error;
|
||||
|
||||
if (!ip->i_disksize || ip->i_disksize > (64 << 20) ||
|
||||
ip->i_disksize & (sdp->sd_sb.sb_bsize - 1)) {
|
||||
gfs2_consist_inode(ip);
|
||||
if (gfs2_check_internal_file_size(sdp->sd_qc_inode, 1, 64 << 20))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
sdp->sd_quota_slots = blocks * sdp->sd_qc_per_block;
|
||||
sdp->sd_quota_chunks = DIV_ROUND_UP(sdp->sd_quota_slots, 8 * PAGE_SIZE);
|
||||
|
||||
@ -1589,6 +1586,7 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
|
||||
error = gfs2_inplace_reserve(ip);
|
||||
if (error)
|
||||
goto out_alloc;
|
||||
blocks += gfs2_rg_blocks(al);
|
||||
}
|
||||
|
||||
error = gfs2_trans_begin(sdp, blocks + RES_DINODE + 1, 0);
|
||||
|
@ -455,11 +455,13 @@ void gfs2_recover_func(struct work_struct *work)
|
||||
int ro = 0;
|
||||
unsigned int pass;
|
||||
int error;
|
||||
int jlocked = 0;
|
||||
|
||||
if (jd->jd_jid != sdp->sd_lockstruct.ls_jid) {
|
||||
if (sdp->sd_args.ar_spectator ||
|
||||
(jd->jd_jid != sdp->sd_lockstruct.ls_jid)) {
|
||||
fs_info(sdp, "jid=%u: Trying to acquire journal lock...\n",
|
||||
jd->jd_jid);
|
||||
|
||||
jlocked = 1;
|
||||
/* Acquire the journal lock so we can do recovery */
|
||||
|
||||
error = gfs2_glock_nq_num(sdp, jd->jd_jid, &gfs2_journal_glops,
|
||||
@ -554,13 +556,12 @@ void gfs2_recover_func(struct work_struct *work)
|
||||
jd->jd_jid, t);
|
||||
}
|
||||
|
||||
if (jd->jd_jid != sdp->sd_lockstruct.ls_jid)
|
||||
gfs2_glock_dq_uninit(&ji_gh);
|
||||
|
||||
gfs2_recovery_done(sdp, jd->jd_jid, LM_RD_SUCCESS);
|
||||
|
||||
if (jd->jd_jid != sdp->sd_lockstruct.ls_jid)
|
||||
if (jlocked) {
|
||||
gfs2_glock_dq_uninit(&ji_gh);
|
||||
gfs2_glock_dq_uninit(&j_gh);
|
||||
}
|
||||
|
||||
fs_info(sdp, "jid=%u: Done\n", jd->jd_jid);
|
||||
goto done;
|
||||
@ -568,7 +569,7 @@ void gfs2_recover_func(struct work_struct *work)
|
||||
fail_gunlock_tr:
|
||||
gfs2_glock_dq_uninit(&t_gh);
|
||||
fail_gunlock_ji:
|
||||
if (jd->jd_jid != sdp->sd_lockstruct.ls_jid) {
|
||||
if (jlocked) {
|
||||
gfs2_glock_dq_uninit(&ji_gh);
|
||||
fail_gunlock_j:
|
||||
gfs2_glock_dq_uninit(&j_gh);
|
||||
|
@ -500,7 +500,7 @@ u64 gfs2_ri_total(struct gfs2_sbd *sdp)
|
||||
for (rgrps = 0;; rgrps++) {
|
||||
loff_t pos = rgrps * sizeof(struct gfs2_rindex);
|
||||
|
||||
if (pos + sizeof(struct gfs2_rindex) >= ip->i_disksize)
|
||||
if (pos + sizeof(struct gfs2_rindex) >= i_size_read(inode))
|
||||
break;
|
||||
error = gfs2_internal_read(ip, &ra_state, buf, &pos,
|
||||
sizeof(struct gfs2_rindex));
|
||||
@ -588,7 +588,9 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
struct inode *inode = &ip->i_inode;
|
||||
struct file_ra_state ra_state;
|
||||
u64 rgrp_count = ip->i_disksize;
|
||||
u64 rgrp_count = i_size_read(inode);
|
||||
struct gfs2_rgrpd *rgd;
|
||||
unsigned int max_data = 0;
|
||||
int error;
|
||||
|
||||
do_div(rgrp_count, sizeof(struct gfs2_rindex));
|
||||
@ -603,6 +605,10 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(rgd, &sdp->sd_rindex_list, rd_list)
|
||||
if (rgd->rd_data > max_data)
|
||||
max_data = rgd->rd_data;
|
||||
sdp->sd_max_rg_data = max_data;
|
||||
sdp->sd_rindex_uptodate = 1;
|
||||
return 0;
|
||||
}
|
||||
@ -622,13 +628,15 @@ static int gfs2_ri_update_special(struct gfs2_inode *ip)
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
struct inode *inode = &ip->i_inode;
|
||||
struct file_ra_state ra_state;
|
||||
struct gfs2_rgrpd *rgd;
|
||||
unsigned int max_data = 0;
|
||||
int error;
|
||||
|
||||
file_ra_state_init(&ra_state, inode->i_mapping);
|
||||
for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
|
||||
/* Ignore partials */
|
||||
if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) >
|
||||
ip->i_disksize)
|
||||
i_size_read(inode))
|
||||
break;
|
||||
error = read_rindex_entry(ip, &ra_state);
|
||||
if (error) {
|
||||
@ -636,6 +644,10 @@ static int gfs2_ri_update_special(struct gfs2_inode *ip)
|
||||
return error;
|
||||
}
|
||||
}
|
||||
list_for_each_entry(rgd, &sdp->sd_rindex_list, rd_list)
|
||||
if (rgd->rd_data > max_data)
|
||||
max_data = rgd->rd_data;
|
||||
sdp->sd_max_rg_data = max_data;
|
||||
|
||||
sdp->sd_rindex_uptodate = 1;
|
||||
return 0;
|
||||
@ -1188,7 +1200,8 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *unlinked,
|
||||
* Returns: errno
|
||||
*/
|
||||
|
||||
int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
|
||||
int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex,
|
||||
char *file, unsigned int line)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
struct gfs2_alloc *al = ip->i_alloc;
|
||||
@ -1199,12 +1212,15 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
|
||||
return -EINVAL;
|
||||
|
||||
try_again:
|
||||
/* We need to hold the rindex unless the inode we're using is
|
||||
the rindex itself, in which case it's already held. */
|
||||
if (ip != GFS2_I(sdp->sd_rindex))
|
||||
error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
|
||||
else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */
|
||||
error = gfs2_ri_update_special(ip);
|
||||
if (hold_rindex) {
|
||||
/* We need to hold the rindex unless the inode we're using is
|
||||
the rindex itself, in which case it's already held. */
|
||||
if (ip != GFS2_I(sdp->sd_rindex))
|
||||
error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
|
||||
else if (!sdp->sd_rgrps) /* We may not have the rindex read
|
||||
in, so: */
|
||||
error = gfs2_ri_update_special(ip);
|
||||
}
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
@ -1215,7 +1231,7 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
|
||||
try to free it, and try the allocation again. */
|
||||
error = get_local_rgrp(ip, &unlinked, &last_unlinked);
|
||||
if (error) {
|
||||
if (ip != GFS2_I(sdp->sd_rindex))
|
||||
if (hold_rindex && ip != GFS2_I(sdp->sd_rindex))
|
||||
gfs2_glock_dq_uninit(&al->al_ri_gh);
|
||||
if (error != -EAGAIN)
|
||||
return error;
|
||||
@ -1257,7 +1273,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip)
|
||||
al->al_rgd = NULL;
|
||||
if (al->al_rgd_gh.gh_gl)
|
||||
gfs2_glock_dq_uninit(&al->al_rgd_gh);
|
||||
if (ip != GFS2_I(sdp->sd_rindex))
|
||||
if (ip != GFS2_I(sdp->sd_rindex) && al->al_ri_gh.gh_gl)
|
||||
gfs2_glock_dq_uninit(&al->al_ri_gh);
|
||||
}
|
||||
|
||||
@ -1496,11 +1512,19 @@ int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n)
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
struct buffer_head *dibh;
|
||||
struct gfs2_alloc *al = ip->i_alloc;
|
||||
struct gfs2_rgrpd *rgd = al->al_rgd;
|
||||
struct gfs2_rgrpd *rgd;
|
||||
u32 goal, blk;
|
||||
u64 block;
|
||||
int error;
|
||||
|
||||
/* Only happens if there is a bug in gfs2, return something distinctive
|
||||
* to ensure that it is noticed.
|
||||
*/
|
||||
if (al == NULL)
|
||||
return -ECANCELED;
|
||||
|
||||
rgd = al->al_rgd;
|
||||
|
||||
if (rgrp_contains_block(rgd, ip->i_goal))
|
||||
goal = ip->i_goal - rgd->rd_data0;
|
||||
else
|
||||
|
@ -39,10 +39,12 @@ static inline void gfs2_alloc_put(struct gfs2_inode *ip)
|
||||
ip->i_alloc = NULL;
|
||||
}
|
||||
|
||||
extern int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file,
|
||||
unsigned int line);
|
||||
extern int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex,
|
||||
char *file, unsigned int line);
|
||||
#define gfs2_inplace_reserve(ip) \
|
||||
gfs2_inplace_reserve_i((ip), __FILE__, __LINE__)
|
||||
gfs2_inplace_reserve_i((ip), 1, __FILE__, __LINE__)
|
||||
#define gfs2_inplace_reserve_ri(ip) \
|
||||
gfs2_inplace_reserve_i((ip), 0, __FILE__, __LINE__)
|
||||
|
||||
extern void gfs2_inplace_release(struct gfs2_inode *ip);
|
||||
|
||||
|
@ -85,6 +85,7 @@ static const match_table_t tokens = {
|
||||
{Opt_locktable, "locktable=%s"},
|
||||
{Opt_hostdata, "hostdata=%s"},
|
||||
{Opt_spectator, "spectator"},
|
||||
{Opt_spectator, "norecovery"},
|
||||
{Opt_ignore_local_fs, "ignore_local_fs"},
|
||||
{Opt_localflocks, "localflocks"},
|
||||
{Opt_localcaching, "localcaching"},
|
||||
@ -159,13 +160,13 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
|
||||
args->ar_spectator = 1;
|
||||
break;
|
||||
case Opt_ignore_local_fs:
|
||||
args->ar_ignore_local_fs = 1;
|
||||
/* Retained for backwards compat only */
|
||||
break;
|
||||
case Opt_localflocks:
|
||||
args->ar_localflocks = 1;
|
||||
break;
|
||||
case Opt_localcaching:
|
||||
args->ar_localcaching = 1;
|
||||
/* Retained for backwards compat only */
|
||||
break;
|
||||
case Opt_debug:
|
||||
if (args->ar_errors == GFS2_ERRORS_PANIC) {
|
||||
@ -179,7 +180,7 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
|
||||
args->ar_debug = 0;
|
||||
break;
|
||||
case Opt_upgrade:
|
||||
args->ar_upgrade = 1;
|
||||
/* Retained for backwards compat only */
|
||||
break;
|
||||
case Opt_acl:
|
||||
args->ar_posix_acl = 1;
|
||||
@ -342,15 +343,14 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
|
||||
u64 size = i_size_read(jd->jd_inode);
|
||||
|
||||
if (ip->i_disksize < (8 << 20) || ip->i_disksize > (1 << 30) ||
|
||||
(ip->i_disksize & (sdp->sd_sb.sb_bsize - 1))) {
|
||||
gfs2_consist_inode(ip);
|
||||
if (gfs2_check_internal_file_size(jd->jd_inode, 8 << 20, 1 << 30))
|
||||
return -EIO;
|
||||
}
|
||||
jd->jd_blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift;
|
||||
|
||||
if (gfs2_write_alloc_required(ip, 0, ip->i_disksize)) {
|
||||
jd->jd_blocks = size >> sdp->sd_sb.sb_bsize_shift;
|
||||
|
||||
if (gfs2_write_alloc_required(ip, 0, size)) {
|
||||
gfs2_consist_inode(ip);
|
||||
return -EIO;
|
||||
}
|
||||
@ -1129,9 +1129,7 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
|
||||
|
||||
/* Some flags must not be changed */
|
||||
if (args_neq(&args, &sdp->sd_args, spectator) ||
|
||||
args_neq(&args, &sdp->sd_args, ignore_local_fs) ||
|
||||
args_neq(&args, &sdp->sd_args, localflocks) ||
|
||||
args_neq(&args, &sdp->sd_args, localcaching) ||
|
||||
args_neq(&args, &sdp->sd_args, meta))
|
||||
return -EINVAL;
|
||||
|
||||
@ -1234,16 +1232,10 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
|
||||
seq_printf(s, ",hostdata=%s", args->ar_hostdata);
|
||||
if (args->ar_spectator)
|
||||
seq_printf(s, ",spectator");
|
||||
if (args->ar_ignore_local_fs)
|
||||
seq_printf(s, ",ignore_local_fs");
|
||||
if (args->ar_localflocks)
|
||||
seq_printf(s, ",localflocks");
|
||||
if (args->ar_localcaching)
|
||||
seq_printf(s, ",localcaching");
|
||||
if (args->ar_debug)
|
||||
seq_printf(s, ",debug");
|
||||
if (args->ar_upgrade)
|
||||
seq_printf(s, ",upgrade");
|
||||
if (args->ar_posix_acl)
|
||||
seq_printf(s, ",acl");
|
||||
if (args->ar_quota != GFS2_QUOTA_DEFAULT) {
|
||||
|
@ -230,7 +230,10 @@ static ssize_t demote_rq_store(struct gfs2_sbd *sdp, const char *buf, size_t len
|
||||
|
||||
if (gltype > LM_TYPE_JOURNAL)
|
||||
return -EINVAL;
|
||||
glops = gfs2_glops_list[gltype];
|
||||
if (gltype == LM_TYPE_NONDISK && glnum == GFS2_TRANS_LOCK)
|
||||
glops = &gfs2_trans_glops;
|
||||
else
|
||||
glops = gfs2_glops_list[gltype];
|
||||
if (glops == NULL)
|
||||
return -EINVAL;
|
||||
if (!test_and_set_bit(SDF_DEMOTE, &sdp->sd_flags))
|
||||
@ -399,31 +402,32 @@ static ssize_t recover_status_show(struct gfs2_sbd *sdp, char *buf)
|
||||
|
||||
static ssize_t jid_show(struct gfs2_sbd *sdp, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%u\n", sdp->sd_lockstruct.ls_jid);
|
||||
return sprintf(buf, "%d\n", sdp->sd_lockstruct.ls_jid);
|
||||
}
|
||||
|
||||
static ssize_t jid_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
|
||||
{
|
||||
unsigned jid;
|
||||
int jid;
|
||||
int rv;
|
||||
|
||||
rv = sscanf(buf, "%u", &jid);
|
||||
rv = sscanf(buf, "%d", &jid);
|
||||
if (rv != 1)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&sdp->sd_jindex_spin);
|
||||
rv = -EINVAL;
|
||||
if (sdp->sd_args.ar_spectator)
|
||||
goto out;
|
||||
if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
|
||||
goto out;
|
||||
rv = -EBUSY;
|
||||
if (test_and_clear_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0)
|
||||
if (test_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0)
|
||||
goto out;
|
||||
rv = 0;
|
||||
if (sdp->sd_args.ar_spectator && jid > 0)
|
||||
rv = jid = -EINVAL;
|
||||
sdp->sd_lockstruct.ls_jid = jid;
|
||||
clear_bit(SDF_NOJOURNALID, &sdp->sd_flags);
|
||||
smp_mb__after_clear_bit();
|
||||
wake_up_bit(&sdp->sd_flags, SDF_NOJOURNALID);
|
||||
rv = 0;
|
||||
out:
|
||||
spin_unlock(&sdp->sd_jindex_spin);
|
||||
return rv ? rv : len;
|
||||
@ -617,7 +621,7 @@ static int gfs2_uevent(struct kset *kset, struct kobject *kobj,
|
||||
add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name);
|
||||
add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name);
|
||||
if (!test_bit(SDF_NOJOURNALID, &sdp->sd_flags))
|
||||
add_uevent_var(env, "JOURNALID=%u", sdp->sd_lockstruct.ls_jid);
|
||||
add_uevent_var(env, "JOURNALID=%d", sdp->sd_lockstruct.ls_jid);
|
||||
if (gfs2_uuid_valid(uuid))
|
||||
add_uevent_var(env, "UUID=%pUB", uuid);
|
||||
return 0;
|
||||
|
@ -39,7 +39,8 @@
|
||||
{(1UL << GLF_INVALIDATE_IN_PROGRESS), "i" }, \
|
||||
{(1UL << GLF_REPLY_PENDING), "r" }, \
|
||||
{(1UL << GLF_INITIAL), "I" }, \
|
||||
{(1UL << GLF_FROZEN), "F" })
|
||||
{(1UL << GLF_FROZEN), "F" }, \
|
||||
{(1UL << GLF_QUEUED), "q" })
|
||||
|
||||
#ifndef NUMPTY
|
||||
#define NUMPTY
|
||||
|
@ -20,11 +20,20 @@ struct gfs2_glock;
|
||||
#define RES_JDATA 1
|
||||
#define RES_DATA 1
|
||||
#define RES_LEAF 1
|
||||
#define RES_RG_HDR 1
|
||||
#define RES_RG_BIT 2
|
||||
#define RES_EATTR 1
|
||||
#define RES_STATFS 1
|
||||
#define RES_QUOTA 2
|
||||
|
||||
/* reserve either the number of blocks to be allocated plus the rg header
|
||||
* block, or all of the blocks in the rg, whichever is smaller */
|
||||
static inline unsigned int gfs2_rg_blocks(const struct gfs2_alloc *al)
|
||||
{
|
||||
return (al->al_requested < al->al_rgd->rd_length)?
|
||||
al->al_requested + 1 : al->al_rgd->rd_length;
|
||||
}
|
||||
|
||||
int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks,
|
||||
unsigned int revokes);
|
||||
|
||||
|
@ -734,7 +734,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
|
||||
goto out_gunlock_q;
|
||||
|
||||
error = gfs2_trans_begin(GFS2_SB(&ip->i_inode),
|
||||
blks + al->al_rgd->rd_length +
|
||||
blks + gfs2_rg_blocks(al) +
|
||||
RES_DINODE + RES_STATFS + RES_QUOTA, 0);
|
||||
if (error)
|
||||
goto out_ipres;
|
||||
|
Loading…
Reference in New Issue
Block a user