Commit 34917f97 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw

Pull GFS2 updates from Steven Whitehouse:
 "One of the main highlights this time, is not the patches themselves
  but instead the widening contributor base.  It is good to see that
  interest is increasing in GFS2, and I'd like to thank all the
  contributors to this patch set.

  In addition to the usual set of bug fixes and clean ups, there are
  patches to improve inode creation performance when xattrs are required
  and some improvements to the transaction code which is intended to
  help improve scalability after further changes in due course.

  Journal extent mapping is also updated to make it more efficient and
  again, this is a foundation for future work in this area.

  The maximum number of ACLs has been increased to 300 (for a 4k block
  size) which means that even with a few additional xattrs from selinux,
  everything should fit within a single fs block.

  There is also a patch to bring GFS2's own copy of the writepages code
  up to the same level as the core VFS.  Eventually we may be able to
  merge some of this code, since it is fairly similar.

  The other major change this time, is bringing consistency to the
  printing of messages via fs_<level>, pr_<level> macros"

* tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw: (29 commits)
  GFS2: Fix address space from page function
  GFS2: Fix uninitialized VFS inode in gfs2_create_inode
  GFS2: Fix return value in slot_get()
  GFS2: inline function gfs2_set_mode
  GFS2: Remove extraneous function gfs2_security_init
  GFS2: Increase the max number of ACLs
  GFS2: Re-add a call to log_flush_wait when flushing the journal
  GFS2: Ensure workqueue is scheduled after noexp request
  GFS2: check NULL return value in gfs2_ok_to_move
  GFS2: Convert gfs2_lm_withdraw to use fs_err
  GFS2: Use fs_<level> more often
  GFS2: Use pr_<level> more consistently
  GFS2: Move recovery variables to journal structure in memory
  GFS2: global conversion to pr_foo()
  GFS2: return -E2BIG if hit the maximum limits of ACLs
  GFS2: Clean up journal extent mapping
  GFS2: replace kmalloc - __vmalloc / memset 0
  GFS2: Remove extra "if" in gfs2_log_flush()
  fs: NULL dereference in posix_acl_to_xattr()
  GFS2: Move log buffer accounting to transaction
  ...
parents f7789dc0 1b2ad412
...@@ -89,6 +89,8 @@ static inline struct inode *wb_inode(struct list_head *head) ...@@ -89,6 +89,8 @@ static inline struct inode *wb_inode(struct list_head *head)
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/writeback.h> #include <trace/events/writeback.h>
EXPORT_TRACEPOINT_SYMBOL_GPL(wbc_writepage);
static void bdi_wakeup_thread(struct backing_dev_info *bdi) static void bdi_wakeup_thread(struct backing_dev_info *bdi)
{ {
spin_lock_bh(&bdi->wb_lock); spin_lock_bh(&bdi->wb_lock);
......
...@@ -64,18 +64,6 @@ struct posix_acl *gfs2_get_acl(struct inode *inode, int type) ...@@ -64,18 +64,6 @@ struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
return acl; return acl;
} }
static int gfs2_set_mode(struct inode *inode, umode_t mode)
{
int error = 0;
if (mode != inode->i_mode) {
inode->i_mode = mode;
mark_inode_dirty(inode);
}
return error;
}
int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{ {
int error; int error;
...@@ -85,8 +73,8 @@ int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) ...@@ -85,8 +73,8 @@ int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
BUG_ON(name == NULL); BUG_ON(name == NULL);
if (acl->a_count > GFS2_ACL_MAX_ENTRIES) if (acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode)))
return -EINVAL; return -E2BIG;
if (type == ACL_TYPE_ACCESS) { if (type == ACL_TYPE_ACCESS) {
umode_t mode = inode->i_mode; umode_t mode = inode->i_mode;
...@@ -98,9 +86,10 @@ int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) ...@@ -98,9 +86,10 @@ int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
if (error == 0) if (error == 0)
acl = NULL; acl = NULL;
error = gfs2_set_mode(inode, mode); if (mode != inode->i_mode) {
if (error) inode->i_mode = mode;
return error; mark_inode_dirty(inode);
}
} }
if (acl) { if (acl) {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#define GFS2_POSIX_ACL_ACCESS "posix_acl_access" #define GFS2_POSIX_ACL_ACCESS "posix_acl_access"
#define GFS2_POSIX_ACL_DEFAULT "posix_acl_default" #define GFS2_POSIX_ACL_DEFAULT "posix_acl_default"
#define GFS2_ACL_MAX_ENTRIES 25 #define GFS2_ACL_MAX_ENTRIES(sdp) ((300 << (sdp)->sd_sb.sb_bsize_shift) >> 12)
extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type); extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type);
extern int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type); extern int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type);
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/gfs2_ondisk.h> #include <linux/gfs2_ondisk.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/aio.h> #include <linux/aio.h>
#include <trace/events/writeback.h>
#include "gfs2.h" #include "gfs2.h"
#include "incore.h" #include "incore.h"
...@@ -230,13 +231,11 @@ static int gfs2_writepages(struct address_space *mapping, ...@@ -230,13 +231,11 @@ static int gfs2_writepages(struct address_space *mapping,
static int gfs2_write_jdata_pagevec(struct address_space *mapping, static int gfs2_write_jdata_pagevec(struct address_space *mapping,
struct writeback_control *wbc, struct writeback_control *wbc,
struct pagevec *pvec, struct pagevec *pvec,
int nr_pages, pgoff_t end) int nr_pages, pgoff_t end,
pgoff_t *done_index)
{ {
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_sbd *sdp = GFS2_SB(inode);
loff_t i_size = i_size_read(inode);
pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
unsigned offset = i_size & (PAGE_CACHE_SIZE-1);
unsigned nrblocks = nr_pages * (PAGE_CACHE_SIZE/inode->i_sb->s_blocksize); unsigned nrblocks = nr_pages * (PAGE_CACHE_SIZE/inode->i_sb->s_blocksize);
int i; int i;
int ret; int ret;
...@@ -248,40 +247,83 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping, ...@@ -248,40 +247,83 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping,
for(i = 0; i < nr_pages; i++) { for(i = 0; i < nr_pages; i++) {
struct page *page = pvec->pages[i]; struct page *page = pvec->pages[i];
/*
* At this point, the page may be truncated or
* invalidated (changing page->mapping to NULL), or
* even swizzled back from swapper_space to tmpfs file
* mapping. However, page->index will not change
* because we have a reference on the page.
*/
if (page->index > end) {
/*
* can't be range_cyclic (1st pass) because
* end == -1 in that case.
*/
ret = 1;
break;
}
*done_index = page->index;
lock_page(page); lock_page(page);
if (unlikely(page->mapping != mapping)) { if (unlikely(page->mapping != mapping)) {
continue_unlock:
unlock_page(page); unlock_page(page);
continue; continue;
} }
if (!wbc->range_cyclic && page->index > end) { if (!PageDirty(page)) {
ret = 1; /* someone wrote it for us */
unlock_page(page); goto continue_unlock;
continue;
} }
if (wbc->sync_mode != WB_SYNC_NONE) if (PageWriteback(page)) {
wait_on_page_writeback(page); if (wbc->sync_mode != WB_SYNC_NONE)
wait_on_page_writeback(page);
if (PageWriteback(page) || else
!clear_page_dirty_for_io(page)) { goto continue_unlock;
unlock_page(page);
continue;
} }
/* Is the page fully outside i_size? (truncate in progress) */ BUG_ON(PageWriteback(page));
if (page->index > end_index || (page->index == end_index && !offset)) { if (!clear_page_dirty_for_io(page))
page->mapping->a_ops->invalidatepage(page, 0, goto continue_unlock;
PAGE_CACHE_SIZE);
unlock_page(page); trace_wbc_writepage(wbc, mapping->backing_dev_info);
continue;
}
ret = __gfs2_jdata_writepage(page, wbc); ret = __gfs2_jdata_writepage(page, wbc);
if (unlikely(ret)) {
if (ret == AOP_WRITEPAGE_ACTIVATE) {
unlock_page(page);
ret = 0;
} else {
/*
* done_index is set past this page,
* so media errors will not choke
* background writeout for the entire
* file. This has consequences for
* range_cyclic semantics (ie. it may
* not be suitable for data integrity
* writeout).
*/
*done_index = page->index + 1;
ret = 1;
break;
}
}
if (ret || (--(wbc->nr_to_write) <= 0)) /*
* We stop writing back only if we are not doing
* integrity sync. In case of integrity sync we have to
* keep going until we have written all the pages
* we tagged for writeback prior to entering this loop.
*/
if (--wbc->nr_to_write <= 0 && wbc->sync_mode == WB_SYNC_NONE) {
ret = 1; ret = 1;
break;
}
} }
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
return ret; return ret;
...@@ -306,51 +348,69 @@ static int gfs2_write_cache_jdata(struct address_space *mapping, ...@@ -306,51 +348,69 @@ static int gfs2_write_cache_jdata(struct address_space *mapping,
int done = 0; int done = 0;
struct pagevec pvec; struct pagevec pvec;
int nr_pages; int nr_pages;
pgoff_t uninitialized_var(writeback_index);
pgoff_t index; pgoff_t index;
pgoff_t end; pgoff_t end;
int scanned = 0; pgoff_t done_index;
int cycled;
int range_whole = 0; int range_whole = 0;
int tag;
pagevec_init(&pvec, 0); pagevec_init(&pvec, 0);
if (wbc->range_cyclic) { if (wbc->range_cyclic) {
index = mapping->writeback_index; /* Start from prev offset */ writeback_index = mapping->writeback_index; /* prev offset */
index = writeback_index;
if (index == 0)
cycled = 1;
else
cycled = 0;
end = -1; end = -1;
} else { } else {
index = wbc->range_start >> PAGE_CACHE_SHIFT; index = wbc->range_start >> PAGE_CACHE_SHIFT;
end = wbc->range_end >> PAGE_CACHE_SHIFT; end = wbc->range_end >> PAGE_CACHE_SHIFT;
if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
range_whole = 1; range_whole = 1;
scanned = 1; cycled = 1; /* ignore range_cyclic tests */
} }
if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
tag = PAGECACHE_TAG_TOWRITE;
else
tag = PAGECACHE_TAG_DIRTY;
retry: retry:
while (!done && (index <= end) && if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
(nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag_pages_for_writeback(mapping, index, end);
PAGECACHE_TAG_DIRTY, done_index = index;
min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) { while (!done && (index <= end)) {
scanned = 1; nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag,
ret = gfs2_write_jdata_pagevec(mapping, wbc, &pvec, nr_pages, end); min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
if (nr_pages == 0)
break;
ret = gfs2_write_jdata_pagevec(mapping, wbc, &pvec, nr_pages, end, &done_index);
if (ret) if (ret)
done = 1; done = 1;
if (ret > 0) if (ret > 0)
ret = 0; ret = 0;
pagevec_release(&pvec); pagevec_release(&pvec);
cond_resched(); cond_resched();
} }
if (!scanned && !done) { if (!cycled && !done) {
/* /*
* range_cyclic:
* We hit the last page and there is more work to be done: wrap * We hit the last page and there is more work to be done: wrap
* back to the start of the file * back to the start of the file
*/ */
scanned = 1; cycled = 1;
index = 0; index = 0;
end = writeback_index - 1;
goto retry; goto retry;
} }
if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
mapping->writeback_index = index; mapping->writeback_index = done_index;
return ret; return ret;
} }
......
...@@ -1327,6 +1327,121 @@ int gfs2_file_dealloc(struct gfs2_inode *ip) ...@@ -1327,6 +1327,121 @@ int gfs2_file_dealloc(struct gfs2_inode *ip)
return trunc_dealloc(ip, 0); return trunc_dealloc(ip, 0);
} }
/**
* gfs2_free_journal_extents - Free cached journal bmap info
* @jd: The journal
*
*/
void gfs2_free_journal_extents(struct gfs2_jdesc *jd)
{
struct gfs2_journal_extent *jext;
while(!list_empty(&jd->extent_list)) {
jext = list_entry(jd->extent_list.next, struct gfs2_journal_extent, list);
list_del(&jext->list);
kfree(jext);
}
}
/**
* gfs2_add_jextent - Add or merge a new extent to extent cache
* @jd: The journal descriptor
* @lblock: The logical block at start of new extent
* @pblock: The physical block at start of new extent
* @blocks: Size of extent in fs blocks
*
* Returns: 0 on success or -ENOMEM
*/
static int gfs2_add_jextent(struct gfs2_jdesc *jd, u64 lblock, u64 dblock, u64 blocks)
{
struct gfs2_journal_extent *jext;
if (!list_empty(&jd->extent_list)) {
jext = list_entry(jd->extent_list.prev, struct gfs2_journal_extent, list);
if ((jext->dblock + jext->blocks) == dblock) {
jext->blocks += blocks;
return 0;
}
}
jext = kzalloc(sizeof(struct gfs2_journal_extent), GFP_NOFS);
if (jext == NULL)
return -ENOMEM;
jext->dblock = dblock;
jext->lblock = lblock;
jext->blocks = blocks;
list_add_tail(&jext->list, &jd->extent_list);
jd->nr_extents++;
return 0;
}
/**
* gfs2_map_journal_extents - Cache journal bmap info
* @sdp: The super block
* @jd: The journal to map
*
* Create a reusable "extent" mapping from all logical
* blocks to all physical blocks for the given journal. This will save
* us time when writing journal blocks. Most journals will have only one
* extent that maps all their logical blocks. That's because gfs2.mkfs
* arranges the journal blocks sequentially to maximize performance.
* So the extent would map the first block for the entire file length.
* However, gfs2_jadd can happen while file activity is happening, so
* those journals may not be sequential. Less likely is the case where
* the users created their own journals by mounting the metafs and
* laying it out. But it's still possible. These journals might have
* several extents.
*
* Returns: 0 on success, or error on failure
*/
int gfs2_map_journal_extents(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd)
{
u64 lblock = 0;
u64 lblock_stop;
struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
struct buffer_head bh;
unsigned int shift = sdp->sd_sb.sb_bsize_shift;
u64 size;
int rc;
lblock_stop = i_size_read(jd->jd_inode) >> shift;
size = (lblock_stop - lblock) << shift;
jd->nr_extents = 0;
WARN_ON(!list_empty(&jd->extent_list));
do {
bh.b_state = 0;
bh.b_blocknr = 0;
bh.b_size = size;
rc = gfs2_block_map(jd->jd_inode, lblock, &bh, 0);
if (rc || !buffer_mapped(&bh))
goto fail;
rc = gfs2_add_jextent(jd, lblock, bh.b_blocknr, bh.b_size >> shift);
if (rc)
goto fail;
size -= bh.b_size;
lblock += (bh.b_size >> ip->i_inode.i_blkbits);
} while(size > 0);
fs_info(sdp, "journal %d mapped with %u extents\n", jd->jd_jid,
jd->nr_extents);
return 0;
fail:
fs_warn(sdp, "error %d mapping journal %u at offset %llu (extent %u)\n",
rc, jd->jd_jid,
(unsigned long long)(i_size_read(jd->jd_inode) - size),
jd->nr_extents);
fs_warn(sdp, "bmap=%d lblock=%llu block=%llu, state=0x%08lx, size=%llu\n",
rc, (unsigned long long)lblock, (unsigned long long)bh.b_blocknr,
bh.b_state, (unsigned long long)bh.b_size);
gfs2_free_journal_extents(jd);
return rc;
}
/** /**
* gfs2_write_alloc_required - figure out if a write will require an allocation * gfs2_write_alloc_required - figure out if a write will require an allocation
* @ip: the file being written to * @ip: the file being written to
......
...@@ -55,5 +55,7 @@ extern int gfs2_truncatei_resume(struct gfs2_inode *ip); ...@@ -55,5 +55,7 @@ extern int gfs2_truncatei_resume(struct gfs2_inode *ip);
extern int gfs2_file_dealloc(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, extern int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
unsigned int len); unsigned int len);
extern int gfs2_map_journal_extents(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd);
extern void gfs2_free_journal_extents(struct gfs2_jdesc *jd);
#endif /* __BMAP_DOT_H__ */ #endif /* __BMAP_DOT_H__ */
...@@ -53,6 +53,8 @@ ...@@ -53,6 +53,8 @@
* but never before the maximum hash table size has been reached. * but never before the maximum hash table size has been reached.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
...@@ -507,8 +509,8 @@ static int gfs2_check_dirent(struct gfs2_dirent *dent, unsigned int offset, ...@@ -507,8 +509,8 @@ static int gfs2_check_dirent(struct gfs2_dirent *dent, unsigned int offset,
goto error; goto error;
return 0; return 0;
error: error:
printk(KERN_WARNING "gfs2_check_dirent: %s (%s)\n", msg, pr_warn("%s: %s (%s)\n",
first ? "first in block" : "not first in block"); __func__, msg, first ? "first in block" : "not first in block");
return -EIO; return -EIO;
} }
...@@ -531,8 +533,7 @@ static int gfs2_dirent_offset(const void *buf) ...@@ -531,8 +533,7 @@ static int gfs2_dirent_offset(const void *buf)
} }
return offset; return offset;
wrong_type: wrong_type:
printk(KERN_WARNING "gfs2_scan_dirent: wrong block type %u\n", pr_warn("%s: wrong block type %u\n", __func__, be32_to_cpu(h->mh_type));
be32_to_cpu(h->mh_type));
return -1; return -1;
} }
...@@ -728,7 +729,7 @@ static int get_leaf(struct gfs2_inode *dip, u64 leaf_no, ...@@ -728,7 +729,7 @@ static int get_leaf(struct gfs2_inode *dip, u64 leaf_no,
error = gfs2_meta_read(dip->i_gl, leaf_no, DIO_WAIT, bhp); error = gfs2_meta_read(dip->i_gl, leaf_no, DIO_WAIT, bhp);
if (!error && gfs2_metatype_check(GFS2_SB(&dip->i_inode), *bhp, GFS2_METATYPE_LF)) { if (!error && gfs2_metatype_check(GFS2_SB(&dip->i_inode), *bhp, GFS2_METATYPE_LF)) {
/* printk(KERN_INFO "block num=%llu\n", leaf_no); */ /* pr_info("block num=%llu\n", leaf_no); */
error = -EIO; error = -EIO;
} }
...@@ -1006,7 +1007,8 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) ...@@ -1006,7 +1007,8 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
len = 1 << (dip->i_depth - be16_to_cpu(oleaf->lf_depth)); len = 1 << (dip->i_depth - be16_to_cpu(oleaf->lf_depth));
half_len = len >> 1; half_len = len >> 1;
if (!half_len) { if (!half_len) {
printk(KERN_WARNING "i_depth %u lf_depth %u index %u\n", dip->i_depth, be16_to_cpu(oleaf->lf_depth), index); pr_warn("i_depth %u lf_depth %u index %u\n",
dip->i_depth, be16_to_cpu(oleaf->lf_depth), index);
gfs2_consist_inode(dip); gfs2_consist_inode(dip);
error = -EIO; error = -EIO;
goto fail_brelse; goto fail_brelse;
...@@ -1684,6 +1686,14 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) ...@@ -1684,6 +1686,14 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
return 0; return 0;
} }
static u16 gfs2_inode_ra_len(const struct gfs2_inode *ip)
{
u64 where = ip->i_no_addr + 1;
if (ip->i_eattr == where)
return 1;
return 0;
}
/** /**
* gfs2_dir_add - Add new filename into directory * gfs2_dir_add - Add new filename into directory
* @inode: The directory inode * @inode: The directory inode
...@@ -1721,6 +1731,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name, ...@@ -1721,6 +1731,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
dent = gfs2_init_dirent(inode, dent, name, bh); dent = gfs2_init_dirent(inode, dent, name, bh);
gfs2_inum_out(nip, dent); gfs2_inum_out(nip, dent);
dent->de_type = cpu_to_be16(IF2DT(nip->i_inode.i_mode)); dent->de_type = cpu_to_be16(IF2DT(nip->i_inode.i_mode));
dent->de_rahead = cpu_to_be16(gfs2_inode_ra_len(nip));
tv = CURRENT_TIME; tv = CURRENT_TIME;
if (ip->i_diskflags & GFS2_DIF_EXHASH) { if (ip->i_diskflags & GFS2_DIF_EXHASH) {
leaf = (struct gfs2_leaf *)bh->b_data; leaf = (struct gfs2_leaf *)bh->b_data;
......
...@@ -811,6 +811,8 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, ...@@ -811,6 +811,8 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
loff_t bsize_mask = ~((loff_t)sdp->sd_sb.sb_bsize - 1); loff_t bsize_mask = ~((loff_t)sdp->sd_sb.sb_bsize - 1);
loff_t next = (offset + len - 1) >> sdp->sd_sb.sb_bsize_shift; loff_t next = (offset + len - 1) >> sdp->sd_sb.sb_bsize_shift;
loff_t max_chunk_size = UINT_MAX & bsize_mask; loff_t max_chunk_size = UINT_MAX & bsize_mask;
struct gfs2_holder gh;
next = (next + 1) << sdp->sd_sb.sb_bsize_shift; next = (next + 1) << sdp->sd_sb.sb_bsize_shift;
/* We only support the FALLOC_FL_KEEP_SIZE mode */ /* We only support the FALLOC_FL_KEEP_SIZE mode */
...@@ -831,8 +833,10 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, ...@@ -831,8 +833,10 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
if (error) if (error)
return error; return error;
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh); mutex_lock(&inode->i_mutex);
error = gfs2_glock_nq(&ip->i_gh);
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
error = gfs2_glock_nq(&gh);
if (unlikely(error)) if (unlikely(error))
goto out_uninit; goto out_uninit;
...@@ -900,9 +904,10 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, ...@@ -900,9 +904,10 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
out_qunlock: out_qunlock:
gfs2_quota_unlock(ip); gfs2_quota_unlock(ip);
out_unlock: out_unlock:
gfs2_glock_dq(&ip->i_gh); gfs2_glock_dq(&gh);
out_uninit: out_uninit:
gfs2_holder_uninit(&ip->i_gh); gfs2_holder_uninit(&gh);
mutex_unlock(&inode->i_mutex);
return error; return error;
} }
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* of the GNU General Public License version 2. * of the GNU General Public License version 2.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -468,7 +470,7 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret) ...@@ -468,7 +470,7 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
do_xmote(gl, gh, LM_ST_UNLOCKED); do_xmote(gl, gh, LM_ST_UNLOCKED);
break; break;
default: /* Everything else */ default: /* Everything else */
printk(KERN_ERR "GFS2: wanted %u got %u\n", gl->gl_target, state); pr_err("wanted %u got %u\n", gl->gl_target, state);
GLOCK_BUG_ON(gl, 1); GLOCK_BUG_ON(gl, 1);
} }
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
...@@ -542,7 +544,7 @@ __acquires(&gl->gl_spin) ...@@ -542,7 +544,7 @@ __acquires(&gl->gl_spin)
/* lock_dlm */ /* lock_dlm */
ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags); ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags);
if (ret) { if (ret) {
printk(KERN_ERR "GFS2: lm_lock ret %d\n", ret); pr_err("lm_lock ret %d\n", ret);
GLOCK_BUG_ON(gl, 1); GLOCK_BUG_ON(gl, 1);
} }
} else { /* lock_nolock */ } else { /* lock_nolock */
...@@ -935,7 +937,7 @@ void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...) ...@@ -935,7 +937,7 @@ void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...)
vaf.fmt = fmt; vaf.fmt = fmt;
vaf.va = &args; vaf.va = &args;
printk(KERN_ERR " %pV", &vaf); pr_err("%pV", &vaf);
} }
va_end(args); va_end(args);
...@@ -1010,13 +1012,13 @@ __acquires(&gl->gl_spin) ...@@ -1010,13 +1012,13 @@ __acquires(&gl->gl_spin)
return; return;
trap_recursive: trap_recursive:
printk(KERN_ERR "original: %pSR\n", (void *)gh2->gh_ip); pr_err("original: %pSR\n", (void *)gh2->gh_ip);
printk(KERN_ERR "pid: %d\n", pid_nr(gh2->gh_owner_pid)); pr_err("pid: %d\n", pid_nr(gh2->gh_owner_pid));
printk(KERN_ERR "lock type: %d req lock state : %d\n", pr_err("lock type: %d req lock state : %d\n",
gh2->gh_gl->gl_name.ln_type, gh2->gh_state); gh2->gh_gl->gl_name.ln_type, gh2->gh_state);
printk(KERN_ERR "new: %pSR\n", (void *)gh->gh_ip); pr_err("new: %pSR\n", (void *)gh->gh_ip);
printk(KERN_ERR "pid: %d\n", pid_nr(gh->gh_owner_pid)); pr_err("pid: %d\n", pid_nr(gh->gh_owner_pid));
printk(KERN_ERR "lock type: %d req lock state : %d\n", pr_err("lock type: %d req lock state : %d\n",
gh->gh_gl->gl_name.ln_type, gh->gh_state); gh->gh_gl->gl_name.ln_type, gh->gh_state);
gfs2_dump_glock(NULL, gl); gfs2_dump_glock(NULL, gl);
BUG(); BUG();
...@@ -1045,9 +1047,13 @@ int gfs2_glock_nq(struct gfs2_holder *gh) ...@@ -1045,9 +1047,13 @@ int gfs2_glock_nq(struct gfs2_holder *gh)
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
add_to_queue(gh); add_to_queue(gh);
if ((LM_FLAG_NOEXP & gh->gh_flags) && if (unlikely((LM_FLAG_NOEXP & gh->gh_flags) &&
test_and_clear_bit(GLF_FROZEN, &gl->gl_flags)) test_and_clear_bit(GLF_FROZEN, &gl->gl_flags))) {
set_bit(GLF_REPLY_PENDING, &gl->gl_flags); set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
gl->gl_lockref.count++;
if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
gl->gl_lockref.count--;
}
run_queue(gl, 1); run_queue(gl, 1);
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
......
...@@ -82,6 +82,8 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl) ...@@ -82,6 +82,8 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
struct gfs2_trans tr; struct gfs2_trans tr;
memset(&tr, 0, sizeof(tr)); memset(&tr, 0, sizeof(tr));
INIT_LIST_HEAD(&tr.tr_buf);
INIT_LIST_HEAD(&tr.tr_databuf);
tr.tr_revokes = atomic_read(&gl->gl_ail_count); tr.tr_revokes = atomic_read(&gl->gl_ail_count);
if (!tr.tr_revokes) if (!tr.tr_revokes)
......
...@@ -52,7 +52,7 @@ struct gfs2_log_header_host { ...@@ -52,7 +52,7 @@ struct gfs2_log_header_host {
*/ */
struct gfs2_log_operations { struct gfs2_log_operations {
void (*lo_before_commit) (struct gfs2_sbd *sdp); void (*lo_before_commit) (struct gfs2_sbd *sdp, struct gfs2_trans *tr);
void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_trans *tr); void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_trans *tr);
void (*lo_before_scan) (struct gfs2_jdesc *jd, void (*lo_before_scan) (struct gfs2_jdesc *jd,
struct gfs2_log_header_host *head, int pass); struct gfs2_log_header_host *head, int pass);
...@@ -371,6 +371,7 @@ enum { ...@@ -371,6 +371,7 @@ enum {
GIF_ALLOC_FAILED = 2, GIF_ALLOC_FAILED = 2,
GIF_SW_PAGED = 3, GIF_SW_PAGED = 3,
GIF_ORDERED = 4, GIF_ORDERED = 4,
GIF_FREE_VFS_INODE = 5,
}; };
struct gfs2_inode { struct gfs2_inode {
...@@ -462,11 +463,11 @@ struct gfs2_trans { ...@@ -462,11 +463,11 @@ struct gfs2_trans {
unsigned int tr_blocks; unsigned int tr_blocks;
unsigned int tr_revokes; unsigned int tr_revokes;
unsigned int tr_reserved; unsigned int tr_reserved;
unsigned int tr_touched:1;
unsigned int tr_attached:1;
struct gfs2_holder tr_t_gh; struct gfs2_holder tr_t_gh;
int tr_touched;
int tr_attached;
unsigned int tr_num_buf_new; unsigned int tr_num_buf_new;
unsigned int tr_num_databuf_new; unsigned int tr_num_databuf_new;
...@@ -476,6 +477,8 @@ struct gfs2_trans { ...@@ -476,6 +477,8 @@ struct gfs2_trans {
unsigned int tr_num_revoke_rm; unsigned int tr_num_revoke_rm;
struct list_head tr_list; struct list_head tr_list;
struct list_head tr_databuf;
struct list_head tr_buf;
unsigned int tr_first; unsigned int tr_first;
struct list_head tr_ail1_list; struct list_head tr_ail1_list;
...@@ -483,7 +486,7 @@ struct gfs2_trans { ...@@ -483,7 +486,7 @@ struct gfs2_trans {
}; };
struct gfs2_journal_extent { struct gfs2_journal_extent {
struct list_head extent_list; struct list_head list;
unsigned int lblock; /* First logical block */ unsigned int lblock; /* First logical block */
u64 dblock; /* First disk block */ u64 dblock; /* First disk block */
...@@ -493,6 +496,7 @@ struct gfs2_journal_extent { ...@@ -493,6 +496,7 @@ struct gfs2_journal_extent {
struct gfs2_jdesc { struct gfs2_jdesc {
struct list_head jd_list; struct list_head jd_list;
struct list_head extent_list; struct list_head extent_list;
unsigned int nr_extents;
struct work_struct jd_work; struct work_struct jd_work;
struct inode *jd_inode; struct inode *jd_inode;
unsigned long jd_flags; unsigned long jd_flags;
...@@ -500,6 +504,15 @@ struct gfs2_jdesc { ...@@ -500,6 +504,15 @@ struct gfs2_jdesc {
unsigned int jd_jid; unsigned int jd_jid;
unsigned int jd_blocks; unsigned int jd_blocks;
int jd_recover_error; int jd_recover_error;
/* Replay stuff */
unsigned int jd_found_blocks;
unsigned int jd_found_revokes;
unsigned int jd_replayed_blocks;
struct list_head jd_revoke_list;
unsigned int jd_replay_tail;
}; };
struct gfs2_statfs_change_host { struct gfs2_statfs_change_host {
...@@ -746,19 +759,12 @@ struct gfs2_sbd { ...@@ -746,19 +759,12 @@ struct gfs2_sbd {
struct gfs2_trans *sd_log_tr; struct gfs2_trans *sd_log_tr;
unsigned int sd_log_blks_reserved; unsigned int sd_log_blks_reserved;
unsigned int sd_log_commited_buf;
unsigned int sd_log_commited_databuf;
int sd_log_commited_revoke; int sd_log_commited_revoke;
atomic_t sd_log_pinned; atomic_t sd_log_pinned;
unsigned int sd_log_num_buf;
unsigned int sd_log_num_revoke; unsigned int sd_log_num_revoke;
unsigned int sd_log_num_rg;
unsigned int sd_log_num_databuf;
struct list_head sd_log_le_buf;
struct list_head sd_log_le_revoke; struct list_head sd_log_le_revoke;
struct list_head sd_log_le_databuf;
struct list_head sd_log_le_ordered; struct list_head sd_log_le_ordered;
spinlock_t sd_ordered_lock; spinlock_t sd_ordered_lock;
...@@ -786,15 +792,6 @@ struct gfs2_sbd { ...@@ -786,15 +792,6 @@ struct gfs2_sbd {
struct list_head sd_ail1_list; struct list_head sd_ail1_list;
struct list_head sd_ail2_list; struct list_head sd_ail2_list;
/* Replay stuff */
struct list_head sd_revoke_list;
unsigned int sd_replay_tail;
unsigned int sd_found_blocks;
unsigned int sd_found_revokes;
unsigned int sd_replayed_blocks;
/* For quiescing the filesystem */ /* For quiescing the filesystem */
struct gfs2_holder sd_freeze_gh; struct gfs2_holder sd_freeze_gh;
......
...@@ -376,12 +376,11 @@ static void munge_mode_uid_gid(const struct gfs2_inode *dip, ...@@ -376,12 +376,11 @@ static void munge_mode_uid_gid(const struct gfs2_inode *dip,
inode->i_gid = current_fsgid(); inode->i_gid = current_fsgid();
} }
static int alloc_dinode(struct gfs2_inode *ip, u32 flags) static int alloc_dinode(struct gfs2_inode *ip, u32 flags, unsigned *dblocks)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc_parms ap = { .target = RES_DINODE, .aflags = flags, }; struct gfs2_alloc_parms ap = { .target = *dblocks, .aflags = flags, };
int error; int error;
int dblocks = 1;
error = gfs2_quota_lock_check(ip); error = gfs2_quota_lock_check(ip);
if (error) if (error)
...@@ -391,11 +390,11 @@ static int alloc_dinode(struct gfs2_inode *ip, u32 flags) ...@@ -391,11 +390,11 @@ static int alloc_dinode(struct gfs2_inode *ip, u32 flags)
if (error) if (error)
goto out_quota; goto out_quota;
error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_STATFS + RES_QUOTA, 0); error = gfs2_trans_begin(sdp, (*dblocks * RES_RG_BIT) + RES_STATFS + RES_QUOTA, 0);
if (error) if (error)
goto out_ipreserv; goto out_ipreserv;
error = gfs2_alloc_blocks(ip, &ip->i_no_addr, &dblocks, 1, &ip->i_generation); error = gfs2_alloc_blocks(ip, &ip->i_no_addr, dblocks, 1, &ip->i_generation);
ip->i_no_formal_ino = ip->i_generation; ip->i_no_formal_ino = ip->i_generation;
ip->i_inode.i_ino = ip->i_no_addr; ip->i_inode.i_ino = ip->i_no_addr;
ip->i_goal = ip->i_no_addr; ip->i_goal = ip->i_no_addr;
...@@ -427,6 +426,33 @@ static void gfs2_init_dir(struct buffer_head *dibh, ...@@ -427,6 +426,33 @@ static void gfs2_init_dir(struct buffer_head *dibh,
} }
/**
* gfs2_init_xattr - Initialise an xattr block for a new inode
* @ip: The inode in question
*
* This sets up an empty xattr block for a new inode, ready to
* take any ACLs, LSM xattrs, etc.
*/
static void gfs2_init_xattr(struct gfs2_inode *ip)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct buffer_head *bh;
struct gfs2_ea_header *ea;
bh = gfs2_meta_new(ip->i_gl, ip->i_eattr);
gfs2_trans_add_meta(ip->i_gl, bh);
gfs2_metatype_set(bh, GFS2_METATYPE_EA, GFS2_FORMAT_EA);
gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
ea = GFS2_EA_BH2FIRST(bh);
ea->ea_rec_len = cpu_to_be32(sdp->sd_jbsize);
ea->ea_type = GFS2_EATYPE_UNUSED;
ea->ea_flags = GFS2_EAFLAG_LAST;
brelse(bh);
}
/** /**
* init_dinode - Fill in a new dinode structure * init_dinode - Fill in a new dinode structure
* @dip: The directory this inode is being created in * @dip: The directory this inode is being created in
...@@ -545,13 +571,6 @@ static int gfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array, ...@@ -545,13 +571,6 @@ static int gfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
return err; return err;
} }
static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip,
const struct qstr *qstr)
{
return security_inode_init_security(&ip->i_inode, &dip->i_inode, qstr,
&gfs2_initxattrs, NULL);
}
/** /**
* gfs2_create_inode - Create a new inode * gfs2_create_inode - Create a new inode
* @dir: The parent directory * @dir: The parent directory
...@@ -578,8 +597,9 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, ...@@ -578,8 +597,9 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct gfs2_glock *io_gl; struct gfs2_glock *io_gl;
struct dentry *d; struct dentry *d;
int error; int error, free_vfs_inode = 0;
u32 aflags = 0; u32 aflags = 0;
unsigned blocks = 1;
struct gfs2_diradd da = { .bh = NULL, }; struct gfs2_diradd da = { .bh = NULL, };
if (!name->len || name->len > GFS2_FNAMESIZE) if (!name->len || name->len > GFS2_FNAMESIZE)
...@@ -676,10 +696,15 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, ...@@ -676,10 +696,15 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
(dip->i_diskflags & GFS2_DIF_TOPDIR)) (dip->i_diskflags & GFS2_DIF_TOPDIR))
aflags |= GFS2_AF_ORLOV; aflags |= GFS2_AF_ORLOV;
error = alloc_dinode(ip, aflags); if (default_acl || acl)
blocks++;
error = alloc_dinode(ip, aflags, &blocks);
if (error) if (error)
goto fail_free_inode; goto fail_free_inode;
gfs2_set_inode_blocks(inode, blocks);
error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
if (error) if (error)
goto fail_free_inode; goto fail_free_inode;
...@@ -689,10 +714,14 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, ...@@ -689,10 +714,14 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
if (error) if (error)
goto fail_free_inode; goto fail_free_inode;
error = gfs2_trans_begin(sdp, RES_DINODE, 0); error = gfs2_trans_begin(sdp, blocks, 0);
if (error) if (error)
goto fail_gunlock2; goto fail_gunlock2;
if (blocks > 1) {
ip->i_eattr = ip->i_no_addr + 1;
gfs2_init_xattr(ip);
}
init_dinode(dip, ip, symname); init_dinode(dip, ip, symname);
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
...@@ -722,7 +751,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, ...@@ -722,7 +751,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
if (error) if (error)
goto fail_gunlock3; goto fail_gunlock3;
error = gfs2_security_init(dip, ip, name); error = security_inode_init_security(&ip->i_inode, &dip->i_inode, name,
&gfs2_initxattrs, NULL);
if (error) if (error)
goto fail_gunlock3; goto fail_gunlock3;
...@@ -758,15 +788,16 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, ...@@ -758,15 +788,16 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
if (acl) if (acl)
posix_acl_release(acl); posix_acl_release(acl);
fail_free_vfs_inode: fail_free_vfs_inode:
free_inode_nonrcu(inode); free_vfs_inode = 1;
inode = NULL;
fail_gunlock: fail_gunlock:
gfs2_dir_no_add(&da); gfs2_dir_no_add(&da);
gfs2_glock_dq_uninit(ghs); gfs2_glock_dq_uninit(ghs);
if (inode && !IS_ERR(inode)) { if (inode && !IS_ERR(inode)) {
clear_nlink(inode); clear_nlink(inode);
mark_inode_dirty(inode); if (!free_vfs_inode)
set_bit(GIF_ALLOC_FAILED, &GFS2_I(inode)->i_flags); mark_inode_dirty(inode);
set_bit(free_vfs_inode ? GIF_FREE_VFS_INODE : GIF_ALLOC_FAILED,
&GFS2_I(inode)->i_flags);
iput(inode); iput(inode);
} }
fail: fail:
...@@ -1263,6 +1294,10 @@ static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to) ...@@ -1263,6 +1294,10 @@ static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
} }
tmp = gfs2_lookupi(dir, &gfs2_qdotdot, 1); tmp = gfs2_lookupi(dir, &gfs2_qdotdot, 1);
if (!tmp) {
error = -ENOENT;
break;
}
if (IS_ERR(tmp)) { if (IS_ERR(tmp)) {
error = PTR_ERR(tmp); error = PTR_ERR(tmp);
break; break;
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* of the GNU General Public License version 2. * of the GNU General Public License version 2.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/dlm.h> #include <linux/dlm.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -176,7 +178,7 @@ static void gdlm_bast(void *arg, int mode) ...@@ -176,7 +178,7 @@ static void gdlm_bast(void *arg, int mode)
gfs2_glock_cb(gl, LM_ST_SHARED); gfs2_glock_cb(gl, LM_ST_SHARED);
break; break;
default: default:
printk(KERN_ERR "unknown bast mode %d", mode); pr_err("unknown bast mode %d\n", mode);
BUG(); BUG();
} }
} }
...@@ -195,7 +197,7 @@ static int make_mode(const unsigned int lmstate) ...@@ -195,7 +197,7 @@ static int make_mode(const unsigned int lmstate)
case LM_ST_SHARED: case LM_ST_SHARED:
return DLM_LOCK_PR; return DLM_LOCK_PR;
} }
printk(KERN_ERR "unknown LM state %d", lmstate); pr_err("unknown LM state %d\n", lmstate);
BUG(); BUG();
return -1; return -1;
} }
...@@ -308,7 +310,7 @@ static void gdlm_put_lock(struct gfs2_glock *gl) ...@@ -308,7 +310,7 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK, error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK,
NULL, gl); NULL, gl);
if (error) { if (error) {
printk(KERN_ERR "gdlm_unlock %x,%llx err=%d\n", pr_err("gdlm_unlock %x,%llx err=%d\n",
gl->gl_name.ln_type, gl->gl_name.ln_type,
(unsigned long long)gl->gl_name.ln_number, error); (unsigned long long)gl->gl_name.ln_number, error);
return; return;
...@@ -1102,7 +1104,7 @@ static void gdlm_recover_slot(void *arg, struct dlm_slot *slot) ...@@ -1102,7 +1104,7 @@ static void gdlm_recover_slot(void *arg, struct dlm_slot *slot)
} }
if (ls->ls_recover_submit[jid]) { if (ls->ls_recover_submit[jid]) {
fs_info(sdp, "recover_slot jid %d gen %u prev %u", fs_info(sdp, "recover_slot jid %d gen %u prev %u\n",
jid, ls->ls_recover_block, ls->ls_recover_submit[jid]); jid, ls->ls_recover_block, ls->ls_recover_submit[jid]);
} }
ls->ls_recover_submit[jid] = ls->ls_recover_block; ls->ls_recover_submit[jid] = ls->ls_recover_block;
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/freezer.h> #include <linux/freezer.h>
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/blkdev.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/list_sort.h> #include <linux/list_sort.h>
...@@ -145,8 +146,10 @@ void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc) ...@@ -145,8 +146,10 @@ void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc)
{ {
struct list_head *head = &sdp->sd_ail1_list; struct list_head *head = &sdp->sd_ail1_list;
struct gfs2_trans *tr; struct gfs2_trans *tr;
struct blk_plug plug;
trace_gfs2_ail_flush(sdp, wbc, 1); trace_gfs2_ail_flush(sdp, wbc, 1);
blk_start_plug(&plug);
spin_lock(&sdp->sd_ail_lock); spin_lock(&sdp->sd_ail_lock);
restart: restart:
list_for_each_entry_reverse(tr, head, tr_list) { list_for_each_entry_reverse(tr, head, tr_list) {
...@@ -156,6 +159,7 @@ void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc) ...@@ -156,6 +159,7 @@ void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc)
goto restart; goto restart;
} }
spin_unlock(&sdp->sd_ail_lock); spin_unlock(&sdp->sd_ail_lock);
blk_finish_plug(&plug);
trace_gfs2_ail_flush(sdp, wbc, 0); trace_gfs2_ail_flush(sdp, wbc, 0);
} }
...@@ -410,24 +414,22 @@ static inline unsigned int log_distance(struct gfs2_sbd *sdp, unsigned int newer ...@@ -410,24 +414,22 @@ static inline unsigned int log_distance(struct gfs2_sbd *sdp, unsigned int newer
static unsigned int calc_reserved(struct gfs2_sbd *sdp) static unsigned int calc_reserved(struct gfs2_sbd *sdp)
{ {
unsigned int reserved = 0; unsigned int reserved = 0;
unsigned int mbuf_limit, metabufhdrs_needed; unsigned int mbuf;
unsigned int dbuf_limit, databufhdrs_needed; unsigned int dbuf;
unsigned int revokes = 0; struct gfs2_trans *tr = sdp->sd_log_tr;
mbuf_limit = buf_limit(sdp); if (tr) {
metabufhdrs_needed = (sdp->sd_log_commited_buf + mbuf = tr->tr_num_buf_new - tr->tr_num_buf_rm;
(mbuf_limit - 1)) / mbuf_limit; dbuf = tr->tr_num_databuf_new - tr->tr_num_databuf_rm;
dbuf_limit = databuf_limit(sdp); reserved = mbuf + dbuf;
databufhdrs_needed = (sdp->sd_log_commited_databuf + /* Account for header blocks */
(dbuf_limit - 1)) / dbuf_limit; reserved += DIV_ROUND_UP(mbuf, buf_limit(sdp));
reserved += DIV_ROUND_UP(dbuf, databuf_limit(sdp));
}
if (sdp->sd_log_commited_revoke > 0) if (sdp->sd_log_commited_revoke > 0)
revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke, reserved += gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
sizeof(u64)); sizeof(u64));
reserved = sdp->sd_log_commited_buf + metabufhdrs_needed +
sdp->sd_log_commited_databuf + databufhdrs_needed +
revokes;
/* One for the overall header */ /* One for the overall header */
if (reserved) if (reserved)
reserved++; reserved++;
...@@ -682,36 +684,25 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) ...@@ -682,36 +684,25 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
} }
trace_gfs2_log_flush(sdp, 1); trace_gfs2_log_flush(sdp, 1);
sdp->sd_log_flush_head = sdp->sd_log_head;
sdp->sd_log_flush_wrapped = 0;
tr = sdp->sd_log_tr; tr = sdp->sd_log_tr;
if (tr) { if (tr) {
sdp->sd_log_tr = NULL; sdp->sd_log_tr = NULL;
INIT_LIST_HEAD(&tr->tr_ail1_list); INIT_LIST_HEAD(&tr->tr_ail1_list);
INIT_LIST_HEAD(&tr->tr_ail2_list); INIT_LIST_HEAD(&tr->tr_ail2_list);
tr->tr_first = sdp->sd_log_flush_head;
} }
if (sdp->sd_log_num_buf != sdp->sd_log_commited_buf) {
printk(KERN_INFO "GFS2: log buf %u %u\n", sdp->sd_log_num_buf,
sdp->sd_log_commited_buf);
gfs2_assert_withdraw(sdp, 0);
}
if (sdp->sd_log_num_databuf != sdp->sd_log_commited_databuf) {
printk(KERN_INFO "GFS2: log databuf %u %u\n",
sdp->sd_log_num_databuf, sdp->sd_log_commited_databuf);
gfs2_assert_withdraw(sdp, 0);
}
gfs2_assert_withdraw(sdp, gfs2_assert_withdraw(sdp,
sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke); sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke);
sdp->sd_log_flush_head = sdp->sd_log_head;
sdp->sd_log_flush_wrapped = 0;
if (tr)
tr->tr_first = sdp->sd_log_flush_head;
gfs2_ordered_write(sdp); gfs2_ordered_write(sdp);
lops_before_commit(sdp); lops_before_commit(sdp, tr);
gfs2_log_flush_bio(sdp, WRITE); gfs2_log_flush_bio(sdp, WRITE);
if (sdp->sd_log_head != sdp->sd_log_flush_head) { if (sdp->sd_log_head != sdp->sd_log_flush_head) {
log_flush_wait(sdp);
log_write_header(sdp, 0); log_write_header(sdp, 0);
} else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){ } else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */ atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */
...@@ -723,8 +714,6 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) ...@@ -723,8 +714,6 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
gfs2_log_lock(sdp); gfs2_log_lock(sdp);
sdp->sd_log_head = sdp->sd_log_flush_head; sdp->sd_log_head = sdp->sd_log_flush_head;
sdp->sd_log_blks_reserved = 0; sdp->sd_log_blks_reserved = 0;
sdp->sd_log_commited_buf = 0;
sdp->sd_log_commited_databuf = 0;
sdp->sd_log_commited_revoke = 0; sdp->sd_log_commited_revoke = 0;
spin_lock(&sdp->sd_ail_lock); spin_lock(&sdp->sd_ail_lock);
...@@ -740,34 +729,54 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) ...@@ -740,34 +729,54 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
kfree(tr); kfree(tr);
} }
/**
* gfs2_merge_trans - Merge a new transaction into a cached transaction
* @old: Original transaction to be expanded
* @new: New transaction to be merged
*/
static void gfs2_merge_trans(struct gfs2_trans *old, struct gfs2_trans *new)
{
WARN_ON_ONCE(old->tr_attached != 1);
old->tr_num_buf_new += new->tr_num_buf_new;
old->tr_num_databuf_new += new->tr_num_databuf_new;
old->tr_num_buf_rm += new->tr_num_buf_rm;
old->tr_num_databuf_rm += new->tr_num_databuf_rm;
old->tr_num_revoke += new->tr_num_revoke;
old->tr_num_revoke_rm += new->tr_num_revoke_rm;
list_splice_tail_init(&new->tr_databuf, &old->tr_databuf);
list_splice_tail_init(&new->tr_buf, &old->tr_buf);
}
static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
{ {
unsigned int reserved; unsigned int reserved;
unsigned int unused; unsigned int unused;
unsigned int maxres;
gfs2_log_lock(sdp); gfs2_log_lock(sdp);
sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm; if (sdp->sd_log_tr) {
sdp->sd_log_commited_databuf += tr->tr_num_databuf_new - gfs2_merge_trans(sdp->sd_log_tr, tr);
tr->tr_num_databuf_rm; } else if (tr->tr_num_buf_new || tr->tr_num_databuf_new) {
gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) || gfs2_assert_withdraw(sdp, tr->tr_t_gh.gh_gl);
(((int)sdp->sd_log_commited_databuf) >= 0)); sdp->sd_log_tr = tr;
tr->tr_attached = 1;
}
sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm; sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm;
reserved = calc_reserved(sdp); reserved = calc_reserved(sdp);
gfs2_assert_withdraw(sdp, sdp->sd_log_blks_reserved + tr->tr_reserved >= reserved); maxres = sdp->sd_log_blks_reserved + tr->tr_reserved;
unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved; gfs2_assert_withdraw(sdp, maxres >= reserved);
unused = maxres - reserved;
atomic_add(unused, &sdp->sd_log_blks_free); atomic_add(unused, &sdp->sd_log_blks_free);
trace_gfs2_log_blocks(sdp, unused); trace_gfs2_log_blocks(sdp, unused);
gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <= gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <=
sdp->sd_jdesc->jd_blocks); sdp->sd_jdesc->jd_blocks);
sdp->sd_log_blks_reserved = reserved; sdp->sd_log_blks_reserved = reserved;
if (sdp->sd_log_tr == NULL &&
(tr->tr_num_buf_new || tr->tr_num_databuf_new)) {
gfs2_assert_withdraw(sdp, tr->tr_t_gh.gh_gl);
sdp->sd_log_tr = tr;
tr->tr_attached = 1;
}
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
} }
...@@ -807,10 +816,7 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp) ...@@ -807,10 +816,7 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
down_write(&sdp->sd_log_flush_lock); down_write(&sdp->sd_log_flush_lock);
gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved); gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved);
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf);
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg);
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf);
gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list)); gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list));
sdp->sd_log_flush_head = sdp->sd_log_head; sdp->sd_log_flush_head = sdp->sd_log_head;
......
...@@ -146,8 +146,8 @@ static u64 gfs2_log_bmap(struct gfs2_sbd *sdp) ...@@ -146,8 +146,8 @@ static u64 gfs2_log_bmap(struct gfs2_sbd *sdp)
struct gfs2_journal_extent *je; struct gfs2_journal_extent *je;
u64 block; u64 block;
list_for_each_entry(je, &sdp->sd_jdesc->extent_list, extent_list) { list_for_each_entry(je, &sdp->sd_jdesc->extent_list, list) {
if (lbn >= je->lblock && lbn < je->lblock + je->blocks) { if ((lbn >= je->lblock) && (lbn < (je->lblock + je->blocks))) {
block = je->dblock + lbn - je->lblock; block = je->dblock + lbn - je->lblock;
gfs2_log_incr_head(sdp); gfs2_log_incr_head(sdp);
return block; return block;
...@@ -491,44 +491,40 @@ static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit, ...@@ -491,44 +491,40 @@ static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit,
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
} }
static void buf_lo_before_commit(struct gfs2_sbd *sdp) static void buf_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
{ {
unsigned int limit = buf_limit(sdp); /* 503 for 4k blocks */ unsigned int limit = buf_limit(sdp); /* 503 for 4k blocks */
unsigned int nbuf;
gfs2_before_commit(sdp, limit, sdp->sd_log_num_buf, if (tr == NULL)
&sdp->sd_log_le_buf, 0); return;
nbuf = tr->tr_num_buf_new - tr->tr_num_buf_rm;
gfs2_before_commit(sdp, limit, nbuf, &tr->tr_buf, 0);
} }
static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
{ {
struct list_head *head = &sdp->sd_log_le_buf; struct list_head *head;
struct gfs2_bufdata *bd; struct gfs2_bufdata *bd;
if (tr == NULL) { if (tr == NULL)
gfs2_assert(sdp, list_empty(head));
return; return;
}
head = &tr->tr_buf;
while (!list_empty(head)) { while (!list_empty(head)) {
bd = list_entry(head->next, struct gfs2_bufdata, bd_list); bd = list_entry(head->next, struct gfs2_bufdata, bd_list);
list_del_init(&bd->bd_list); list_del_init(&bd->bd_list);
sdp->sd_log_num_buf--;
gfs2_unpin(sdp, bd->bd_bh, tr); gfs2_unpin(sdp, bd->bd_bh, tr);
} }
gfs2_assert_warn(sdp, !sdp->sd_log_num_buf);
} }
static void buf_lo_before_scan(struct gfs2_jdesc *jd, static void buf_lo_before_scan(struct gfs2_jdesc *jd,
struct gfs2_log_header_host *head, int pass) struct gfs2_log_header_host *head, int pass)
{ {
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
if (pass != 0) if (pass != 0)
return; return;
sdp->sd_found_blocks = 0; jd->jd_found_blocks = 0;
sdp->sd_replayed_blocks = 0; jd->jd_replayed_blocks = 0;
} }
static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
...@@ -551,9 +547,9 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, ...@@ -551,9 +547,9 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
for (; blks; gfs2_replay_incr_blk(sdp, &start), blks--) { for (; blks; gfs2_replay_incr_blk(sdp, &start), blks--) {
blkno = be64_to_cpu(*ptr++); blkno = be64_to_cpu(*ptr++);
sdp->sd_found_blocks++; jd->jd_found_blocks++;
if (gfs2_revoke_check(sdp, blkno, start)) if (gfs2_revoke_check(jd, blkno, start))
continue; continue;
error = gfs2_replay_read_block(jd, start, &bh_log); error = gfs2_replay_read_block(jd, start, &bh_log);
...@@ -574,7 +570,7 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, ...@@ -574,7 +570,7 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
if (error) if (error)
break; break;
sdp->sd_replayed_blocks++; jd->jd_replayed_blocks++;
} }
return error; return error;
...@@ -617,10 +613,10 @@ static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass) ...@@ -617,10 +613,10 @@ static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
gfs2_meta_sync(ip->i_gl); gfs2_meta_sync(ip->i_gl);
fs_info(sdp, "jid=%u: Replayed %u of %u blocks\n", fs_info(sdp, "jid=%u: Replayed %u of %u blocks\n",
jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks); jd->jd_jid, jd->jd_replayed_blocks, jd->jd_found_blocks);
} }
static void revoke_lo_before_commit(struct gfs2_sbd *sdp) static void revoke_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
{ {
struct gfs2_meta_header *mh; struct gfs2_meta_header *mh;
unsigned int offset; unsigned int offset;
...@@ -679,13 +675,11 @@ static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) ...@@ -679,13 +675,11 @@ static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
static void revoke_lo_before_scan(struct gfs2_jdesc *jd, static void revoke_lo_before_scan(struct gfs2_jdesc *jd,
struct gfs2_log_header_host *head, int pass) struct gfs2_log_header_host *head, int pass)
{ {
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
if (pass != 0) if (pass != 0)
return; return;
sdp->sd_found_revokes = 0; jd->jd_found_revokes = 0;
sdp->sd_replay_tail = head->lh_tail; jd->jd_replay_tail = head->lh_tail;
} }
static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
...@@ -717,13 +711,13 @@ static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, ...@@ -717,13 +711,13 @@ static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
while (offset + sizeof(u64) <= sdp->sd_sb.sb_bsize) { while (offset + sizeof(u64) <= sdp->sd_sb.sb_bsize) {
blkno = be64_to_cpu(*(__be64 *)(bh->b_data + offset)); blkno = be64_to_cpu(*(__be64 *)(bh->b_data + offset));
error = gfs2_revoke_add(sdp, blkno, start); error = gfs2_revoke_add(jd, blkno, start);
if (error < 0) { if (error < 0) {
brelse(bh); brelse(bh);
return error; return error;
} }
else if (error) else if (error)
sdp->sd_found_revokes++; jd->jd_found_revokes++;
if (!--revokes) if (!--revokes)
break; break;
...@@ -743,16 +737,16 @@ static void revoke_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass) ...@@ -743,16 +737,16 @@ static void revoke_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
if (error) { if (error) {
gfs2_revoke_clean(sdp); gfs2_revoke_clean(jd);
return; return;
} }
if (pass != 1) if (pass != 1)
return; return;
fs_info(sdp, "jid=%u: Found %u revoke tags\n", fs_info(sdp, "jid=%u: Found %u revoke tags\n",
jd->jd_jid, sdp->sd_found_revokes); jd->jd_jid, jd->jd_found_revokes);
gfs2_revoke_clean(sdp); gfs2_revoke_clean(jd);
} }
/** /**
...@@ -760,12 +754,14 @@ static void revoke_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass) ...@@ -760,12 +754,14 @@ static void revoke_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
* *
*/ */
static void databuf_lo_before_commit(struct gfs2_sbd *sdp) static void databuf_lo_before_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
{ {
unsigned int limit = buf_limit(sdp) / 2; unsigned int limit = databuf_limit(sdp);
unsigned int nbuf;
gfs2_before_commit(sdp, limit, sdp->sd_log_num_databuf, if (tr == NULL)
&sdp->sd_log_le_databuf, 1); return;
nbuf = tr->tr_num_databuf_new - tr->tr_num_databuf_rm;
gfs2_before_commit(sdp, limit, nbuf, &tr->tr_databuf, 1);
} }
static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
...@@ -789,9 +785,9 @@ static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, ...@@ -789,9 +785,9 @@ static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
blkno = be64_to_cpu(*ptr++); blkno = be64_to_cpu(*ptr++);
esc = be64_to_cpu(*ptr++); esc = be64_to_cpu(*ptr++);
sdp->sd_found_blocks++; jd->jd_found_blocks++;
if (gfs2_revoke_check(sdp, blkno, start)) if (gfs2_revoke_check(jd, blkno, start))
continue; continue;
error = gfs2_replay_read_block(jd, start, &bh_log); error = gfs2_replay_read_block(jd, start, &bh_log);
...@@ -811,7 +807,7 @@ static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, ...@@ -811,7 +807,7 @@ static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
brelse(bh_log); brelse(bh_log);
brelse(bh_ip); brelse(bh_ip);
sdp->sd_replayed_blocks++; jd->jd_replayed_blocks++;
} }
return error; return error;
...@@ -835,26 +831,23 @@ static void databuf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass) ...@@ -835,26 +831,23 @@ static void databuf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
gfs2_meta_sync(ip->i_gl); gfs2_meta_sync(ip->i_gl);
fs_info(sdp, "jid=%u: Replayed %u of %u data blocks\n", fs_info(sdp, "jid=%u: Replayed %u of %u data blocks\n",
jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks); jd->jd_jid, jd->jd_replayed_blocks, jd->jd_found_blocks);
} }
static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
{ {
struct list_head *head = &sdp->sd_log_le_databuf; struct list_head *head;
struct gfs2_bufdata *bd; struct gfs2_bufdata *bd;
if (tr == NULL) { if (tr == NULL)
gfs2_assert(sdp, list_empty(head));
return; return;
}
head = &tr->tr_databuf;
while (!list_empty(head)) { while (!list_empty(head)) {
bd = list_entry(head->next, struct gfs2_bufdata, bd_list); bd = list_entry(head->next, struct gfs2_bufdata, bd_list);
list_del_init(&bd->bd_list); list_del_init(&bd->bd_list);
sdp->sd_log_num_databuf--;
gfs2_unpin(sdp, bd->bd_bh, tr); gfs2_unpin(sdp, bd->bd_bh, tr);
} }
gfs2_assert_warn(sdp, !sdp->sd_log_num_databuf);
} }
......
...@@ -46,12 +46,13 @@ static inline unsigned int databuf_limit(struct gfs2_sbd *sdp) ...@@ -46,12 +46,13 @@ static inline unsigned int databuf_limit(struct gfs2_sbd *sdp)
return limit; return limit;
} }
static inline void lops_before_commit(struct gfs2_sbd *sdp) static inline void lops_before_commit(struct gfs2_sbd *sdp,
struct gfs2_trans *tr)
{ {
int x; int x;
for (x = 0; gfs2_log_ops[x]; x++) for (x = 0; gfs2_log_ops[x]; x++)
if (gfs2_log_ops[x]->lo_before_commit) if (gfs2_log_ops[x]->lo_before_commit)
gfs2_log_ops[x]->lo_before_commit(sdp); gfs2_log_ops[x]->lo_before_commit(sdp, tr);
} }
static inline void lops_after_commit(struct gfs2_sbd *sdp, static inline void lops_after_commit(struct gfs2_sbd *sdp,
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* of the GNU General Public License version 2. * of the GNU General Public License version 2.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/completion.h> #include <linux/completion.h>
...@@ -165,7 +167,7 @@ static int __init init_gfs2_fs(void) ...@@ -165,7 +167,7 @@ static int __init init_gfs2_fs(void)
gfs2_register_debugfs(); gfs2_register_debugfs();
printk("GFS2 installed\n"); pr_info("GFS2 installed\n");
return 0; return 0;
......
...@@ -97,6 +97,11 @@ const struct address_space_operations gfs2_meta_aops = { ...@@ -97,6 +97,11 @@ const struct address_space_operations gfs2_meta_aops = {
.releasepage = gfs2_releasepage, .releasepage = gfs2_releasepage,
}; };
const struct address_space_operations gfs2_rgrp_aops = {
.writepage = gfs2_aspace_writepage,
.releasepage = gfs2_releasepage,
};
/** /**
* gfs2_getbuf - Get a buffer with a given address space * gfs2_getbuf - Get a buffer with a given address space
* @gl: the glock * @gl: the glock
...@@ -267,15 +272,10 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int ...@@ -267,15 +272,10 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int
trace_gfs2_pin(bd, 0); trace_gfs2_pin(bd, 0);
atomic_dec(&sdp->sd_log_pinned); atomic_dec(&sdp->sd_log_pinned);
list_del_init(&bd->bd_list); list_del_init(&bd->bd_list);
if (meta) { if (meta)
gfs2_assert_warn(sdp, sdp->sd_log_num_buf);
sdp->sd_log_num_buf--;
tr->tr_num_buf_rm++; tr->tr_num_buf_rm++;
} else { else
gfs2_assert_warn(sdp, sdp->sd_log_num_databuf);
sdp->sd_log_num_databuf--;
tr->tr_num_databuf_rm++; tr->tr_num_databuf_rm++;
}
tr->tr_touched = 1; tr->tr_touched = 1;
was_pinned = 1; was_pinned = 1;
brelse(bh); brelse(bh);
......
...@@ -38,12 +38,15 @@ static inline void gfs2_buffer_copy_tail(struct buffer_head *to_bh, ...@@ -38,12 +38,15 @@ static inline void gfs2_buffer_copy_tail(struct buffer_head *to_bh,
} }
extern const struct address_space_operations gfs2_meta_aops; extern const struct address_space_operations gfs2_meta_aops;
extern const struct address_space_operations gfs2_rgrp_aops;
static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping) static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping)
{ {
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
if (mapping->a_ops == &gfs2_meta_aops) if (mapping->a_ops == &gfs2_meta_aops)
return (((struct gfs2_glock *)mapping) - 1)->gl_sbd; return (((struct gfs2_glock *)mapping) - 1)->gl_sbd;
else if (mapping->a_ops == &gfs2_rgrp_aops)
return container_of(mapping, struct gfs2_sbd, sd_aspace);
else else
return inode->i_sb->s_fs_info; return inode->i_sb->s_fs_info;
} }
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* of the GNU General Public License version 2. * of the GNU General Public License version 2.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -104,7 +106,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) ...@@ -104,7 +106,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
mapping = &sdp->sd_aspace; mapping = &sdp->sd_aspace;
address_space_init_once(mapping); address_space_init_once(mapping);
mapping->a_ops = &gfs2_meta_aops; mapping->a_ops = &gfs2_rgrp_aops;
mapping->host = sb->s_bdev->bd_inode; mapping->host = sb->s_bdev->bd_inode;
mapping->flags = 0; mapping->flags = 0;
mapping_set_gfp_mask(mapping, GFP_NOFS); mapping_set_gfp_mask(mapping, GFP_NOFS);
...@@ -114,9 +116,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) ...@@ -114,9 +116,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
spin_lock_init(&sdp->sd_log_lock); spin_lock_init(&sdp->sd_log_lock);
atomic_set(&sdp->sd_log_pinned, 0); atomic_set(&sdp->sd_log_pinned, 0);
INIT_LIST_HEAD(&sdp->sd_log_le_buf);
INIT_LIST_HEAD(&sdp->sd_log_le_revoke); INIT_LIST_HEAD(&sdp->sd_log_le_revoke);
INIT_LIST_HEAD(&sdp->sd_log_le_databuf);
INIT_LIST_HEAD(&sdp->sd_log_le_ordered); INIT_LIST_HEAD(&sdp->sd_log_le_ordered);
spin_lock_init(&sdp->sd_ordered_lock); spin_lock_init(&sdp->sd_ordered_lock);
...@@ -130,8 +130,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) ...@@ -130,8 +130,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
atomic_set(&sdp->sd_log_in_flight, 0); atomic_set(&sdp->sd_log_in_flight, 0);
init_waitqueue_head(&sdp->sd_log_flush_wait); init_waitqueue_head(&sdp->sd_log_flush_wait);
INIT_LIST_HEAD(&sdp->sd_revoke_list);
return sdp; return sdp;
} }
...@@ -154,7 +152,7 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, int silent) ...@@ -154,7 +152,7 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, int silent)
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)
printk(KERN_WARNING "GFS2: not a GFS2 filesystem\n"); pr_warn("not a GFS2 filesystem\n");
return -EINVAL; return -EINVAL;
} }
...@@ -176,7 +174,7 @@ static void end_bio_io_page(struct bio *bio, int error) ...@@ -176,7 +174,7 @@ static void end_bio_io_page(struct bio *bio, int error)
if (!error) if (!error)
SetPageUptodate(page); SetPageUptodate(page);
else else
printk(KERN_WARNING "gfs2: error %d reading superblock\n", error); pr_warn("error %d reading superblock\n", error);
unlock_page(page); unlock_page(page);
} }
...@@ -519,67 +517,6 @@ static int init_sb(struct gfs2_sbd *sdp, int silent) ...@@ -519,67 +517,6 @@ static int init_sb(struct gfs2_sbd *sdp, int silent)
return ret; return ret;
} }
/**
* map_journal_extents - create a reusable "extent" mapping from all logical
* blocks to all physical blocks for the given journal. This will save
* us time when writing journal blocks. Most journals will have only one
* extent that maps all their logical blocks. That's because gfs2.mkfs
* arranges the journal blocks sequentially to maximize performance.
* So the extent would map the first block for the entire file length.
* However, gfs2_jadd can happen while file activity is happening, so
* those journals may not be sequential. Less likely is the case where
* the users created their own journals by mounting the metafs and
* laying it out. But it's still possible. These journals might have
* several extents.
*
* TODO: This should be done in bigger chunks rather than one block at a time,
* but since it's only done at mount time, I'm not worried about the
* time it takes.
*/
static int map_journal_extents(struct gfs2_sbd *sdp)
{
struct gfs2_jdesc *jd = sdp->sd_jdesc;
unsigned int lb;
u64 db, prev_db; /* logical block, disk block, prev disk block */
struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
struct gfs2_journal_extent *jext = NULL;
struct buffer_head bh;
int rc = 0;
prev_db = 0;
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;
rc = gfs2_block_map(jd->jd_inode, lb, &bh, 0);
db = bh.b_blocknr;
if (rc || !db) {
printk(KERN_INFO "GFS2 journal mapping error %d: lb="
"%u db=%llu\n", rc, lb, (unsigned long long)db);
break;
}
if (!prev_db || db != prev_db + 1) {
jext = kzalloc(sizeof(struct gfs2_journal_extent),
GFP_KERNEL);
if (!jext) {
printk(KERN_INFO "GFS2 error: out of memory "
"mapping journal extents.\n");
rc = -ENOMEM;
break;
}
jext->dblock = db;
jext->lblock = lb;
jext->blocks = 1;
list_add_tail(&jext->extent_list, &jd->extent_list);
} else {
jext->blocks++;
}
prev_db = db;
}
return rc;
}
static void gfs2_others_may_mount(struct gfs2_sbd *sdp) static void gfs2_others_may_mount(struct gfs2_sbd *sdp)
{ {
char *message = "FIRSTMOUNT=Done"; char *message = "FIRSTMOUNT=Done";
...@@ -638,6 +575,8 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh) ...@@ -638,6 +575,8 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
break; break;
INIT_LIST_HEAD(&jd->extent_list); INIT_LIST_HEAD(&jd->extent_list);
INIT_LIST_HEAD(&jd->jd_revoke_list);
INIT_WORK(&jd->jd_work, gfs2_recover_func); INIT_WORK(&jd->jd_work, gfs2_recover_func);
jd->jd_inode = gfs2_lookupi(sdp->sd_jindex, &name, 1); jd->jd_inode = gfs2_lookupi(sdp->sd_jindex, &name, 1);
if (!jd->jd_inode || IS_ERR(jd->jd_inode)) { if (!jd->jd_inode || IS_ERR(jd->jd_inode)) {
...@@ -781,7 +720,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) ...@@ -781,7 +720,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
atomic_set(&sdp->sd_log_thresh2, 4*sdp->sd_jdesc->jd_blocks/5); atomic_set(&sdp->sd_log_thresh2, 4*sdp->sd_jdesc->jd_blocks/5);
/* Map the extents for this journal's blocks */ /* Map the extents for this journal's blocks */
map_journal_extents(sdp); gfs2_map_journal_extents(sdp, sdp->sd_jdesc);
} }
trace_gfs2_log_blocks(sdp, atomic_read(&sdp->sd_log_blks_free)); trace_gfs2_log_blocks(sdp, atomic_read(&sdp->sd_log_blks_free));
...@@ -1008,7 +947,7 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent) ...@@ -1008,7 +947,7 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
lm = &gfs2_dlm_ops; lm = &gfs2_dlm_ops;
#endif #endif
} else { } else {
printk(KERN_INFO "GFS2: can't find protocol %s\n", proto); pr_info("can't find protocol %s\n", proto);
return -ENOENT; return -ENOENT;
} }
...@@ -1115,7 +1054,7 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent ...@@ -1115,7 +1054,7 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent
sdp = init_sbd(sb); sdp = init_sbd(sb);
if (!sdp) { if (!sdp) {
printk(KERN_WARNING "GFS2: can't alloc struct gfs2_sbd\n"); pr_warn("can't alloc struct gfs2_sbd\n");
return -ENOMEM; return -ENOMEM;
} }
sdp->sd_args = *args; sdp->sd_args = *args;
...@@ -1363,7 +1302,7 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags, ...@@ -1363,7 +1302,7 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,
error = gfs2_mount_args(&args, data); error = gfs2_mount_args(&args, data);
if (error) { if (error) {
printk(KERN_WARNING "GFS2: can't parse mount arguments\n"); pr_warn("can't parse mount arguments\n");
goto error_super; goto error_super;
} }
...@@ -1413,15 +1352,15 @@ static struct dentry *gfs2_mount_meta(struct file_system_type *fs_type, ...@@ -1413,15 +1352,15 @@ static struct dentry *gfs2_mount_meta(struct file_system_type *fs_type,
error = kern_path(dev_name, LOOKUP_FOLLOW, &path); error = kern_path(dev_name, LOOKUP_FOLLOW, &path);
if (error) { if (error) {
printk(KERN_WARNING "GFS2: path_lookup on %s returned error %d\n", pr_warn("path_lookup on %s returned error %d\n",
dev_name, error); dev_name, error);
return ERR_PTR(error); return ERR_PTR(error);
} }
s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super, flags, s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super, flags,
path.dentry->d_inode->i_sb->s_bdev); path.dentry->d_inode->i_sb->s_bdev);
path_put(&path); path_put(&path);
if (IS_ERR(s)) { if (IS_ERR(s)) {
printk(KERN_WARNING "GFS2: gfs2 mount does not exist\n"); pr_warn("gfs2 mount does not exist\n");
return ERR_CAST(s); return ERR_CAST(s);
} }
if ((flags ^ s->s_flags) & MS_RDONLY) { if ((flags ^ s->s_flags) & MS_RDONLY) {
......
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
* the quota file, so it is not being constantly read. * the quota file, so it is not being constantly read.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mm.h> #include <linux/mm.h>
...@@ -330,6 +332,7 @@ static int slot_get(struct gfs2_quota_data *qd) ...@@ -330,6 +332,7 @@ static int slot_get(struct gfs2_quota_data *qd)
if (bit < sdp->sd_quota_slots) { if (bit < sdp->sd_quota_slots) {
set_bit(bit, sdp->sd_quota_bitmap); set_bit(bit, sdp->sd_quota_bitmap);
qd->qd_slot = bit; qd->qd_slot = bit;
error = 0;
out: out:
qd->qd_slot_count++; qd->qd_slot_count++;
} }
...@@ -1081,10 +1084,10 @@ static int print_message(struct gfs2_quota_data *qd, char *type) ...@@ -1081,10 +1084,10 @@ static int print_message(struct gfs2_quota_data *qd, char *type)
{ {
struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd; struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
printk(KERN_INFO "GFS2: fsid=%s: quota %s for %s %u\n", fs_info(sdp, "quota %s for %s %u\n",
sdp->sd_fsname, type, type,
(qd->qd_id.type == USRQUOTA) ? "user" : "group", (qd->qd_id.type == USRQUOTA) ? "user" : "group",
from_kqid(&init_user_ns, qd->qd_id)); from_kqid(&init_user_ns, qd->qd_id));
return 0; return 0;
} }
...@@ -1242,14 +1245,13 @@ int gfs2_quota_init(struct gfs2_sbd *sdp) ...@@ -1242,14 +1245,13 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
bm_size = DIV_ROUND_UP(sdp->sd_quota_slots, 8 * sizeof(unsigned long)); bm_size = DIV_ROUND_UP(sdp->sd_quota_slots, 8 * sizeof(unsigned long));
bm_size *= sizeof(unsigned long); bm_size *= sizeof(unsigned long);
error = -ENOMEM; error = -ENOMEM;
sdp->sd_quota_bitmap = kmalloc(bm_size, GFP_NOFS|__GFP_NOWARN); sdp->sd_quota_bitmap = kzalloc(bm_size, GFP_NOFS | __GFP_NOWARN);
if (sdp->sd_quota_bitmap == NULL) if (sdp->sd_quota_bitmap == NULL)
sdp->sd_quota_bitmap = __vmalloc(bm_size, GFP_NOFS, PAGE_KERNEL); sdp->sd_quota_bitmap = __vmalloc(bm_size, GFP_NOFS |
__GFP_ZERO, PAGE_KERNEL);
if (!sdp->sd_quota_bitmap) if (!sdp->sd_quota_bitmap)
return error; return error;
memset(sdp->sd_quota_bitmap, 0, bm_size);
for (x = 0; x < blocks; x++) { for (x = 0; x < blocks; x++) {
struct buffer_head *bh; struct buffer_head *bh;
const struct gfs2_quota_change *qc; const struct gfs2_quota_change *qc;
......
...@@ -52,9 +52,9 @@ int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk, ...@@ -52,9 +52,9 @@ int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,
return error; return error;
} }
int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where) int gfs2_revoke_add(struct gfs2_jdesc *jd, u64 blkno, unsigned int where)
{ {
struct list_head *head = &sdp->sd_revoke_list; struct list_head *head = &jd->jd_revoke_list;
struct gfs2_revoke_replay *rr; struct gfs2_revoke_replay *rr;
int found = 0; int found = 0;
...@@ -81,13 +81,13 @@ int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where) ...@@ -81,13 +81,13 @@ int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where)
return 1; return 1;
} }
int gfs2_revoke_check(struct gfs2_sbd *sdp, u64 blkno, unsigned int where) int gfs2_revoke_check(struct gfs2_jdesc *jd, u64 blkno, unsigned int where)
{ {
struct gfs2_revoke_replay *rr; struct gfs2_revoke_replay *rr;
int wrap, a, b, revoke; int wrap, a, b, revoke;
int found = 0; int found = 0;
list_for_each_entry(rr, &sdp->sd_revoke_list, rr_list) { list_for_each_entry(rr, &jd->jd_revoke_list, rr_list) {
if (rr->rr_blkno == blkno) { if (rr->rr_blkno == blkno) {
found = 1; found = 1;
break; break;
...@@ -97,17 +97,17 @@ int gfs2_revoke_check(struct gfs2_sbd *sdp, u64 blkno, unsigned int where) ...@@ -97,17 +97,17 @@ int gfs2_revoke_check(struct gfs2_sbd *sdp, u64 blkno, unsigned int where)
if (!found) if (!found)
return 0; return 0;
wrap = (rr->rr_where < sdp->sd_replay_tail); wrap = (rr->rr_where < jd->jd_replay_tail);
a = (sdp->sd_replay_tail < where); a = (jd->jd_replay_tail < where);
b = (where < rr->rr_where); b = (where < rr->rr_where);
revoke = (wrap) ? (a || b) : (a && b); revoke = (wrap) ? (a || b) : (a && b);
return revoke; return revoke;
} }
void gfs2_revoke_clean(struct gfs2_sbd *sdp) void gfs2_revoke_clean(struct gfs2_jdesc *jd)
{ {
struct list_head *head = &sdp->sd_revoke_list; struct list_head *head = &jd->jd_revoke_list;
struct gfs2_revoke_replay *rr; struct gfs2_revoke_replay *rr;
while (!list_empty(head)) { while (!list_empty(head)) {
......
...@@ -23,9 +23,9 @@ static inline void gfs2_replay_incr_blk(struct gfs2_sbd *sdp, unsigned int *blk) ...@@ -23,9 +23,9 @@ static inline void gfs2_replay_incr_blk(struct gfs2_sbd *sdp, unsigned int *blk)
extern int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk, extern int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,
struct buffer_head **bh); struct buffer_head **bh);
extern int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where); extern int gfs2_revoke_add(struct gfs2_jdesc *jd, u64 blkno, unsigned int where);
extern int gfs2_revoke_check(struct gfs2_sbd *sdp, u64 blkno, unsigned int where); extern int gfs2_revoke_check(struct gfs2_jdesc *jd, u64 blkno, unsigned int where);
extern void gfs2_revoke_clean(struct gfs2_sbd *sdp); extern void gfs2_revoke_clean(struct gfs2_jdesc *jd);
extern int gfs2_find_jhead(struct gfs2_jdesc *jd, extern int gfs2_find_jhead(struct gfs2_jdesc *jd,
struct gfs2_log_header_host *head); struct gfs2_log_header_host *head);
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* of the GNU General Public License version 2. * of the GNU General Public License version 2.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/completion.h> #include <linux/completion.h>
...@@ -99,12 +101,12 @@ static inline void gfs2_setbit(const struct gfs2_rbm *rbm, bool do_clone, ...@@ -99,12 +101,12 @@ static inline void gfs2_setbit(const struct gfs2_rbm *rbm, bool do_clone,
cur_state = (*byte1 >> bit) & GFS2_BIT_MASK; cur_state = (*byte1 >> bit) & GFS2_BIT_MASK;
if (unlikely(!valid_change[new_state * 4 + cur_state])) { if (unlikely(!valid_change[new_state * 4 + cur_state])) {
printk(KERN_WARNING "GFS2: buf_blk = 0x%x old_state=%d, " pr_warn("buf_blk = 0x%x old_state=%d, new_state=%d\n",
"new_state=%d\n", rbm->offset, cur_state, new_state); rbm->offset, cur_state, new_state);
printk(KERN_WARNING "GFS2: rgrp=0x%llx bi_start=0x%x\n", pr_warn("rgrp=0x%llx bi_start=0x%x\n",
(unsigned long long)rbm->rgd->rd_addr, bi->bi_start); (unsigned long long)rbm->rgd->rd_addr, bi->bi_start);
printk(KERN_WARNING "GFS2: bi_offset=0x%x bi_len=0x%x\n", pr_warn("bi_offset=0x%x bi_len=0x%x\n",
bi->bi_offset, bi->bi_len); bi->bi_offset, bi->bi_len);
dump_stack(); dump_stack();
gfs2_consist_rgrpd(rbm->rgd); gfs2_consist_rgrpd(rbm->rgd);
return; return;
...@@ -736,11 +738,11 @@ void gfs2_clear_rgrpd(struct gfs2_sbd *sdp) ...@@ -736,11 +738,11 @@ void gfs2_clear_rgrpd(struct gfs2_sbd *sdp)
static void gfs2_rindex_print(const struct gfs2_rgrpd *rgd) static void gfs2_rindex_print(const struct gfs2_rgrpd *rgd)
{ {
printk(KERN_INFO " ri_addr = %llu\n", (unsigned long long)rgd->rd_addr); pr_info("ri_addr = %llu\n", (unsigned long long)rgd->rd_addr);
printk(KERN_INFO " ri_length = %u\n", rgd->rd_length); pr_info("ri_length = %u\n", rgd->rd_length);
printk(KERN_INFO " ri_data0 = %llu\n", (unsigned long long)rgd->rd_data0); pr_info("ri_data0 = %llu\n", (unsigned long long)rgd->rd_data0);
printk(KERN_INFO " ri_data = %u\n", rgd->rd_data); pr_info("ri_data = %u\n", rgd->rd_data);
printk(KERN_INFO " ri_bitbytes = %u\n", rgd->rd_bitbytes); pr_info("ri_bitbytes = %u\n", rgd->rd_bitbytes);
} }
/** /**
...@@ -1102,7 +1104,7 @@ static u32 count_unlinked(struct gfs2_rgrpd *rgd) ...@@ -1102,7 +1104,7 @@ static u32 count_unlinked(struct gfs2_rgrpd *rgd)
* Returns: errno * Returns: errno
*/ */
int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd) static int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
{ {
struct gfs2_sbd *sdp = rgd->rd_sbd; struct gfs2_sbd *sdp = rgd->rd_sbd;
struct gfs2_glock *gl = rgd->rd_gl; struct gfs2_glock *gl = rgd->rd_gl;
...@@ -1169,7 +1171,7 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd) ...@@ -1169,7 +1171,7 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
return error; return error;
} }
int update_rgrp_lvb(struct gfs2_rgrpd *rgd) static int update_rgrp_lvb(struct gfs2_rgrpd *rgd)
{ {
u32 rl_flags; u32 rl_flags;
...@@ -2278,7 +2280,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, ...@@ -2278,7 +2280,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
} }
} }
if (rbm.rgd->rd_free < *nblocks) { if (rbm.rgd->rd_free < *nblocks) {
printk(KERN_WARNING "nblocks=%u\n", *nblocks); pr_warn("nblocks=%u\n", *nblocks);
goto rgrp_error; goto rgrp_error;
} }
...@@ -2296,7 +2298,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, ...@@ -2296,7 +2298,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
gfs2_statfs_change(sdp, 0, -(s64)*nblocks, dinode ? 1 : 0); gfs2_statfs_change(sdp, 0, -(s64)*nblocks, dinode ? 1 : 0);
if (dinode) if (dinode)
gfs2_trans_add_unrevoke(sdp, block, 1); gfs2_trans_add_unrevoke(sdp, block, *nblocks);
gfs2_quota_change(ip, *nblocks, ip->i_inode.i_uid, ip->i_inode.i_gid); gfs2_quota_change(ip, *nblocks, ip->i_inode.i_uid, ip->i_inode.i_gid);
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* of the GNU General Public License version 2. * of the GNU General Public License version 2.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -175,8 +177,7 @@ int gfs2_mount_args(struct gfs2_args *args, char *options) ...@@ -175,8 +177,7 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
break; break;
case Opt_debug: case Opt_debug:
if (args->ar_errors == GFS2_ERRORS_PANIC) { if (args->ar_errors == GFS2_ERRORS_PANIC) {
printk(KERN_WARNING "GFS2: -o debug and -o errors=panic " pr_warn("-o debug and -o errors=panic are mutually exclusive\n");
"are mutually exclusive.\n");
return -EINVAL; return -EINVAL;
} }
args->ar_debug = 1; args->ar_debug = 1;
...@@ -228,21 +229,21 @@ int gfs2_mount_args(struct gfs2_args *args, char *options) ...@@ -228,21 +229,21 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
case Opt_commit: case Opt_commit:
rv = match_int(&tmp[0], &args->ar_commit); rv = match_int(&tmp[0], &args->ar_commit);
if (rv || args->ar_commit <= 0) { if (rv || args->ar_commit <= 0) {
printk(KERN_WARNING "GFS2: commit mount option requires a positive numeric argument\n"); pr_warn("commit mount option requires a positive numeric argument\n");
return rv ? rv : -EINVAL; return rv ? rv : -EINVAL;
} }
break; break;
case Opt_statfs_quantum: case Opt_statfs_quantum:
rv = match_int(&tmp[0], &args->ar_statfs_quantum); rv = match_int(&tmp[0], &args->ar_statfs_quantum);
if (rv || args->ar_statfs_quantum < 0) { if (rv || args->ar_statfs_quantum < 0) {
printk(KERN_WARNING "GFS2: statfs_quantum mount option requires a non-negative numeric argument\n"); pr_warn("statfs_quantum mount option requires a non-negative numeric argument\n");
return rv ? rv : -EINVAL; return rv ? rv : -EINVAL;
} }
break; break;
case Opt_quota_quantum: case Opt_quota_quantum:
rv = match_int(&tmp[0], &args->ar_quota_quantum); rv = match_int(&tmp[0], &args->ar_quota_quantum);
if (rv || args->ar_quota_quantum <= 0) { if (rv || args->ar_quota_quantum <= 0) {
printk(KERN_WARNING "GFS2: quota_quantum mount option requires a positive numeric argument\n"); pr_warn("quota_quantum mount option requires a positive numeric argument\n");
return rv ? rv : -EINVAL; return rv ? rv : -EINVAL;
} }
break; break;
...@@ -250,7 +251,7 @@ int gfs2_mount_args(struct gfs2_args *args, char *options) ...@@ -250,7 +251,7 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
rv = match_int(&tmp[0], &args->ar_statfs_percent); rv = match_int(&tmp[0], &args->ar_statfs_percent);
if (rv || args->ar_statfs_percent < 0 || if (rv || args->ar_statfs_percent < 0 ||
args->ar_statfs_percent > 100) { args->ar_statfs_percent > 100) {
printk(KERN_WARNING "statfs_percent mount option requires a numeric argument between 0 and 100\n"); pr_warn("statfs_percent mount option requires a numeric argument between 0 and 100\n");
return rv ? rv : -EINVAL; return rv ? rv : -EINVAL;
} }
break; break;
...@@ -259,8 +260,7 @@ int gfs2_mount_args(struct gfs2_args *args, char *options) ...@@ -259,8 +260,7 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
break; break;
case Opt_err_panic: case Opt_err_panic:
if (args->ar_debug) { if (args->ar_debug) {
printk(KERN_WARNING "GFS2: -o debug and -o errors=panic " pr_warn("-o debug and -o errors=panic are mutually exclusive\n");
"are mutually exclusive.\n");
return -EINVAL; return -EINVAL;
} }
args->ar_errors = GFS2_ERRORS_PANIC; args->ar_errors = GFS2_ERRORS_PANIC;
...@@ -279,7 +279,7 @@ int gfs2_mount_args(struct gfs2_args *args, char *options) ...@@ -279,7 +279,7 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
break; break;
case Opt_error: case Opt_error:
default: default:
printk(KERN_WARNING "GFS2: invalid mount option: %s\n", o); pr_warn("invalid mount option: %s\n", o);
return -EINVAL; return -EINVAL;
} }
} }
...@@ -295,9 +295,8 @@ int gfs2_mount_args(struct gfs2_args *args, char *options) ...@@ -295,9 +295,8 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
void gfs2_jindex_free(struct gfs2_sbd *sdp) void gfs2_jindex_free(struct gfs2_sbd *sdp)
{ {
struct list_head list, *head; struct list_head list;
struct gfs2_jdesc *jd; struct gfs2_jdesc *jd;
struct gfs2_journal_extent *jext;
spin_lock(&sdp->sd_jindex_spin); spin_lock(&sdp->sd_jindex_spin);
list_add(&list, &sdp->sd_jindex_list); list_add(&list, &sdp->sd_jindex_list);
...@@ -307,14 +306,7 @@ void gfs2_jindex_free(struct gfs2_sbd *sdp) ...@@ -307,14 +306,7 @@ void gfs2_jindex_free(struct gfs2_sbd *sdp)
while (!list_empty(&list)) { while (!list_empty(&list)) {
jd = list_entry(list.next, struct gfs2_jdesc, jd_list); jd = list_entry(list.next, struct gfs2_jdesc, jd_list);
head = &jd->extent_list; gfs2_free_journal_extents(jd);
while (!list_empty(head)) {
jext = list_entry(head->next,
struct gfs2_journal_extent,
extent_list);
list_del(&jext->extent_list);
kfree(jext);
}
list_del(&jd->jd_list); list_del(&jd->jd_list);
iput(jd->jd_inode); iput(jd->jd_inode);
kfree(jd); kfree(jd);
...@@ -1256,7 +1248,7 @@ static int gfs2_drop_inode(struct inode *inode) ...@@ -1256,7 +1248,7 @@ static int gfs2_drop_inode(struct inode *inode)
{ {
struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_inode *ip = GFS2_I(inode);
if (inode->i_nlink) { if (!test_bit(GIF_FREE_VFS_INODE, &ip->i_flags) && inode->i_nlink) {
struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl;
if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags)) if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags))
clear_nlink(inode); clear_nlink(inode);
...@@ -1471,6 +1463,11 @@ static void gfs2_evict_inode(struct inode *inode) ...@@ -1471,6 +1463,11 @@ static void gfs2_evict_inode(struct inode *inode)
struct gfs2_holder gh; struct gfs2_holder gh;
int error; int error;
if (test_bit(GIF_FREE_VFS_INODE, &ip->i_flags)) {
clear_inode(inode);
return;
}
if (inode->i_nlink || (sb->s_flags & MS_RDONLY)) if (inode->i_nlink || (sb->s_flags & MS_RDONLY))
goto out; goto out;
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* of the GNU General Public License version 2. * of the GNU General Public License version 2.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/completion.h> #include <linux/completion.h>
...@@ -138,9 +140,8 @@ static ssize_t withdraw_store(struct gfs2_sbd *sdp, const char *buf, size_t len) ...@@ -138,9 +140,8 @@ static ssize_t withdraw_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
if (simple_strtol(buf, NULL, 0) != 1) if (simple_strtol(buf, NULL, 0) != 1)
return -EINVAL; return -EINVAL;
gfs2_lm_withdraw(sdp, gfs2_lm_withdraw(sdp, "withdrawing from cluster at user's request\n");
"GFS2: fsid=%s: withdrawing from cluster at user's request\n",
sdp->sd_fsname);
return len; return len;
} }
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* of the GNU General Public License version 2. * of the GNU General Public License version 2.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -51,6 +53,9 @@ int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks, ...@@ -51,6 +53,9 @@ int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks,
if (revokes) if (revokes)
tr->tr_reserved += gfs2_struct2blk(sdp, revokes, tr->tr_reserved += gfs2_struct2blk(sdp, revokes,
sizeof(u64)); sizeof(u64));
INIT_LIST_HEAD(&tr->tr_databuf);
INIT_LIST_HEAD(&tr->tr_buf);
sb_start_intwrite(sdp->sd_vfs); sb_start_intwrite(sdp->sd_vfs);
gfs2_holder_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &tr->tr_t_gh); gfs2_holder_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &tr->tr_t_gh);
...@@ -96,14 +101,13 @@ static void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks) ...@@ -96,14 +101,13 @@ static void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks)
static void gfs2_print_trans(const struct gfs2_trans *tr) static void gfs2_print_trans(const struct gfs2_trans *tr)
{ {
printk(KERN_WARNING "GFS2: Transaction created at: %pSR\n", pr_warn("Transaction created at: %pSR\n", (void *)tr->tr_ip);
(void *)tr->tr_ip); pr_warn("blocks=%u revokes=%u reserved=%u touched=%u\n",
printk(KERN_WARNING "GFS2: blocks=%u revokes=%u reserved=%u touched=%d\n", tr->tr_blocks, tr->tr_revokes, tr->tr_reserved, tr->tr_touched);
tr->tr_blocks, tr->tr_revokes, tr->tr_reserved, tr->tr_touched); pr_warn("Buf %u/%u Databuf %u/%u Revoke %u/%u\n",
printk(KERN_WARNING "GFS2: Buf %u/%u Databuf %u/%u Revoke %u/%u\n", tr->tr_num_buf_new, tr->tr_num_buf_rm,
tr->tr_num_buf_new, tr->tr_num_buf_rm, tr->tr_num_databuf_new, tr->tr_num_databuf_rm,
tr->tr_num_databuf_new, tr->tr_num_databuf_rm, tr->tr_num_revoke, tr->tr_num_revoke_rm);
tr->tr_num_revoke, tr->tr_num_revoke_rm);
} }
void gfs2_trans_end(struct gfs2_sbd *sdp) void gfs2_trans_end(struct gfs2_sbd *sdp)
...@@ -210,8 +214,7 @@ void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh) ...@@ -210,8 +214,7 @@ void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh)
set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
gfs2_pin(sdp, bd->bd_bh); gfs2_pin(sdp, bd->bd_bh);
tr->tr_num_databuf_new++; tr->tr_num_databuf_new++;
sdp->sd_log_num_databuf++; list_add_tail(&bd->bd_list, &tr->tr_databuf);
list_add_tail(&bd->bd_list, &sdp->sd_log_le_databuf);
} }
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
unlock_buffer(bh); unlock_buffer(bh);
...@@ -230,16 +233,14 @@ static void meta_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) ...@@ -230,16 +233,14 @@ static void meta_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; mh = (struct gfs2_meta_header *)bd->bd_bh->b_data;
if (unlikely(mh->mh_magic != cpu_to_be32(GFS2_MAGIC))) { if (unlikely(mh->mh_magic != cpu_to_be32(GFS2_MAGIC))) {
printk(KERN_ERR pr_err("Attempting to add uninitialised block to journal (inplace block=%lld)\n",
"Attempting to add uninitialised block to journal (inplace block=%lld)\n",
(unsigned long long)bd->bd_bh->b_blocknr); (unsigned long long)bd->bd_bh->b_blocknr);
BUG(); BUG();
} }
gfs2_pin(sdp, bd->bd_bh); gfs2_pin(sdp, bd->bd_bh);
mh->__pad0 = cpu_to_be64(0); mh->__pad0 = cpu_to_be64(0);
mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid);
sdp->sd_log_num_buf++; list_add(&bd->bd_list, &tr->tr_buf);
list_add(&bd->bd_list, &sdp->sd_log_le_buf);
tr->tr_num_buf_new++; tr->tr_num_buf_new++;
} }
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* of the GNU General Public License version 2. * of the GNU General Public License version 2.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
...@@ -30,22 +32,27 @@ mempool_t *gfs2_page_pool __read_mostly; ...@@ -30,22 +32,27 @@ mempool_t *gfs2_page_pool __read_mostly;
void gfs2_assert_i(struct gfs2_sbd *sdp) void gfs2_assert_i(struct gfs2_sbd *sdp)
{ {
printk(KERN_EMERG "GFS2: fsid=%s: fatal assertion failed\n", fs_emerg(sdp, "fatal assertion failed\n");
sdp->sd_fsname);
} }
int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...) int gfs2_lm_withdraw(struct gfs2_sbd *sdp, const char *fmt, ...)
{ {
struct lm_lockstruct *ls = &sdp->sd_lockstruct; struct lm_lockstruct *ls = &sdp->sd_lockstruct;
const struct lm_lockops *lm = ls->ls_ops; const struct lm_lockops *lm = ls->ls_ops;
va_list args; va_list args;
struct va_format vaf;
if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW && if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW &&
test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags)) test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags))
return 0; return 0;
va_start(args, fmt); va_start(args, fmt);
vprintk(fmt, args);
vaf.fmt = fmt;
vaf.va = &args;
fs_err(sdp, "%pV", &vaf);
va_end(args); va_end(args);
if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW) { if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW) {
...@@ -66,7 +73,7 @@ int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...) ...@@ -66,7 +73,7 @@ int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...)
} }
if (sdp->sd_args.ar_errors == GFS2_ERRORS_PANIC) if (sdp->sd_args.ar_errors == GFS2_ERRORS_PANIC)
panic("GFS2: fsid=%s: panic requested.\n", sdp->sd_fsname); panic("GFS2: fsid=%s: panic requested\n", sdp->sd_fsname);
return -1; return -1;
} }
...@@ -82,10 +89,9 @@ int gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion, ...@@ -82,10 +89,9 @@ int gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion,
{ {
int me; int me;
me = gfs2_lm_withdraw(sdp, me = gfs2_lm_withdraw(sdp,
"GFS2: fsid=%s: fatal: assertion \"%s\" failed\n" "fatal: assertion \"%s\" failed\n"
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n", " function = %s, file = %s, line = %u\n",
sdp->sd_fsname, assertion, assertion, function, file, line);
sdp->sd_fsname, function, file, line);
dump_stack(); dump_stack();
return (me) ? -1 : -2; return (me) ? -1 : -2;
} }
...@@ -105,11 +111,8 @@ int gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion, ...@@ -105,11 +111,8 @@ int gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion,
return -2; return -2;
if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW) if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW)
printk(KERN_WARNING fs_warn(sdp, "warning: assertion \"%s\" failed at function = %s, file = %s, line = %u\n",
"GFS2: fsid=%s: warning: assertion \"%s\" failed\n" assertion, function, file, line);
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n",
sdp->sd_fsname, assertion,
sdp->sd_fsname, function, file, line);
if (sdp->sd_args.ar_debug) if (sdp->sd_args.ar_debug)
BUG(); BUG();
...@@ -138,10 +141,8 @@ int gfs2_consist_i(struct gfs2_sbd *sdp, int cluster_wide, const char *function, ...@@ -138,10 +141,8 @@ int gfs2_consist_i(struct gfs2_sbd *sdp, int cluster_wide, const char *function,
{ {
int rv; int rv;
rv = gfs2_lm_withdraw(sdp, rv = gfs2_lm_withdraw(sdp,
"GFS2: fsid=%s: fatal: filesystem consistency error\n" "fatal: filesystem consistency error - function = %s, file = %s, line = %u\n",
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n", function, file, line);
sdp->sd_fsname,
sdp->sd_fsname, function, file, line);
return rv; return rv;
} }
...@@ -157,13 +158,12 @@ int gfs2_consist_inode_i(struct gfs2_inode *ip, int cluster_wide, ...@@ -157,13 +158,12 @@ int gfs2_consist_inode_i(struct gfs2_inode *ip, int cluster_wide,
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
int rv; int rv;
rv = gfs2_lm_withdraw(sdp, rv = gfs2_lm_withdraw(sdp,
"GFS2: fsid=%s: fatal: filesystem consistency error\n" "fatal: filesystem consistency error\n"
"GFS2: fsid=%s: inode = %llu %llu\n" " inode = %llu %llu\n"
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n", " function = %s, file = %s, line = %u\n",
sdp->sd_fsname, (unsigned long long)ip->i_no_formal_ino,
sdp->sd_fsname, (unsigned long long)ip->i_no_formal_ino, (unsigned long long)ip->i_no_addr,
(unsigned long long)ip->i_no_addr, function, file, line);
sdp->sd_fsname, function, file, line);
return rv; return rv;
} }
...@@ -179,12 +179,11 @@ int gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd, int cluster_wide, ...@@ -179,12 +179,11 @@ int gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd, int cluster_wide,
struct gfs2_sbd *sdp = rgd->rd_sbd; struct gfs2_sbd *sdp = rgd->rd_sbd;
int rv; int rv;
rv = gfs2_lm_withdraw(sdp, rv = gfs2_lm_withdraw(sdp,
"GFS2: fsid=%s: fatal: filesystem consistency error\n" "fatal: filesystem consistency error\n"
"GFS2: fsid=%s: RG = %llu\n" " RG = %llu\n"
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n", " function = %s, file = %s, line = %u\n",
sdp->sd_fsname, (unsigned long long)rgd->rd_addr,
sdp->sd_fsname, (unsigned long long)rgd->rd_addr, function, file, line);
sdp->sd_fsname, function, file, line);
return rv; return rv;
} }
...@@ -200,12 +199,11 @@ int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh, ...@@ -200,12 +199,11 @@ int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
{ {
int me; int me;
me = gfs2_lm_withdraw(sdp, me = gfs2_lm_withdraw(sdp,
"GFS2: fsid=%s: fatal: invalid metadata block\n" "fatal: invalid metadata block\n"
"GFS2: fsid=%s: bh = %llu (%s)\n" " bh = %llu (%s)\n"
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n", " function = %s, file = %s, line = %u\n",
sdp->sd_fsname, (unsigned long long)bh->b_blocknr, type,
sdp->sd_fsname, (unsigned long long)bh->b_blocknr, type, function, file, line);
sdp->sd_fsname, function, file, line);
return (me) ? -1 : -2; return (me) ? -1 : -2;
} }
...@@ -221,12 +219,11 @@ int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh, ...@@ -221,12 +219,11 @@ int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
{ {
int me; int me;
me = gfs2_lm_withdraw(sdp, me = gfs2_lm_withdraw(sdp,
"GFS2: fsid=%s: fatal: invalid metadata block\n" "fatal: invalid metadata block\n"
"GFS2: fsid=%s: bh = %llu (type: exp=%u, found=%u)\n" " bh = %llu (type: exp=%u, found=%u)\n"
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n", " function = %s, file = %s, line = %u\n",
sdp->sd_fsname, (unsigned long long)bh->b_blocknr, type, t,
sdp->sd_fsname, (unsigned long long)bh->b_blocknr, type, t, function, file, line);
sdp->sd_fsname, function, file, line);
return (me) ? -1 : -2; return (me) ? -1 : -2;
} }
...@@ -241,10 +238,9 @@ int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function, char *file, ...@@ -241,10 +238,9 @@ int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function, char *file,
{ {
int rv; int rv;
rv = gfs2_lm_withdraw(sdp, rv = gfs2_lm_withdraw(sdp,
"GFS2: fsid=%s: fatal: I/O error\n" "fatal: I/O error\n"
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n", " function = %s, file = %s, line = %u\n",
sdp->sd_fsname, function, file, line);
sdp->sd_fsname, function, file, line);
return rv; return rv;
} }
...@@ -259,12 +255,11 @@ int gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh, ...@@ -259,12 +255,11 @@ int gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh,
{ {
int rv; int rv;
rv = gfs2_lm_withdraw(sdp, rv = gfs2_lm_withdraw(sdp,
"GFS2: fsid=%s: fatal: I/O error\n" "fatal: I/O error\n"
"GFS2: fsid=%s: block = %llu\n" " block = %llu\n"
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n", " function = %s, file = %s, line = %u\n",
sdp->sd_fsname, (unsigned long long)bh->b_blocknr,
sdp->sd_fsname, (unsigned long long)bh->b_blocknr, function, file, line);
sdp->sd_fsname, function, file, line);
return rv; return rv;
} }
...@@ -10,22 +10,23 @@ ...@@ -10,22 +10,23 @@
#ifndef __UTIL_DOT_H__ #ifndef __UTIL_DOT_H__
#define __UTIL_DOT_H__ #define __UTIL_DOT_H__
#ifdef pr_fmt
#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#endif
#include <linux/mempool.h> #include <linux/mempool.h>
#include "incore.h" #include "incore.h"
#define fs_printk(level, fs, fmt, arg...) \ #define fs_emerg(fs, fmt, ...) \
printk(level "GFS2: fsid=%s: " fmt , (fs)->sd_fsname , ## arg) pr_emerg("fsid=%s: " fmt, (fs)->sd_fsname, ##__VA_ARGS__)
#define fs_warn(fs, fmt, ...) \
#define fs_info(fs, fmt, arg...) \ pr_warn("fsid=%s: " fmt, (fs)->sd_fsname, ##__VA_ARGS__)
fs_printk(KERN_INFO , fs , fmt , ## arg) #define fs_err(fs, fmt, ...) \
pr_err("fsid=%s: " fmt, (fs)->sd_fsname, ##__VA_ARGS__)
#define fs_warn(fs, fmt, arg...) \ #define fs_info(fs, fmt, ...) \
fs_printk(KERN_WARNING , fs , fmt , ## arg) pr_info("fsid=%s: " fmt, (fs)->sd_fsname, ##__VA_ARGS__)
#define fs_err(fs, fmt, arg...) \
fs_printk(KERN_ERR, fs , fmt , ## arg)
void gfs2_assert_i(struct gfs2_sbd *sdp); void gfs2_assert_i(struct gfs2_sbd *sdp);
...@@ -85,7 +86,7 @@ static inline int gfs2_meta_check(struct gfs2_sbd *sdp, ...@@ -85,7 +86,7 @@ static inline int gfs2_meta_check(struct gfs2_sbd *sdp,
struct gfs2_meta_header *mh = (struct gfs2_meta_header *)bh->b_data; struct gfs2_meta_header *mh = (struct gfs2_meta_header *)bh->b_data;
u32 magic = be32_to_cpu(mh->mh_magic); u32 magic = be32_to_cpu(mh->mh_magic);
if (unlikely(magic != GFS2_MAGIC)) { if (unlikely(magic != GFS2_MAGIC)) {
printk(KERN_ERR "GFS2: Magic number missing at %llu\n", pr_err("Magic number missing at %llu\n",
(unsigned long long)bh->b_blocknr); (unsigned long long)bh->b_blocknr);
return -EIO; return -EIO;
} }
...@@ -164,7 +165,7 @@ static inline unsigned int gfs2_tune_get_i(struct gfs2_tune *gt, ...@@ -164,7 +165,7 @@ static inline unsigned int gfs2_tune_get_i(struct gfs2_tune *gt,
#define gfs2_tune_get(sdp, field) \ #define gfs2_tune_get(sdp, field) \
gfs2_tune_get_i(&(sdp)->sd_tune, &(sdp)->sd_tune.field) gfs2_tune_get_i(&(sdp)->sd_tune, &(sdp)->sd_tune.field)
int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...); __printf(2, 3)
int gfs2_lm_withdraw(struct gfs2_sbd *sdp, const char *fmt, ...);
#endif /* __UTIL_DOT_H__ */ #endif /* __UTIL_DOT_H__ */
...@@ -723,7 +723,7 @@ posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl, ...@@ -723,7 +723,7 @@ posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
void *buffer, size_t size) void *buffer, size_t size)
{ {
posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer; posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer;
posix_acl_xattr_entry *ext_entry = ext_acl->a_entries; posix_acl_xattr_entry *ext_entry;
int real_size, n; int real_size, n;
real_size = posix_acl_xattr_size(acl->a_count); real_size = posix_acl_xattr_size(acl->a_count);
...@@ -731,7 +731,8 @@ posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl, ...@@ -731,7 +731,8 @@ posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
return real_size; return real_size;
if (real_size > size) if (real_size > size)
return -ERANGE; return -ERANGE;
ext_entry = ext_acl->a_entries;
ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION); ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
for (n=0; n < acl->a_count; n++, ext_entry++) { for (n=0; n < acl->a_count; n++, ext_entry++) {
......
...@@ -304,7 +304,13 @@ struct gfs2_dirent { ...@@ -304,7 +304,13 @@ struct gfs2_dirent {
__be16 de_rec_len; __be16 de_rec_len;
__be16 de_name_len; __be16 de_name_len;
__be16 de_type; __be16 de_type;
__u8 __pad[14]; union {
__u8 __pad[14];
struct {
__be16 de_rahead;
__u8 pad2[12];
};
};
}; };
/* /*
...@@ -347,9 +353,9 @@ struct gfs2_leaf { ...@@ -347,9 +353,9 @@ struct gfs2_leaf {
* metadata header. Each inode, if it has extended attributes, will * metadata header. Each inode, if it has extended attributes, will
* have either a single block containing the extended attribute headers * have either a single block containing the extended attribute headers
* or a single indirect block pointing to blocks containing the * or a single indirect block pointing to blocks containing the
* extended attribure headers. * extended attribute headers.
* *
* The maximim size of the data part of an extended attribute is 64k * The maximum size of the data part of an extended attribute is 64k
* so the number of blocks required depends upon block size. Since the * so the number of blocks required depends upon block size. Since the
* block size also determines the number of pointers in an indirect * block size also determines the number of pointers in an indirect
* block, its a fairly complicated calculation to work out the maximum * block, its a fairly complicated calculation to work out the maximum
......
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