Commit f6f0a6d6 authored by Linus Torvalds's avatar Linus Torvalds

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

* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw: (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
  ...
parents 2017bd19 33027af6
config GFS2_FS config GFS2_FS
tristate "GFS2 file system support" tristate "GFS2 file system support"
depends on EXPERIMENTAL && (64BIT || LBDAF) depends on (64BIT || LBDAF)
select DLM if GFS2_FS_LOCKING_DLM select DLM if GFS2_FS_LOCKING_DLM
select CONFIGFS_FS if GFS2_FS_LOCKING_DLM select CONFIGFS_FS if GFS2_FS_LOCKING_DLM
select SYSFS if GFS2_FS_LOCKING_DLM select SYSFS if GFS2_FS_LOCKING_DLM
......
...@@ -36,8 +36,8 @@ ...@@ -36,8 +36,8 @@
#include "glops.h" #include "glops.h"
static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page, void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
unsigned int from, unsigned int to) unsigned int from, unsigned int to)
{ {
struct buffer_head *head = page_buffers(page); struct buffer_head *head = page_buffers(page);
unsigned int bsize = head->b_size; unsigned int bsize = head->b_size;
...@@ -615,7 +615,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, ...@@ -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; unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
int alloc_required; int alloc_required;
int error = 0; int error = 0;
struct gfs2_alloc *al; struct gfs2_alloc *al = NULL;
pgoff_t index = pos >> PAGE_CACHE_SHIFT; pgoff_t index = pos >> PAGE_CACHE_SHIFT;
unsigned from = pos & (PAGE_CACHE_SIZE - 1); unsigned from = pos & (PAGE_CACHE_SIZE - 1);
unsigned to = from + len; unsigned to = from + len;
...@@ -663,6 +663,8 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, ...@@ -663,6 +663,8 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
rblocks += RES_STATFS + RES_QUOTA; rblocks += RES_STATFS + RES_QUOTA;
if (&ip->i_inode == sdp->sd_rindex) if (&ip->i_inode == sdp->sd_rindex)
rblocks += 2 * RES_STATFS; rblocks += 2 * RES_STATFS;
if (alloc_required)
rblocks += gfs2_rg_blocks(al);
error = gfs2_trans_begin(sdp, rblocks, error = gfs2_trans_begin(sdp, rblocks,
PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize); PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize);
...@@ -696,13 +698,11 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, ...@@ -696,13 +698,11 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
page_cache_release(page); page_cache_release(page);
/* gfs2_trans_end(sdp);
* XXX(truncate): the call below should probably be replaced with
* a call to the gfs2-specific truncate blocks helper to actually
* release disk blocks..
*/
if (pos + len > ip->i_inode.i_size) 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: out_endtrans:
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
out_trans_fail: out_trans_fail:
...@@ -802,10 +802,8 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh, ...@@ -802,10 +802,8 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
page_cache_release(page); page_cache_release(page);
if (copied) { if (copied) {
if (inode->i_size < to) { if (inode->i_size < to)
i_size_write(inode, to); i_size_write(inode, to);
ip->i_disksize = inode->i_size;
}
gfs2_dinode_out(ip, di); gfs2_dinode_out(ip, di);
mark_inode_dirty(inode); mark_inode_dirty(inode);
} }
...@@ -876,8 +874,6 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, ...@@ -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); ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
if (ret > 0) { if (ret > 0) {
if (inode->i_size > ip->i_disksize)
ip->i_disksize = inode->i_size;
gfs2_dinode_out(ip, dibh->b_data); gfs2_dinode_out(ip, dibh->b_data);
mark_inode_dirty(inode); mark_inode_dirty(inode);
} }
......
This diff is collapsed.
...@@ -44,14 +44,16 @@ static inline void gfs2_write_calc_reserv(const struct gfs2_inode *ip, ...@@ -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); extern 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); extern int gfs2_block_map(struct inode *inode, sector_t lblock,
int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen); struct buffer_head *bh, int create);
extern int gfs2_extent_map(struct inode *inode, u64 lblock, int *new,
int gfs2_truncatei(struct gfs2_inode *ip, u64 size); u64 *dblock, unsigned *extlen);
int gfs2_truncatei_resume(struct gfs2_inode *ip); extern int gfs2_setattr_size(struct inode *inode, u64 size);
int gfs2_file_dealloc(struct gfs2_inode *ip); extern void gfs2_trim_blocks(struct inode *inode);
int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, extern int gfs2_truncatei_resume(struct gfs2_inode *ip);
unsigned int len); 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__ */ #endif /* __BMAP_DOT_H__ */
...@@ -49,7 +49,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) ...@@ -49,7 +49,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
ip = GFS2_I(inode); ip = GFS2_I(inode);
} }
if (sdp->sd_args.ar_localcaching) if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
goto valid; goto valid;
had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL); had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL);
......
...@@ -79,6 +79,9 @@ ...@@ -79,6 +79,9 @@
#define gfs2_disk_hash2offset(h) (((u64)(h)) >> 1) #define gfs2_disk_hash2offset(h) (((u64)(h)) >> 1)
#define gfs2_dir_offset2hash(p) ((u32)(((u64)(p)) << 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, typedef int (*leaf_call_t) (struct gfs2_inode *dip, u32 index, u32 len,
u64 leaf_no, void *data); u64 leaf_no, void *data);
typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent, 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, ...@@ -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); gfs2_trans_add_bh(ip->i_gl, dibh, 1);
memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size); memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
if (ip->i_disksize < offset + size) if (ip->i_inode.i_size < offset + size)
ip->i_disksize = offset + size; i_size_write(&ip->i_inode, offset + size);
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_dinode_out(ip, dibh->b_data); gfs2_dinode_out(ip, dibh->b_data);
...@@ -225,8 +228,8 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf, ...@@ -225,8 +228,8 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
if (error) if (error)
return error; return error;
if (ip->i_disksize < offset + copied) if (ip->i_inode.i_size < offset + copied)
ip->i_disksize = offset + copied; i_size_write(&ip->i_inode, offset + copied);
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1); 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, ...@@ -275,12 +278,13 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf, u64 offset,
unsigned int o; unsigned int o;
int copied = 0; int copied = 0;
int error = 0; int error = 0;
u64 disksize = i_size_read(&ip->i_inode);
if (offset >= ip->i_disksize) if (offset >= disksize)
return 0; return 0;
if (offset + size > ip->i_disksize) if (offset + size > disksize)
size = ip->i_disksize - offset; size = disksize - offset;
if (!size) if (!size)
return 0; return 0;
...@@ -727,7 +731,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode, ...@@ -727,7 +731,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
unsigned hsize = 1 << ip->i_depth; unsigned hsize = 1 << ip->i_depth;
unsigned index; unsigned index;
u64 ln; u64 ln;
if (hsize * sizeof(u64) != ip->i_disksize) { if (hsize * sizeof(u64) != i_size_read(inode)) {
gfs2_consist_inode(ip); gfs2_consist_inode(ip);
return ERR_PTR(-EIO); return ERR_PTR(-EIO);
} }
...@@ -879,7 +883,7 @@ static int dir_make_exhash(struct inode *inode) ...@@ -879,7 +883,7 @@ static int dir_make_exhash(struct inode *inode)
for (x = sdp->sd_hash_ptrs; x--; lp++) for (x = sdp->sd_hash_ptrs; x--; lp++)
*lp = cpu_to_be64(bn); *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); gfs2_add_inode_blocks(&dip->i_inode, 1);
dip->i_diskflags |= GFS2_DIF_EXHASH; dip->i_diskflags |= GFS2_DIF_EXHASH;
...@@ -1057,11 +1061,12 @@ static int dir_double_exhash(struct gfs2_inode *dip) ...@@ -1057,11 +1061,12 @@ static int dir_double_exhash(struct gfs2_inode *dip)
u64 *buf; u64 *buf;
u64 *from, *to; u64 *from, *to;
u64 block; u64 block;
u64 disksize = i_size_read(&dip->i_inode);
int x; int x;
int error = 0; int error = 0;
hsize = 1 << dip->i_depth; hsize = 1 << dip->i_depth;
if (hsize * sizeof(u64) != dip->i_disksize) { if (hsize * sizeof(u64) != disksize) {
gfs2_consist_inode(dip); gfs2_consist_inode(dip);
return -EIO; return -EIO;
} }
...@@ -1072,7 +1077,7 @@ static int dir_double_exhash(struct gfs2_inode *dip) ...@@ -1072,7 +1077,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
if (!buf) if (!buf)
return -ENOMEM; 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, error = gfs2_dir_read_data(dip, (char *)buf,
block * sdp->sd_hash_bsize, block * sdp->sd_hash_bsize,
sdp->sd_hash_bsize, 1); sdp->sd_hash_bsize, 1);
...@@ -1370,7 +1375,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, ...@@ -1370,7 +1375,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
unsigned depth = 0; unsigned depth = 0;
hsize = 1 << dip->i_depth; hsize = 1 << dip->i_depth;
if (hsize * sizeof(u64) != dip->i_disksize) { if (hsize * sizeof(u64) != i_size_read(inode)) {
gfs2_consist_inode(dip); gfs2_consist_inode(dip);
return -EIO; return -EIO;
} }
...@@ -1784,7 +1789,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data) ...@@ -1784,7 +1789,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
int error = 0; int error = 0;
hsize = 1 << dip->i_depth; 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); gfs2_consist_inode(dip);
return -EIO; return -EIO;
} }
......
...@@ -17,23 +17,24 @@ struct inode; ...@@ -17,23 +17,24 @@ struct inode;
struct gfs2_inode; struct gfs2_inode;
struct gfs2_inum; struct gfs2_inum;
struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *filename); extern struct inode *gfs2_dir_search(struct inode *dir,
int gfs2_dir_check(struct inode *dir, const struct qstr *filename, const struct qstr *filename);
const struct gfs2_inode *ip); extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
int gfs2_dir_add(struct inode *inode, const struct qstr *filename, const struct gfs2_inode *ip);
const struct gfs2_inode *ip, unsigned int type); extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename); const struct gfs2_inode *ip, unsigned int type);
int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, extern int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
filldir_t filldir); extern int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, filldir_t filldir);
const struct gfs2_inode *nip, unsigned int new_type); 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, extern int gfs2_diradd_alloc_required(struct inode *dir,
const struct qstr *filename); const struct qstr *filename);
int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block, extern int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
struct buffer_head **bhp); struct buffer_head **bhp);
static inline u32 gfs2_disk_hash(const char *data, int len) 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 ...@@ -61,4 +62,7 @@ static inline void gfs2_qstr2dirent(const struct qstr *name, u16 reclen, struct
memcpy(dent + 1, name->name, name->len); memcpy(dent + 1, name->name, name->len);
} }
extern struct qstr gfs2_qdot;
extern struct qstr gfs2_qdotdot;
#endif /* __DIR_DOT_H__ */ #endif /* __DIR_DOT_H__ */
...@@ -126,16 +126,9 @@ static int gfs2_get_name(struct dentry *parent, char *name, ...@@ -126,16 +126,9 @@ static int gfs2_get_name(struct dentry *parent, char *name,
static struct dentry *gfs2_get_parent(struct dentry *child) static struct dentry *gfs2_get_parent(struct dentry *child)
{ {
struct qstr dotdot;
struct dentry *dentry; struct dentry *dentry;
/* dentry = d_obtain_alias(gfs2_lookupi(child->d_inode, &gfs2_qdotdot, 1));
* 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));
if (!IS_ERR(dentry)) if (!IS_ERR(dentry))
dentry->d_op = &gfs2_dops; dentry->d_op = &gfs2_dops;
return dentry; return dentry;
......
...@@ -382,8 +382,10 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -382,8 +382,10 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
rblocks = RES_DINODE + ind_blocks; rblocks = RES_DINODE + ind_blocks;
if (gfs2_is_jdata(ip)) if (gfs2_is_jdata(ip))
rblocks += data_blocks ? data_blocks : 1; rblocks += data_blocks ? data_blocks : 1;
if (ind_blocks || data_blocks) if (ind_blocks || data_blocks) {
rblocks += RES_STATFS + RES_QUOTA; rblocks += RES_STATFS + RES_QUOTA;
rblocks += gfs2_rg_blocks(al);
}
ret = gfs2_trans_begin(sdp, rblocks, 0); ret = gfs2_trans_begin(sdp, rblocks, 0);
if (ret) if (ret)
goto out_trans_fail; goto out_trans_fail;
...@@ -491,7 +493,7 @@ static int gfs2_open(struct inode *inode, struct file *file) ...@@ -491,7 +493,7 @@ static int gfs2_open(struct inode *inode, struct file *file)
goto fail; goto fail;
if (!(file->f_flags & O_LARGEFILE) && if (!(file->f_flags & O_LARGEFILE) &&
ip->i_disksize > MAX_NON_LFS) { i_size_read(inode) > MAX_NON_LFS) {
error = -EOVERFLOW; error = -EOVERFLOW;
goto fail_gunlock; goto fail_gunlock;
} }
......
...@@ -441,6 +441,8 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state) ...@@ -441,6 +441,8 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state)
else else
gfs2_glock_put_nolock(gl); 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_state = new_state;
gl->gl_tchange = jiffies; gl->gl_tchange = jiffies;
...@@ -1012,6 +1014,7 @@ __acquires(&gl->gl_spin) ...@@ -1012,6 +1014,7 @@ __acquires(&gl->gl_spin)
if (unlikely((gh->gh_flags & LM_FLAG_PRIORITY) && !insert_pt)) if (unlikely((gh->gh_flags & LM_FLAG_PRIORITY) && !insert_pt))
insert_pt = &gh2->gh_list; insert_pt = &gh2->gh_list;
} }
set_bit(GLF_QUEUED, &gl->gl_flags);
if (likely(insert_pt == NULL)) { if (likely(insert_pt == NULL)) {
list_add_tail(&gh->gh_list, &gl->gl_holders); list_add_tail(&gh->gh_list, &gl->gl_holders);
if (unlikely(gh->gh_flags & LM_FLAG_PRIORITY)) if (unlikely(gh->gh_flags & LM_FLAG_PRIORITY))
...@@ -1310,10 +1313,12 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state) ...@@ -1310,10 +1313,12 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
gfs2_glock_hold(gl); gfs2_glock_hold(gl);
holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time; holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time;
if (time_before(now, holdtime)) if (test_bit(GLF_QUEUED, &gl->gl_flags)) {
delay = holdtime - now; if (time_before(now, holdtime))
if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags)) delay = holdtime - now;
delay = gl->gl_ops->go_min_hold_time; if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
delay = gl->gl_ops->go_min_hold_time;
}
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
handle_callback(gl, state, delay); handle_callback(gl, state, delay);
...@@ -1512,7 +1517,7 @@ static void clear_glock(struct gfs2_glock *gl) ...@@ -1512,7 +1517,7 @@ static void clear_glock(struct gfs2_glock *gl)
spin_unlock(&lru_lock); spin_unlock(&lru_lock);
spin_lock(&gl->gl_spin); 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); handle_callback(gl, LM_ST_UNLOCKED, 0);
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
gfs2_glock_hold(gl); gfs2_glock_hold(gl);
...@@ -1660,6 +1665,8 @@ static const char *gflags2str(char *buf, const unsigned long *gflags) ...@@ -1660,6 +1665,8 @@ static const char *gflags2str(char *buf, const unsigned long *gflags)
*p++ = 'I'; *p++ = 'I';
if (test_bit(GLF_FROZEN, gflags)) if (test_bit(GLF_FROZEN, gflags))
*p++ = 'F'; *p++ = 'F';
if (test_bit(GLF_QUEUED, gflags))
*p++ = 'q';
*p = 0; *p = 0;
return buf; return buf;
} }
...@@ -1776,10 +1783,12 @@ int __init gfs2_glock_init(void) ...@@ -1776,10 +1783,12 @@ int __init gfs2_glock_init(void)
} }
#endif #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)) if (IS_ERR(glock_workqueue))
return PTR_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)) { if (IS_ERR(gfs2_delete_workqueue)) {
destroy_workqueue(glock_workqueue); destroy_workqueue(glock_workqueue);
return PTR_ERR(gfs2_delete_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); ...@@ -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, ...); 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 * @gl: the glock
* @state: the state we're requesting * @state: the state we're requesting
* @flags: the modifier flags * @flags: the modifier flags
......
...@@ -262,13 +262,12 @@ static int inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl) ...@@ -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; const struct gfs2_inode *ip = gl->gl_object;
if (ip == NULL) if (ip == NULL)
return 0; 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_formal_ino,
(unsigned long long)ip->i_no_addr, (unsigned long long)ip->i_no_addr,
IF2DT(ip->i_inode.i_mode), ip->i_flags, IF2DT(ip->i_inode.i_mode), ip->i_flags,
(unsigned int)ip->i_diskflags, (unsigned int)ip->i_diskflags,
(unsigned long long)ip->i_inode.i_size, (unsigned long long)i_size_read(&ip->i_inode));
(unsigned long long)ip->i_disksize);
return 0; return 0;
} }
...@@ -453,7 +452,6 @@ const struct gfs2_glock_operations *gfs2_glops_list[] = { ...@@ -453,7 +452,6 @@ const struct gfs2_glock_operations *gfs2_glops_list[] = {
[LM_TYPE_META] = &gfs2_meta_glops, [LM_TYPE_META] = &gfs2_meta_glops,
[LM_TYPE_INODE] = &gfs2_inode_glops, [LM_TYPE_INODE] = &gfs2_inode_glops,
[LM_TYPE_RGRP] = &gfs2_rgrp_glops, [LM_TYPE_RGRP] = &gfs2_rgrp_glops,
[LM_TYPE_NONDISK] = &gfs2_trans_glops,
[LM_TYPE_IOPEN] = &gfs2_iopen_glops, [LM_TYPE_IOPEN] = &gfs2_iopen_glops,
[LM_TYPE_FLOCK] = &gfs2_flock_glops, [LM_TYPE_FLOCK] = &gfs2_flock_glops,
[LM_TYPE_NONDISK] = &gfs2_nondisk_glops, [LM_TYPE_NONDISK] = &gfs2_nondisk_glops,
......
...@@ -196,6 +196,7 @@ enum { ...@@ -196,6 +196,7 @@ enum {
GLF_REPLY_PENDING = 9, GLF_REPLY_PENDING = 9,
GLF_INITIAL = 10, GLF_INITIAL = 10,
GLF_FROZEN = 11, GLF_FROZEN = 11,
GLF_QUEUED = 12,
}; };
struct gfs2_glock { struct gfs2_glock {
...@@ -267,7 +268,6 @@ struct gfs2_inode { ...@@ -267,7 +268,6 @@ struct gfs2_inode {
u64 i_no_formal_ino; u64 i_no_formal_ino;
u64 i_generation; u64 i_generation;
u64 i_eattr; u64 i_eattr;
loff_t i_disksize;
unsigned long i_flags; /* GIF_... */ unsigned long i_flags; /* GIF_... */
struct gfs2_glock *i_gl; /* Move into i_gh? */ struct gfs2_glock *i_gl; /* Move into i_gh? */
struct gfs2_holder i_iopen_gh; struct gfs2_holder i_iopen_gh;
...@@ -416,11 +416,8 @@ struct gfs2_args { ...@@ -416,11 +416,8 @@ struct gfs2_args {
char ar_locktable[GFS2_LOCKNAME_LEN]; /* Name of the Lock Table */ char ar_locktable[GFS2_LOCKNAME_LEN]; /* Name of the Lock Table */
char ar_hostdata[GFS2_LOCKNAME_LEN]; /* Host specific data */ char ar_hostdata[GFS2_LOCKNAME_LEN]; /* Host specific data */
unsigned int ar_spectator:1; /* Don't get a journal */ 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_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_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_posix_acl:1; /* Enable posix acls */
unsigned int ar_quota:2; /* off/account/on */ unsigned int ar_quota:2; /* off/account/on */
unsigned int ar_suiddir:1; /* suiddir support */ unsigned int ar_suiddir:1; /* suiddir support */
...@@ -497,7 +494,7 @@ struct gfs2_sb_host { ...@@ -497,7 +494,7 @@ struct gfs2_sb_host {
*/ */
struct lm_lockstruct { struct lm_lockstruct {
unsigned int ls_jid; int ls_jid;
unsigned int ls_first; unsigned int ls_first;
unsigned int ls_first_done; unsigned int ls_first_done;
unsigned int ls_nodir; unsigned int ls_nodir;
...@@ -572,6 +569,7 @@ struct gfs2_sbd { ...@@ -572,6 +569,7 @@ struct gfs2_sbd {
struct list_head sd_rindex_mru_list; struct list_head sd_rindex_mru_list;
struct gfs2_rgrpd *sd_rindex_forward; struct gfs2_rgrpd *sd_rindex_forward;
unsigned int sd_rgrps; unsigned int sd_rgrps;
unsigned int sd_max_rg_data;
/* Journal index stuff */ /* Journal index stuff */
......
...@@ -359,8 +359,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) ...@@ -359,8 +359,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
* to do that. * to do that.
*/ */
ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink); 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, be64_to_cpu(str->di_size));
i_size_write(&ip->i_inode, ip->i_disksize);
gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks)); gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
atime.tv_sec = be64_to_cpu(str->di_atime); atime.tv_sec = be64_to_cpu(str->di_atime);
atime.tv_nsec = be32_to_cpu(str->di_atime_nsec); 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) ...@@ -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_uid = cpu_to_be32(ip->i_inode.i_uid);
str->di_gid = cpu_to_be32(ip->i_inode.i_gid); str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink); str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
str->di_size = cpu_to_be64(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_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec); str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
...@@ -1085,8 +1084,8 @@ void gfs2_dinode_print(const struct gfs2_inode *ip) ...@@ -1085,8 +1084,8 @@ void gfs2_dinode_print(const struct gfs2_inode *ip)
(unsigned long long)ip->i_no_formal_ino); (unsigned long long)ip->i_no_formal_ino);
printk(KERN_INFO " no_addr = %llu\n", printk(KERN_INFO " no_addr = %llu\n",
(unsigned long long)ip->i_no_addr); (unsigned long long)ip->i_no_addr);
printk(KERN_INFO " i_disksize = %llu\n", printk(KERN_INFO " i_size = %llu\n",
(unsigned long long)ip->i_disksize); (unsigned long long)i_size_read(&ip->i_inode));
printk(KERN_INFO " blocks = %llu\n", printk(KERN_INFO " blocks = %llu\n",
(unsigned long long)gfs2_get_inode_blocks(&ip->i_inode)); (unsigned long long)gfs2_get_inode_blocks(&ip->i_inode));
printk(KERN_INFO " i_goal = %llu\n", printk(KERN_INFO " i_goal = %llu\n",
......
...@@ -19,6 +19,8 @@ extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask); ...@@ -19,6 +19,8 @@ extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask);
extern int gfs2_internal_read(struct gfs2_inode *ip, extern int gfs2_internal_read(struct gfs2_inode *ip,
struct file_ra_state *ra_state, struct file_ra_state *ra_state,
char *buf, loff_t *pos, unsigned size); 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); extern void gfs2_set_aops(struct inode *inode);
static inline int gfs2_is_stuffed(const struct gfs2_inode *ip) 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, ...@@ -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); 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 void gfs2_set_iop(struct inode *inode);
extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type,
......
...@@ -42,9 +42,9 @@ static void gdlm_ast(void *arg) ...@@ -42,9 +42,9 @@ static void gdlm_ast(void *arg)
ret |= LM_OUT_CANCELED; ret |= LM_OUT_CANCELED;
goto out; goto out;
case -EAGAIN: /* Try lock fails */ case -EAGAIN: /* Try lock fails */
case -EDEADLK: /* Deadlock detected */
goto out; goto out;
case -EINVAL: /* Invalid */ case -ETIMEDOUT: /* Canceled due to timeout */
case -ENOMEM: /* Out of memory */
ret |= LM_OUT_ERROR; ret |= LM_OUT_ERROR;
goto out; goto out;
case 0: /* Success */ case 0: /* Success */
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "glock.h" #include "glock.h"
#include "quota.h" #include "quota.h"
#include "recovery.h" #include "recovery.h"
#include "dir.h"
static struct shrinker qd_shrinker = { static struct shrinker qd_shrinker = {
.shrink = gfs2_shrink_qd_memory, .shrink = gfs2_shrink_qd_memory,
...@@ -78,6 +79,9 @@ static int __init init_gfs2_fs(void) ...@@ -78,6 +79,9 @@ static int __init init_gfs2_fs(void)
{ {
int error; int error;
gfs2_str2qstr(&gfs2_qdot, ".");
gfs2_str2qstr(&gfs2_qdotdot, "..");
error = gfs2_sys_init(); error = gfs2_sys_init();
if (error) if (error)
return error; return error;
...@@ -140,7 +144,7 @@ static int __init init_gfs2_fs(void) ...@@ -140,7 +144,7 @@ static int __init init_gfs2_fs(void)
error = -ENOMEM; error = -ENOMEM;
gfs_recovery_wq = alloc_workqueue("gfs_recovery", gfs_recovery_wq = alloc_workqueue("gfs_recovery",
WQ_NON_REENTRANT | WQ_RESCUER, 0); WQ_RESCUER | WQ_FREEZEABLE, 0);
if (!gfs_recovery_wq) if (!gfs_recovery_wq)
goto fail_wq; goto fail_wq;
......
...@@ -38,14 +38,6 @@ ...@@ -38,14 +38,6 @@
#define DO 0 #define DO 0
#define UNDO 1 #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 * gfs2_tune_init - Fill a gfs2_tune structure with default values
* @gt: tune * @gt: tune
...@@ -135,8 +127,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) ...@@ -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) 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 || if (sb->sb_magic != GFS2_MAGIC ||
sb->sb_type != GFS2_METATYPE_SB) { sb->sb_type != GFS2_METATYPE_SB) {
if (!silent) if (!silent)
...@@ -150,55 +140,9 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int sile ...@@ -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) sb->sb_multihost_format == GFS2_FORMAT_MULTI)
return 0; return 0;
if (sb->sb_fs_format != GFS2_FORMAT_FS) { fs_warn(sdp, "Unknown on-disk format, unable to mount\n");
for (x = 0; gfs2_old_fs_formats[x]; x++)
if (gfs2_old_fs_formats[x] == sb->sb_fs_format)
break;
if (!gfs2_old_fs_formats[x]) { return -EINVAL;
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;
} }
static void end_bio_io_page(struct bio *bio, int error) static void end_bio_io_page(struct bio *bio, int error)
...@@ -586,7 +530,7 @@ static int map_journal_extents(struct gfs2_sbd *sdp) ...@@ -586,7 +530,7 @@ static int map_journal_extents(struct gfs2_sbd *sdp)
prev_db = 0; 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_state = 0;
bh.b_blocknr = 0; bh.b_blocknr = 0;
bh.b_size = 1 << ip->i_inode.i_blkbits; bh.b_size = 1 << ip->i_inode.i_blkbits;
...@@ -1022,7 +966,6 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent) ...@@ -1022,7 +966,6 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
if (!strcmp("lock_nolock", proto)) { if (!strcmp("lock_nolock", proto)) {
lm = &nolock_ops; lm = &nolock_ops;
sdp->sd_args.ar_localflocks = 1; sdp->sd_args.ar_localflocks = 1;
sdp->sd_args.ar_localcaching = 1;
#ifdef CONFIG_GFS2_FS_LOCKING_DLM #ifdef CONFIG_GFS2_FS_LOCKING_DLM
} else if (!strcmp("lock_dlm", proto)) { } else if (!strcmp("lock_dlm", proto)) {
lm = &gfs2_dlm_ops; lm = &gfs2_dlm_ops;
...@@ -1113,8 +1056,6 @@ static int gfs2_journalid_wait(void *word) ...@@ -1113,8 +1056,6 @@ static int gfs2_journalid_wait(void *word)
static int wait_on_journal(struct gfs2_sbd *sdp) 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) if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
return 0; return 0;
...@@ -1217,6 +1158,20 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent ...@@ -1217,6 +1158,20 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent
if (error) if (error)
goto fail_sb; 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); error = init_inodes(sdp, DO);
if (error) if (error)
goto fail_sb; goto fail_sb;
......
This diff is collapsed.
...@@ -735,10 +735,8 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, ...@@ -735,10 +735,8 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
goto out; goto out;
size = loc + sizeof(struct gfs2_quota); size = loc + sizeof(struct gfs2_quota);
if (size > inode->i_size) { if (size > inode->i_size)
ip->i_disksize = size;
i_size_write(inode, size); i_size_write(inode, size);
}
inode->i_mtime = inode->i_atime = CURRENT_TIME; inode->i_mtime = inode->i_atime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data); gfs2_dinode_out(ip, dibh->b_data);
...@@ -817,7 +815,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) ...@@ -817,7 +815,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
goto out_alloc; goto out_alloc;
if (nalloc) 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); error = gfs2_trans_begin(sdp, blocks, 0);
if (error) if (error)
...@@ -1190,18 +1188,17 @@ static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void * ...@@ -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) int gfs2_quota_init(struct gfs2_sbd *sdp)
{ {
struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode); 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 x, slot = 0;
unsigned int found = 0; unsigned int found = 0;
u64 dblock; u64 dblock;
u32 extlen = 0; u32 extlen = 0;
int error; int error;
if (!ip->i_disksize || ip->i_disksize > (64 << 20) || if (gfs2_check_internal_file_size(sdp->sd_qc_inode, 1, 64 << 20))
ip->i_disksize & (sdp->sd_sb.sb_bsize - 1)) {
gfs2_consist_inode(ip);
return -EIO; return -EIO;
}
sdp->sd_quota_slots = blocks * sdp->sd_qc_per_block; sdp->sd_quota_slots = blocks * sdp->sd_qc_per_block;
sdp->sd_quota_chunks = DIV_ROUND_UP(sdp->sd_quota_slots, 8 * PAGE_SIZE); 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, ...@@ -1589,6 +1586,7 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
error = gfs2_inplace_reserve(ip); error = gfs2_inplace_reserve(ip);
if (error) if (error)
goto out_alloc; goto out_alloc;
blocks += gfs2_rg_blocks(al);
} }
error = gfs2_trans_begin(sdp, blocks + RES_DINODE + 1, 0); error = gfs2_trans_begin(sdp, blocks + RES_DINODE + 1, 0);
......
...@@ -455,11 +455,13 @@ void gfs2_recover_func(struct work_struct *work) ...@@ -455,11 +455,13 @@ void gfs2_recover_func(struct work_struct *work)
int ro = 0; int ro = 0;
unsigned int pass; unsigned int pass;
int error; 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", fs_info(sdp, "jid=%u: Trying to acquire journal lock...\n",
jd->jd_jid); jd->jd_jid);
jlocked = 1;
/* Acquire the journal lock so we can do recovery */ /* Acquire the journal lock so we can do recovery */
error = gfs2_glock_nq_num(sdp, jd->jd_jid, &gfs2_journal_glops, error = gfs2_glock_nq_num(sdp, jd->jd_jid, &gfs2_journal_glops,
...@@ -554,13 +556,12 @@ void gfs2_recover_func(struct work_struct *work) ...@@ -554,13 +556,12 @@ void gfs2_recover_func(struct work_struct *work)
jd->jd_jid, t); 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); 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); gfs2_glock_dq_uninit(&j_gh);
}
fs_info(sdp, "jid=%u: Done\n", jd->jd_jid); fs_info(sdp, "jid=%u: Done\n", jd->jd_jid);
goto done; goto done;
...@@ -568,7 +569,7 @@ void gfs2_recover_func(struct work_struct *work) ...@@ -568,7 +569,7 @@ void gfs2_recover_func(struct work_struct *work)
fail_gunlock_tr: fail_gunlock_tr:
gfs2_glock_dq_uninit(&t_gh); gfs2_glock_dq_uninit(&t_gh);
fail_gunlock_ji: fail_gunlock_ji:
if (jd->jd_jid != sdp->sd_lockstruct.ls_jid) { if (jlocked) {
gfs2_glock_dq_uninit(&ji_gh); gfs2_glock_dq_uninit(&ji_gh);
fail_gunlock_j: fail_gunlock_j:
gfs2_glock_dq_uninit(&j_gh); gfs2_glock_dq_uninit(&j_gh);
......
...@@ -500,7 +500,7 @@ u64 gfs2_ri_total(struct gfs2_sbd *sdp) ...@@ -500,7 +500,7 @@ u64 gfs2_ri_total(struct gfs2_sbd *sdp)
for (rgrps = 0;; rgrps++) { for (rgrps = 0;; rgrps++) {
loff_t pos = rgrps * sizeof(struct gfs2_rindex); 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; break;
error = gfs2_internal_read(ip, &ra_state, buf, &pos, error = gfs2_internal_read(ip, &ra_state, buf, &pos,
sizeof(struct gfs2_rindex)); sizeof(struct gfs2_rindex));
...@@ -588,7 +588,9 @@ static int gfs2_ri_update(struct gfs2_inode *ip) ...@@ -588,7 +588,9 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct inode *inode = &ip->i_inode; struct inode *inode = &ip->i_inode;
struct file_ra_state ra_state; 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; int error;
do_div(rgrp_count, sizeof(struct gfs2_rindex)); do_div(rgrp_count, sizeof(struct gfs2_rindex));
...@@ -603,6 +605,10 @@ static int gfs2_ri_update(struct gfs2_inode *ip) ...@@ -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; sdp->sd_rindex_uptodate = 1;
return 0; return 0;
} }
...@@ -622,13 +628,15 @@ static int gfs2_ri_update_special(struct gfs2_inode *ip) ...@@ -622,13 +628,15 @@ static int gfs2_ri_update_special(struct gfs2_inode *ip)
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct inode *inode = &ip->i_inode; struct inode *inode = &ip->i_inode;
struct file_ra_state ra_state; struct file_ra_state ra_state;
struct gfs2_rgrpd *rgd;
unsigned int max_data = 0;
int error; int error;
file_ra_state_init(&ra_state, inode->i_mapping); file_ra_state_init(&ra_state, inode->i_mapping);
for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) { for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
/* Ignore partials */ /* Ignore partials */
if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) > if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) >
ip->i_disksize) i_size_read(inode))
break; break;
error = read_rindex_entry(ip, &ra_state); error = read_rindex_entry(ip, &ra_state);
if (error) { if (error) {
...@@ -636,6 +644,10 @@ static int gfs2_ri_update_special(struct gfs2_inode *ip) ...@@ -636,6 +644,10 @@ static int gfs2_ri_update_special(struct gfs2_inode *ip)
return error; 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; sdp->sd_rindex_uptodate = 1;
return 0; return 0;
...@@ -1188,7 +1200,8 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *unlinked, ...@@ -1188,7 +1200,8 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *unlinked,
* Returns: errno * 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_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = ip->i_alloc; 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) ...@@ -1199,12 +1212,15 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
return -EINVAL; return -EINVAL;
try_again: try_again:
/* We need to hold the rindex unless the inode we're using is if (hold_rindex) {
the rindex itself, in which case it's already held. */ /* We need to hold the rindex unless the inode we're using is
if (ip != GFS2_I(sdp->sd_rindex)) the rindex itself, in which case it's already held. */
error = gfs2_rindex_hold(sdp, &al->al_ri_gh); if (ip != GFS2_I(sdp->sd_rindex))
else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */ error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
error = gfs2_ri_update_special(ip); else if (!sdp->sd_rgrps) /* We may not have the rindex read
in, so: */
error = gfs2_ri_update_special(ip);
}
if (error) if (error)
return error; return error;
...@@ -1215,7 +1231,7 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) ...@@ -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. */ try to free it, and try the allocation again. */
error = get_local_rgrp(ip, &unlinked, &last_unlinked); error = get_local_rgrp(ip, &unlinked, &last_unlinked);
if (error) { 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); gfs2_glock_dq_uninit(&al->al_ri_gh);
if (error != -EAGAIN) if (error != -EAGAIN)
return error; return error;
...@@ -1257,7 +1273,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip) ...@@ -1257,7 +1273,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip)
al->al_rgd = NULL; al->al_rgd = NULL;
if (al->al_rgd_gh.gh_gl) if (al->al_rgd_gh.gh_gl)
gfs2_glock_dq_uninit(&al->al_rgd_gh); 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); 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) ...@@ -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 gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct buffer_head *dibh; struct buffer_head *dibh;
struct gfs2_alloc *al = ip->i_alloc; struct gfs2_alloc *al = ip->i_alloc;
struct gfs2_rgrpd *rgd = al->al_rgd; struct gfs2_rgrpd *rgd;
u32 goal, blk; u32 goal, blk;
u64 block; u64 block;
int error; 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)) if (rgrp_contains_block(rgd, ip->i_goal))
goal = ip->i_goal - rgd->rd_data0; goal = ip->i_goal - rgd->rd_data0;
else else
......
...@@ -39,10 +39,12 @@ static inline void gfs2_alloc_put(struct gfs2_inode *ip) ...@@ -39,10 +39,12 @@ static inline void gfs2_alloc_put(struct gfs2_inode *ip)
ip->i_alloc = NULL; ip->i_alloc = NULL;
} }
extern int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, extern int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex,
unsigned int line); char *file, unsigned int line);
#define gfs2_inplace_reserve(ip) \ #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); extern void gfs2_inplace_release(struct gfs2_inode *ip);
......
...@@ -85,6 +85,7 @@ static const match_table_t tokens = { ...@@ -85,6 +85,7 @@ static const match_table_t tokens = {
{Opt_locktable, "locktable=%s"}, {Opt_locktable, "locktable=%s"},
{Opt_hostdata, "hostdata=%s"}, {Opt_hostdata, "hostdata=%s"},
{Opt_spectator, "spectator"}, {Opt_spectator, "spectator"},
{Opt_spectator, "norecovery"},
{Opt_ignore_local_fs, "ignore_local_fs"}, {Opt_ignore_local_fs, "ignore_local_fs"},
{Opt_localflocks, "localflocks"}, {Opt_localflocks, "localflocks"},
{Opt_localcaching, "localcaching"}, {Opt_localcaching, "localcaching"},
...@@ -159,13 +160,13 @@ int gfs2_mount_args(struct gfs2_args *args, char *options) ...@@ -159,13 +160,13 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
args->ar_spectator = 1; args->ar_spectator = 1;
break; break;
case Opt_ignore_local_fs: case Opt_ignore_local_fs:
args->ar_ignore_local_fs = 1; /* Retained for backwards compat only */
break; break;
case Opt_localflocks: case Opt_localflocks:
args->ar_localflocks = 1; args->ar_localflocks = 1;
break; break;
case Opt_localcaching: case Opt_localcaching:
args->ar_localcaching = 1; /* Retained for backwards compat only */
break; break;
case Opt_debug: case Opt_debug:
if (args->ar_errors == GFS2_ERRORS_PANIC) { if (args->ar_errors == GFS2_ERRORS_PANIC) {
...@@ -179,7 +180,7 @@ int gfs2_mount_args(struct gfs2_args *args, char *options) ...@@ -179,7 +180,7 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
args->ar_debug = 0; args->ar_debug = 0;
break; break;
case Opt_upgrade: case Opt_upgrade:
args->ar_upgrade = 1; /* Retained for backwards compat only */
break; break;
case Opt_acl: case Opt_acl:
args->ar_posix_acl = 1; args->ar_posix_acl = 1;
...@@ -342,15 +343,14 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd) ...@@ -342,15 +343,14 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd)
{ {
struct gfs2_inode *ip = GFS2_I(jd->jd_inode); struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
struct gfs2_sbd *sdp = GFS2_SB(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) || if (gfs2_check_internal_file_size(jd->jd_inode, 8 << 20, 1 << 30))
(ip->i_disksize & (sdp->sd_sb.sb_bsize - 1))) {
gfs2_consist_inode(ip);
return -EIO; 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); gfs2_consist_inode(ip);
return -EIO; return -EIO;
} }
...@@ -1129,9 +1129,7 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) ...@@ -1129,9 +1129,7 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
/* Some flags must not be changed */ /* Some flags must not be changed */
if (args_neq(&args, &sdp->sd_args, spectator) || 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, localflocks) ||
args_neq(&args, &sdp->sd_args, localcaching) ||
args_neq(&args, &sdp->sd_args, meta)) args_neq(&args, &sdp->sd_args, meta))
return -EINVAL; return -EINVAL;
...@@ -1234,16 +1232,10 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) ...@@ -1234,16 +1232,10 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
seq_printf(s, ",hostdata=%s", args->ar_hostdata); seq_printf(s, ",hostdata=%s", args->ar_hostdata);
if (args->ar_spectator) if (args->ar_spectator)
seq_printf(s, ",spectator"); seq_printf(s, ",spectator");
if (args->ar_ignore_local_fs)
seq_printf(s, ",ignore_local_fs");
if (args->ar_localflocks) if (args->ar_localflocks)
seq_printf(s, ",localflocks"); seq_printf(s, ",localflocks");
if (args->ar_localcaching)
seq_printf(s, ",localcaching");
if (args->ar_debug) if (args->ar_debug)
seq_printf(s, ",debug"); seq_printf(s, ",debug");
if (args->ar_upgrade)
seq_printf(s, ",upgrade");
if (args->ar_posix_acl) if (args->ar_posix_acl)
seq_printf(s, ",acl"); seq_printf(s, ",acl");
if (args->ar_quota != GFS2_QUOTA_DEFAULT) { 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 ...@@ -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) if (gltype > LM_TYPE_JOURNAL)
return -EINVAL; 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) if (glops == NULL)
return -EINVAL; return -EINVAL;
if (!test_and_set_bit(SDF_DEMOTE, &sdp->sd_flags)) 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) ...@@ -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) 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) static ssize_t jid_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
{ {
unsigned jid; int jid;
int rv; int rv;
rv = sscanf(buf, "%u", &jid); rv = sscanf(buf, "%d", &jid);
if (rv != 1) if (rv != 1)
return -EINVAL; return -EINVAL;
spin_lock(&sdp->sd_jindex_spin); spin_lock(&sdp->sd_jindex_spin);
rv = -EINVAL; rv = -EINVAL;
if (sdp->sd_args.ar_spectator)
goto out;
if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
goto out; goto out;
rv = -EBUSY; rv = -EBUSY;
if (test_and_clear_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0) if (test_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0)
goto out; goto out;
rv = 0;
if (sdp->sd_args.ar_spectator && jid > 0)
rv = jid = -EINVAL;
sdp->sd_lockstruct.ls_jid = jid; sdp->sd_lockstruct.ls_jid = jid;
clear_bit(SDF_NOJOURNALID, &sdp->sd_flags);
smp_mb__after_clear_bit(); smp_mb__after_clear_bit();
wake_up_bit(&sdp->sd_flags, SDF_NOJOURNALID); wake_up_bit(&sdp->sd_flags, SDF_NOJOURNALID);
rv = 0;
out: out:
spin_unlock(&sdp->sd_jindex_spin); spin_unlock(&sdp->sd_jindex_spin);
return rv ? rv : len; return rv ? rv : len;
...@@ -617,7 +621,7 @@ static int gfs2_uevent(struct kset *kset, struct kobject *kobj, ...@@ -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, "LOCKTABLE=%s", sdp->sd_table_name);
add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name); add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name);
if (!test_bit(SDF_NOJOURNALID, &sdp->sd_flags)) 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)) if (gfs2_uuid_valid(uuid))
add_uevent_var(env, "UUID=%pUB", uuid); add_uevent_var(env, "UUID=%pUB", uuid);
return 0; return 0;
......
...@@ -39,7 +39,8 @@ ...@@ -39,7 +39,8 @@
{(1UL << GLF_INVALIDATE_IN_PROGRESS), "i" }, \ {(1UL << GLF_INVALIDATE_IN_PROGRESS), "i" }, \
{(1UL << GLF_REPLY_PENDING), "r" }, \ {(1UL << GLF_REPLY_PENDING), "r" }, \
{(1UL << GLF_INITIAL), "I" }, \ {(1UL << GLF_INITIAL), "I" }, \
{(1UL << GLF_FROZEN), "F" }) {(1UL << GLF_FROZEN), "F" }, \
{(1UL << GLF_QUEUED), "q" })
#ifndef NUMPTY #ifndef NUMPTY
#define NUMPTY #define NUMPTY
......
...@@ -20,11 +20,20 @@ struct gfs2_glock; ...@@ -20,11 +20,20 @@ struct gfs2_glock;
#define RES_JDATA 1 #define RES_JDATA 1
#define RES_DATA 1 #define RES_DATA 1
#define RES_LEAF 1 #define RES_LEAF 1
#define RES_RG_HDR 1
#define RES_RG_BIT 2 #define RES_RG_BIT 2
#define RES_EATTR 1 #define RES_EATTR 1
#define RES_STATFS 1 #define RES_STATFS 1
#define RES_QUOTA 2 #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, int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks,
unsigned int revokes); unsigned int revokes);
......
...@@ -734,7 +734,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er, ...@@ -734,7 +734,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
goto out_gunlock_q; goto out_gunlock_q;
error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), 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); RES_DINODE + RES_STATFS + RES_QUOTA, 0);
if (error) if (error)
goto out_ipres; goto out_ipres;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment