Commit 1e43938b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gfs2-4.18.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2

Pull gfs2 updates from Bob Peterson:
 "We've got nine more patches for this merge window.

   - remove sd_jheightsize to greatly simplify some code (Andreas
     Gruenbacher)

   - fix some comments (Andreas)

   - fix a glock recursion bug when allocation errors occur (Andreas)

   - improve the hole_size function so it returns the entire hole rather
     than figuring it out piecemeal (Andreas)

   - clean up gfs2_stuffed_write_end to remove a lot of redundancy
     (Andreas)

   - clarify code with regard to the way ordered writes are processed
     (Andreas)

   - a bunch of improvements and cleanups of the iomap code to pave the
     way for iomap writes, which is a future patch set (Andreas)

   - fix a bug where block reservations can run off the end of a bitmap
     (Bob Peterson)

   - add Andreas to the MAINTAINERS file (Bob Peterson)"

* tag 'gfs2-4.18.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  MAINTAINERS: Add Andreas Gruenbacher as a maintainer for gfs2
  gfs2: Iomap cleanups and improvements
  gfs2: Remove ordered write mode handling from gfs2_trans_add_data
  gfs2: gfs2_stuffed_write_end cleanup
  gfs2: hole_size improvement
  GFS2: gfs2_free_extlen can return an extent that is too long
  GFS2: Fix allocation error bug with recursive rgrp glocking
  gfs2: Update find_metapath comment
  gfs2: Remove sdp->sd_jheightsize
parents 8a463114 6d1c2cf2
...@@ -5950,8 +5950,8 @@ S: Maintained ...@@ -5950,8 +5950,8 @@ S: Maintained
F: scripts/get_maintainer.pl F: scripts/get_maintainer.pl
GFS2 FILE SYSTEM GFS2 FILE SYSTEM
M: Steven Whitehouse <swhiteho@redhat.com>
M: Bob Peterson <rpeterso@redhat.com> M: Bob Peterson <rpeterso@redhat.com>
M: Andreas Gruenbacher <agruenba@redhat.com>
L: cluster-devel@redhat.com L: cluster-devel@redhat.com
W: http://sources.redhat.com/cluster/ W: http://sources.redhat.com/cluster/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git
......
...@@ -54,8 +54,7 @@ static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page, ...@@ -54,8 +54,7 @@ static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
continue; continue;
if (start >= to) if (start >= to)
break; break;
if (gfs2_is_jdata(ip)) set_buffer_uptodate(bh);
set_buffer_uptodate(bh);
gfs2_trans_add_data(ip->i_gl, bh); gfs2_trans_add_data(ip->i_gl, bh);
} }
} }
...@@ -747,18 +746,21 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, ...@@ -747,18 +746,21 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
put_page(page); put_page(page);
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
if (pos + len > ip->i_inode.i_size) if (alloc_required) {
gfs2_trim_blocks(&ip->i_inode); gfs2_inplace_release(ip);
goto out_trans_fail; if (pos + len > ip->i_inode.i_size)
gfs2_trim_blocks(&ip->i_inode);
}
goto out_qunlock;
out_endtrans: out_endtrans:
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
out_trans_fail: out_trans_fail:
if (alloc_required) { if (alloc_required)
gfs2_inplace_release(ip); gfs2_inplace_release(ip);
out_qunlock: out_qunlock:
if (alloc_required)
gfs2_quota_unlock(ip); gfs2_quota_unlock(ip);
}
out_unlock: out_unlock:
if (&ip->i_inode == sdp->sd_rindex) { if (&ip->i_inode == sdp->sd_rindex) {
gfs2_glock_dq(&m_ip->i_gh); gfs2_glock_dq(&m_ip->i_gh);
...@@ -814,7 +816,6 @@ static void adjust_fs_space(struct inode *inode) ...@@ -814,7 +816,6 @@ static void adjust_fs_space(struct inode *inode)
* @inode: The inode * @inode: The inode
* @dibh: The buffer_head containing the on-disk inode * @dibh: The buffer_head containing the on-disk inode
* @pos: The file position * @pos: The file position
* @len: The length of the write
* @copied: How much was actually copied by the VFS * @copied: How much was actually copied by the VFS
* @page: The page * @page: The page
* *
...@@ -824,17 +825,15 @@ static void adjust_fs_space(struct inode *inode) ...@@ -824,17 +825,15 @@ static void adjust_fs_space(struct inode *inode)
* Returns: errno * Returns: errno
*/ */
static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh, static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
loff_t pos, unsigned len, unsigned copied, loff_t pos, unsigned copied,
struct page *page) struct page *page)
{ {
struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
u64 to = pos + copied; u64 to = pos + copied;
void *kaddr; void *kaddr;
unsigned char *buf = dibh->b_data + sizeof(struct gfs2_dinode); unsigned char *buf = dibh->b_data + sizeof(struct gfs2_dinode);
BUG_ON(pos + len > gfs2_max_stuffed_size(ip)); BUG_ON(pos + copied > gfs2_max_stuffed_size(ip));
kaddr = kmap_atomic(page); kaddr = kmap_atomic(page);
memcpy(buf + pos, kaddr + pos, copied); memcpy(buf + pos, kaddr + pos, copied);
...@@ -850,20 +849,6 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh, ...@@ -850,20 +849,6 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
i_size_write(inode, to); i_size_write(inode, to);
mark_inode_dirty(inode); mark_inode_dirty(inode);
} }
if (inode == sdp->sd_rindex) {
adjust_fs_space(inode);
sdp->sd_rindex_uptodate = 0;
}
brelse(dibh);
gfs2_trans_end(sdp);
if (inode == sdp->sd_rindex) {
gfs2_glock_dq(&m_ip->i_gh);
gfs2_holder_uninit(&m_ip->i_gh);
}
gfs2_glock_dq(&ip->i_gh);
gfs2_holder_uninit(&ip->i_gh);
return copied; return copied;
} }
...@@ -877,9 +862,8 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh, ...@@ -877,9 +862,8 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
* @page: The page that has been written * @page: The page that has been written
* @fsdata: The fsdata (unused in GFS2) * @fsdata: The fsdata (unused in GFS2)
* *
* The main write_end function for GFS2. We have a separate one for * The main write_end function for GFS2. We just put our locking around the VFS
* stuffed files as they are slightly different, otherwise we just * provided functions.
* put our locking around the VFS provided functions.
* *
* Returns: errno * Returns: errno
*/ */
...@@ -900,32 +884,39 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, ...@@ -900,32 +884,39 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == NULL); BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == NULL);
ret = gfs2_meta_inode_buffer(ip, &dibh); ret = gfs2_meta_inode_buffer(ip, &dibh);
if (unlikely(ret)) { if (unlikely(ret))
unlock_page(page); goto out;
put_page(page);
goto failed;
}
if (gfs2_is_stuffed(ip)) if (gfs2_is_stuffed(ip)) {
return gfs2_stuffed_write_end(inode, dibh, pos, len, copied, page); ret = gfs2_stuffed_write_end(inode, dibh, pos, copied, page);
page = NULL;
goto out2;
}
if (!gfs2_is_writeback(ip)) if (gfs2_is_jdata(ip))
gfs2_page_add_databufs(ip, page, pos & ~PAGE_MASK, len); gfs2_page_add_databufs(ip, page, pos & ~PAGE_MASK, len);
else
gfs2_ordered_add_inode(ip);
ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata); ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
page = NULL;
if (tr->tr_num_buf_new) if (tr->tr_num_buf_new)
__mark_inode_dirty(inode, I_DIRTY_DATASYNC); __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
else else
gfs2_trans_add_meta(ip->i_gl, dibh); gfs2_trans_add_meta(ip->i_gl, dibh);
out2:
if (inode == sdp->sd_rindex) { if (inode == sdp->sd_rindex) {
adjust_fs_space(inode); adjust_fs_space(inode);
sdp->sd_rindex_uptodate = 0; sdp->sd_rindex_uptodate = 0;
} }
brelse(dibh); brelse(dibh);
failed: out:
if (page) {
unlock_page(page);
put_page(page);
}
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
gfs2_inplace_release(ip); gfs2_inplace_release(ip);
if (ip->i_qadata && ip->i_qadata->qa_qd_num) if (ip->i_qadata && ip->i_qadata->qa_qd_num)
......
This diff is collapsed.
...@@ -46,11 +46,13 @@ static inline void gfs2_write_calc_reserv(const struct gfs2_inode *ip, ...@@ -46,11 +46,13 @@ static inline void gfs2_write_calc_reserv(const struct gfs2_inode *ip,
} }
} }
extern const struct iomap_ops gfs2_iomap_ops;
extern int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page); extern int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page);
extern int gfs2_block_map(struct inode *inode, sector_t lblock, extern int gfs2_block_map(struct inode *inode, sector_t lblock,
struct buffer_head *bh, int create); struct buffer_head *bh, int create);
extern int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length, extern int gfs2_iomap_get_alloc(struct inode *inode, loff_t pos, loff_t length,
unsigned flags, struct iomap *iomap); struct iomap *iomap);
extern int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, extern int gfs2_extent_map(struct inode *inode, u64 lblock, int *new,
u64 *dblock, unsigned *extlen); u64 *dblock, unsigned *extlen);
extern int gfs2_setattr_size(struct inode *inode, u64 size); extern int gfs2_setattr_size(struct inode *inode, u64 size);
......
...@@ -733,7 +733,7 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len, ...@@ -733,7 +733,7 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_inode *ip = GFS2_I(inode);
loff_t end = offset + len; loff_t end = offset + len;
struct buffer_head *dibh; struct buffer_head *dibh;
struct iomap iomap; struct iomap iomap = { };
int error; int error;
error = gfs2_meta_inode_buffer(ip, &dibh); error = gfs2_meta_inode_buffer(ip, &dibh);
...@@ -749,8 +749,8 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len, ...@@ -749,8 +749,8 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
} }
while (offset < end) { while (offset < end) {
error = gfs2_iomap_begin(inode, offset, end - offset, error = gfs2_iomap_get_alloc(inode, offset, end - offset,
IOMAP_WRITE, &iomap); &iomap);
if (error) if (error)
goto out; goto out;
offset = iomap.offset + iomap.length; offset = iomap.offset + iomap.length;
......
...@@ -116,6 +116,7 @@ static inline struct gfs2_bitmap *rbm_bi(const struct gfs2_rbm *rbm) ...@@ -116,6 +116,7 @@ static inline struct gfs2_bitmap *rbm_bi(const struct gfs2_rbm *rbm)
static inline u64 gfs2_rbm_to_block(const struct gfs2_rbm *rbm) static inline u64 gfs2_rbm_to_block(const struct gfs2_rbm *rbm)
{ {
BUG_ON(rbm->offset >= rbm->rgd->rd_data);
return rbm->rgd->rd_data0 + (rbm_bi(rbm)->bi_start * GFS2_NBBY) + return rbm->rgd->rd_data0 + (rbm_bi(rbm)->bi_start * GFS2_NBBY) +
rbm->offset; rbm->offset;
} }
...@@ -696,8 +697,6 @@ struct gfs2_sbd { ...@@ -696,8 +697,6 @@ struct gfs2_sbd {
u32 sd_max_dirres; /* Max blocks needed to add a directory entry */ u32 sd_max_dirres; /* Max blocks needed to add a directory entry */
u32 sd_max_height; /* Max height of a file's metadata tree */ u32 sd_max_height; /* Max height of a file's metadata tree */
u64 sd_heightsize[GFS2_MAX_META_HEIGHT + 1]; u64 sd_heightsize[GFS2_MAX_META_HEIGHT + 1];
u32 sd_max_jheight; /* Max height of journaled file's meta tree */
u64 sd_jheightsize[GFS2_MAX_META_HEIGHT + 1];
u32 sd_max_dents_per_leaf; /* Max number of dirents in a leaf block */ u32 sd_max_dents_per_leaf; /* Max number of dirents in a leaf block */
struct gfs2_args sd_args; /* Mount arguments */ struct gfs2_args sd_args; /* Mount arguments */
......
...@@ -2006,10 +2006,6 @@ static int gfs2_getattr(const struct path *path, struct kstat *stat, ...@@ -2006,10 +2006,6 @@ static int gfs2_getattr(const struct path *path, struct kstat *stat,
return 0; return 0;
} }
const struct iomap_ops gfs2_iomap_ops = {
.iomap_begin = gfs2_iomap_begin,
};
static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 start, u64 len) u64 start, u64 len)
{ {
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include "incore.h" #include "incore.h"
#include "inode.h"
/** /**
* gfs2_log_lock - acquire the right to mess with the log manager * gfs2_log_lock - acquire the right to mess with the log manager
...@@ -50,8 +51,12 @@ static inline void gfs2_log_pointers_init(struct gfs2_sbd *sdp, ...@@ -50,8 +51,12 @@ static inline void gfs2_log_pointers_init(struct gfs2_sbd *sdp,
static inline void gfs2_ordered_add_inode(struct gfs2_inode *ip) static inline void gfs2_ordered_add_inode(struct gfs2_inode *ip)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp;
if (!gfs2_is_ordered(ip))
return;
sdp = GFS2_SB(&ip->i_inode);
if (!test_bit(GIF_ORDERED, &ip->i_flags)) { if (!test_bit(GIF_ORDERED, &ip->i_flags)) {
spin_lock(&sdp->sd_ordered_lock); spin_lock(&sdp->sd_ordered_lock);
if (!test_and_set_bit(GIF_ORDERED, &ip->i_flags)) if (!test_and_set_bit(GIF_ORDERED, &ip->i_flags))
......
...@@ -335,25 +335,6 @@ static int gfs2_read_sb(struct gfs2_sbd *sdp, int silent) ...@@ -335,25 +335,6 @@ static int gfs2_read_sb(struct gfs2_sbd *sdp, int silent)
sdp->sd_heightsize[x] = ~0; sdp->sd_heightsize[x] = ~0;
gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT); gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT);
sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize -
sizeof(struct gfs2_dinode);
sdp->sd_jheightsize[1] = sdp->sd_jbsize * sdp->sd_diptrs;
for (x = 2;; x++) {
u64 space, d;
u32 m;
space = sdp->sd_jheightsize[x - 1] * sdp->sd_inptrs;
d = space;
m = do_div(d, sdp->sd_inptrs);
if (d != sdp->sd_jheightsize[x - 1] || m)
break;
sdp->sd_jheightsize[x] = space;
}
sdp->sd_max_jheight = x;
sdp->sd_jheightsize[x] = ~0;
gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT);
sdp->sd_max_dents_per_leaf = (sdp->sd_sb.sb_bsize - sdp->sd_max_dents_per_leaf = (sdp->sd_sb.sb_bsize -
sizeof(struct gfs2_leaf)) / sizeof(struct gfs2_leaf)) /
GFS2_MIN_DIRENT_SIZE; GFS2_MIN_DIRENT_SIZE;
......
...@@ -735,7 +735,10 @@ static int gfs2_write_buf_to_page(struct gfs2_inode *ip, unsigned long index, ...@@ -735,7 +735,10 @@ static int gfs2_write_buf_to_page(struct gfs2_inode *ip, unsigned long index,
if (!buffer_uptodate(bh)) if (!buffer_uptodate(bh))
goto unlock_out; goto unlock_out;
} }
gfs2_trans_add_data(ip->i_gl, bh); if (gfs2_is_jdata(ip))
gfs2_trans_add_data(ip->i_gl, bh);
else
gfs2_ordered_add_inode(ip);
/* If we need to write to the next block as well */ /* If we need to write to the next block as well */
if (to_write > (bsize - boff)) { if (to_write > (bsize - boff)) {
......
...@@ -372,8 +372,8 @@ static u32 gfs2_free_extlen(const struct gfs2_rbm *rrbm, u32 len) ...@@ -372,8 +372,8 @@ static u32 gfs2_free_extlen(const struct gfs2_rbm *rrbm, u32 len)
start = bi->bi_bh->b_data; start = bi->bi_bh->b_data;
if (bi->bi_clone) if (bi->bi_clone)
start = bi->bi_clone; start = bi->bi_clone;
end = start + bi->bi_bh->b_size;
start += bi->bi_offset; start += bi->bi_offset;
end = start + bi->bi_len;
BUG_ON(rbm.offset & 3); BUG_ON(rbm.offset & 3);
start += (rbm.offset / GFS2_NBBY); start += (rbm.offset / GFS2_NBBY);
bytes = min_t(u32, len / GFS2_NBBY, (end - start)); bytes = min_t(u32, len / GFS2_NBBY, (end - start));
......
...@@ -143,32 +143,21 @@ static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl, ...@@ -143,32 +143,21 @@ static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl,
* @gl: The inode glock associated with the buffer * @gl: The inode glock associated with the buffer
* @bh: The buffer to add * @bh: The buffer to add
* *
* This is used in two distinct cases: * This is used in journaled data mode.
* i) In ordered write mode * We need to journal the data block in the same way as metadata in
* We put the data buffer on a list so that we can ensure that it's * the functions above. The difference is that here we have a tag
* synced to disk at the right time * which is two __be64's being the block number (as per meta data)
* ii) In journaled data mode * and a flag which says whether the data block needs escaping or
* We need to journal the data block in the same way as metadata in * not. This means we need a new log entry for each 251 or so data
* the functions above. The difference is that here we have a tag * blocks, which isn't an enormous overhead but twice as much as
* which is two __be64's being the block number (as per meta data) * for normal metadata blocks.
* and a flag which says whether the data block needs escaping or
* not. This means we need a new log entry for each 251 or so data
* blocks, which isn't an enormous overhead but twice as much as
* for normal metadata blocks.
*/ */
void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh) void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh)
{ {
struct gfs2_trans *tr = current->journal_info; struct gfs2_trans *tr = current->journal_info;
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
struct address_space *mapping = bh->b_page->mapping;
struct gfs2_inode *ip = GFS2_I(mapping->host);
struct gfs2_bufdata *bd; struct gfs2_bufdata *bd;
if (!gfs2_is_jdata(ip)) {
gfs2_ordered_add_inode(ip);
return;
}
lock_buffer(bh); lock_buffer(bh);
if (buffer_pinned(bh)) { if (buffer_pinned(bh)) {
set_bit(TR_TOUCHED, &tr->tr_flags); set_bit(TR_TOUCHED, &tr->tr_flags);
......
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