* [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window)
@ 2015-04-13 15:10 Bob Peterson
0 siblings, 0 replies; 14+ messages in thread
From: Bob Peterson @ 2015-04-13 15:10 UTC (permalink / raw)
To: cluster-devel.redhat.com
Hi,
Here is a list of patches we've accumulated for GFS2 for the current upstream
merge window. Most of the patches fix GFS2 quotas, which were not properly
enforced. There's another that adds me as a GFS2 co-maintainer, and a
couple patches that fix a kernel panic doing splice_write on GFS2 as well
as a few correctness patches.
Regards,
Bob Peterson
Red Hat File Systems
----------------------------------------------------------------
Abhi Das (4):
gfs2: perform quota checks against allocation parameters
gfs2: allow quota_check and inplace_reserve to return available blocks
gfs2: allow fallocate to max out quotas/fs efficiently
gfs2: fix quota refresh race in do_glock()
Andreas Gruenbacher (1):
GFS2: gfs2_set_acl(): Cache "no acl" as well
Bob Peterson (3):
Add myself (Bob Peterson) as a maintainer of GFS2
GFS2: Allocate reservation during splice_write
GFS2: Move gfs2_file_splice_write outside of #ifdef
Chengyu Song (1):
gfs2: incorrect check for debugfs returns
MAINTAINERS | 4 +--
fs/gfs2/acl.c | 6 +---
fs/gfs2/aops.c | 6 ++--
fs/gfs2/bmap.c | 2 +-
fs/gfs2/file.c | 101 ++++++++++++++++++++++++++++++++++++++-----------------
fs/gfs2/glock.c | 47 +++++++++++++++-----------
fs/gfs2/incore.h | 4 ++-
fs/gfs2/inode.c | 18 +++++-----
fs/gfs2/quota.c | 62 ++++++++++++++++++++++++----------
fs/gfs2/quota.h | 8 +++--
fs/gfs2/rgrp.c | 20 ++++++++---
fs/gfs2/rgrp.h | 3 +-
fs/gfs2/xattr.c | 2 +-
13 files changed, 186 insertions(+), 97 deletions(-)
--
1.9.3
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window)
@ 2016-05-20 16:22 Bob Peterson
0 siblings, 0 replies; 14+ messages in thread
From: Bob Peterson @ 2016-05-20 16:22 UTC (permalink / raw)
To: cluster-devel.redhat.com
Hi,
We've got nine patches this time:
- Abhi Das has two patches that fix a GFS2 splice issue (and an adjustment).
- Ben Marzinski has a patch which allows the proper unmount of a GFS2
file system after hitting a withdraw error.
- I have a patch to fix a problem where GFS2 would dereference an error
value, plus three cosmetic / refactoring patches.
- Daniel DeFreez has a patch to fix two glock reference count problems,
where GFS2 was not properly "uninitializing" its glock holder on error
paths.
- Denys Vlasenko has a patch to change a function to not be inlined,
thus reducing the memory footprint of the GFS2 module.
Regards,
Bob Peterson
---
Abhi Das (2):
gfs2: Use gfs2 wrapper to sync inode before calling
generic_file_splice_read()
gfs2: use inode_lock/unlock instead of accessing i_mutex directly
Benjamin Marzinski (1):
GFS2: ignore unlock failures after withdraw
Bob Peterson (4):
GFS2: Get rid of dead code in inode_go_demote_ok
GFS2: Don't dereference inode in gfs2_inode_lookup until it's valid
GFS2: Remove allocation parms from gfs2_rbm_find
GFS2: Refactor gfs2_remove_from_journal
Daniel DeFreez (1):
GFS2: Add calls to gfs2_holder_uninit in two error handlers
Denys Vlasenko (1):
GFS2: fs/gfs2/glock.c: Deinline do_error, save 1856 bytes
fs/gfs2/aops.c | 5 +++--
fs/gfs2/file.c | 31 ++++++++++++++++++++++++++++---
fs/gfs2/glock.c | 11 +++++++++--
fs/gfs2/glops.c | 7 -------
fs/gfs2/inode.c | 6 +++---
fs/gfs2/meta_io.c | 7 ++++---
fs/gfs2/meta_io.h | 8 ++++++--
fs/gfs2/rgrp.c | 16 ++++++----------
fs/gfs2/util.c | 1 +
9 files changed, 60 insertions(+), 32 deletions(-)
--
2.5.5
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window)
@ 2017-05-03 13:45 Bob Peterson
0 siblings, 0 replies; 14+ messages in thread
From: Bob Peterson @ 2017-05-03 13:45 UTC (permalink / raw)
To: cluster-devel.redhat.com
Hi,
We've got nine GFS2 patches for this merge window.
1. Andreas Gruenbacher wrote a patch to replace the deprecated
call to rhashtable_walk_init with rhashtable_walk_enter.
2. Andreas also wrote a patch to eliminate redundant code in
two of our debugfs sequence files.
3. Andreas also cleaned up the rhashtable key ugliness Linus
pointed out during this cycle, following Linus's suggestions.
4. Andreas also wrote a patch to take advantage of his new
function rhashtable_lookup_get_insert_fast. This makes glock
lookup faster and more bullet-proof.
5. Andreas also wrote a patch to revert a patch in the evict
path that caused occasional deadlocks, and is no longer
needed.
6. Andrew Price wrote a patch to re-enable fallocate for the
rindex system file to enable gfs2_grow to grow properly on
secondary file system grow operations.
7. I wrote a patch to initialize an inode number field to make
certain kernel trace points more understandable.
8. I also wrote a patch that makes GFS2 file system "withdraw"
work more like it should by ignoring operations after a
withdraw that would formerly cause a BUG() and kernel panic.
9. I also reworked the entire truncate/delete algorithm,
scrapping the old recursive algorithm in favor of a new
non-recursive algorithm. This was done for performance:
This way, GFS2 no longer needs to lock multiple resource
groups while doing truncates and deletes of files that cross
multiple resource group boundaries, allowing for better
parallelism. It also solves a problem whereby deleting large
files would request a large chunk of kernel memory, which
resulted in a get_page_from_freelist warning.
Regards,
Bob Peterson
---
Andreas Gruenbacher (5):
gfs2: Replace rhashtable_walk_init with rhashtable_walk_enter
gfs2: Deduplicate gfs2_{glocks,glstats}_open
gfs2: Don't pack struct lm_lockname
gfs2: Switch to rhashtable_lookup_get_insert_fast
Revert "GFS2: Wait for iopen glock dequeues"
Andrew Price (1):
gfs2: Re-enable fallocate for the rindex
Bob Peterson (3):
GFS2: Prevent BUG from occurring when normal Withdraws occur
GFS2: Temporarily zero i_no_addr when creating a dinode
GFS2: Non-recursive delete
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window)
@ 2018-04-02 15:44 Bob Peterson
0 siblings, 0 replies; 14+ messages in thread
From: Bob Peterson @ 2018-04-02 15:44 UTC (permalink / raw)
To: cluster-devel.redhat.com
Hi,
We've only got 9 GFS2 patches for this merge window:
1. Abhi Das contributed a patch to report journal recovery times more
accurately during journal replay.
2. Andreas Gruenbacher contributed a patch to fix fallocate chunk size.
3. Andreas added a patch to correctly dirty inodes during rename.
4. Andreas added a patch to improve the comment for function gfs2_block_map.
5. Andreas added a patch to improve kernel trace point iomap end:
The physical block address was added.
6. Andreas added a patch to fix a nasty file system corruption bug that
surfaced in xfstests 476 in punch-hole/truncate.
7. Andreas fixed a problem Christoph Helwig pointed out, namely, that GFS2
was misusing the IOMAP_ZERO flag. The zeroing of new blocks was moved
to the proper fallocate code.
8. I contributed a patch to declare function gfs2_remove_from_ail as static.
9. I added a patch to only set PageChecked for jdata page writes.
Regards,
Bob Peterson
---
Abhi Das (1):
gfs2: time journal recovery steps accurately
Andreas Gruenbacher (6):
gfs2: Fix fallocate chunk size
gfs2: Dirty source inode during rename
gfs2: Improve gfs2_block_map comment
gfs2: gfs2_iomap_end tracepoint: log block address
gfs2: Check for the end of metadata in punch_hole
gfs2: Zero out fallocated blocks in fallocate_chunk
Bob Peterson (2):
GFS2: Make function gfs2_remove_from_ail static
GFS2: Only set PageChecked for jdata pages
fs/gfs2/aops.c | 8 ++++----
fs/gfs2/bmap.c | 38 ++++++++++++++++++++------------------
fs/gfs2/dir.c | 13 ++-----------
fs/gfs2/file.c | 34 +++++++++++++++++-----------------
fs/gfs2/incore.h | 3 ---
fs/gfs2/inode.c | 10 +---------
fs/gfs2/log.c | 2 +-
fs/gfs2/log.h | 1 -
fs/gfs2/quota.h | 2 ++
fs/gfs2/recovery.c | 20 ++++++++++++++------
fs/gfs2/trace_gfs2.h | 9 +++++++--
11 files changed, 68 insertions(+), 72 deletions(-)
--
2.14.3
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window)
@ 2018-06-04 16:29 Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 1/9] gfs2: Remove sdp->sd_jheightsize Bob Peterson
` (8 more replies)
0 siblings, 9 replies; 14+ messages in thread
From: Bob Peterson @ 2018-06-04 16:29 UTC (permalink / raw)
To: cluster-devel.redhat.com
Hi,
We've got 9 more patches for this merge window.
1. Andreas Gruenbacher contributed a patch to remove sd_jheightsize to
greatly simplify some code.
2. Andreas fixed some comments.
3. Andreas fixed a glock recursion bug when allocation errors occur.
4. Andreas improved the hole_size function so it returns the entire hole
rather than figuring it out piecemeal.
5. Andreas cleaned up gfs2_stuffed_write_end to remove a lot of redundancy.
6. Andreas clarified code with regard to the way ordered writes are processed.
7. Andreas did a bunch of improvements and cleanups of the iomap code to
pave the way for iomap writes, which is a future patch set.
8. I fixed a bug where block reservations can run off the end of a bitmap.
9. I added Andreas to the MAINTAINERS file.
Regards,
Bob Peterson
---
Andreas Gruenbacher (7):
gfs2: Remove sdp->sd_jheightsize
gfs2: Update find_metapath comment
GFS2: Fix allocation error bug with recursive rgrp glocking
gfs2: hole_size improvement
gfs2: gfs2_stuffed_write_end cleanup
gfs2: Remove ordered write mode handling from gfs2_trans_add_data
gfs2: Iomap cleanups and improvements
Bob Peterson (2):
GFS2: gfs2_free_extlen can return an extent that is too long
MAINTAINERS: Add Andreas Gruenbacher as a maintainer for gfs2
MAINTAINERS | 2 +-
fs/gfs2/aops.c | 69 +++----
fs/gfs2/bmap.c | 428 +++++++++++++++++++++++++++----------------
fs/gfs2/bmap.h | 6 +-
fs/gfs2/file.c | 6 +-
fs/gfs2/incore.h | 3 +-
fs/gfs2/inode.c | 4 -
fs/gfs2/log.h | 7 +-
fs/gfs2/ops_fstype.c | 19 --
fs/gfs2/quota.c | 5 +-
fs/gfs2/rgrp.c | 2 +-
fs/gfs2/trans.c | 27 +--
12 files changed, 332 insertions(+), 246 deletions(-)
--
2.17.1
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Cluster-devel] [PATCH 1/9] gfs2: Remove sdp->sd_jheightsize
2018-06-04 16:29 [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window) Bob Peterson
@ 2018-06-04 16:29 ` Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 2/9] gfs2: Update find_metapath comment Bob Peterson
` (7 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Bob Peterson @ 2018-06-04 16:29 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Andreas Gruenbacher <agruenba@redhat.com>
GFS2 keeps two arrarys in the superblock that define the maximum size of
an inode depending on the inode's height: sdp->sd_heightsize defines the
heights in units of sb->s_blocksize; sdp->sd_jheightsize defines them in
units of sb->s_blocksize - sizeof(struct gfs2_meta_header). These
arrays are used to determine when additional layers of indirect blocks
are needed. The second array is used for directories which have an
additional gfs2_meta_header at the beginning of each block.
Distinguishing between these two cases makes no sense: the height
required for representing N blocks will come out the same no matter if
the calculation is done in gross (sb->s_blocksize) or net
(sb->s_blocksize - sizeof(struct gfs2_meta_header)) units.
Stuffed directories don't have an additional gfs2_meta_header, but the
stuffed case is handled separately for both files and directories,
anyway.
Remove the unncessary sdp->sd_jheightsize array.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/bmap.c | 14 +-------------
fs/gfs2/incore.h | 2 --
fs/gfs2/ops_fstype.c | 19 -------------------
3 files changed, 1 insertion(+), 34 deletions(-)
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 278ed0869c3c..0590e93494f7 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -700,8 +700,6 @@ int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
struct metapath mp = { .mp_aheight = 1, };
- unsigned int factor = sdp->sd_sb.sb_bsize;
- const u64 *arr = sdp->sd_heightsize;
__be64 *ptr;
sector_t lblock;
sector_t lend;
@@ -737,22 +735,12 @@ int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
iomap->flags = IOMAP_F_MERGED;
bmap_lock(ip, flags & IOMAP_WRITE);
- /*
- * Directory data blocks have a struct gfs2_meta_header header, so the
- * remaining size is smaller than the filesystem block size. Logical
- * block numbers for directories are in units of this remaining size!
- */
- if (gfs2_is_dir(ip)) {
- factor = sdp->sd_jbsize;
- arr = sdp->sd_jheightsize;
- }
-
ret = gfs2_meta_inode_buffer(ip, &mp.mp_bh[0]);
if (ret)
goto out_release;
height = ip->i_height;
- while ((lblock + 1) * factor > arr[height])
+ while ((lblock + 1) * sdp->sd_sb.sb_bsize > sdp->sd_heightsize[height])
height++;
find_metapath(sdp, lblock, &mp, height);
if (height > ip->i_height || gfs2_is_stuffed(ip))
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 1b6b1e3f5caf..0bbbaa9b05cb 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -696,8 +696,6 @@ struct gfs2_sbd {
u32 sd_max_dirres; /* Max blocks needed to add a directory entry */
u32 sd_max_height; /* Max height of a file's metadata tree */
u64 sd_heightsize[GFS2_MAX_META_HEIGHT + 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 */
struct gfs2_args sd_args; /* Mount arguments */
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 3ba3f167641c..c2469833b4fb 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -335,25 +335,6 @@ static int gfs2_read_sb(struct gfs2_sbd *sdp, int silent)
sdp->sd_heightsize[x] = ~0;
gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT);
- sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize -
- 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 -
sizeof(struct gfs2_leaf)) /
GFS2_MIN_DIRENT_SIZE;
--
2.17.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Cluster-devel] [PATCH 2/9] gfs2: Update find_metapath comment
2018-06-04 16:29 [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window) Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 1/9] gfs2: Remove sdp->sd_jheightsize Bob Peterson
@ 2018-06-04 16:29 ` Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 3/9] GFS2: Fix allocation error bug with recursive rgrp glocking Bob Peterson
` (6 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Bob Peterson @ 2018-06-04 16:29 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/bmap.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 0590e93494f7..fcf2f7d166de 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -176,8 +176,8 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
/**
* find_metapath - Find path through the metadata tree
* @sdp: The superblock
- * @mp: The metapath to return the result in
* @block: The disk block to look up
+ * @mp: The metapath to return the result in
* @height: The pre-calculated height of the metadata tree
*
* This routine returns a struct metapath structure that defines a path
@@ -188,8 +188,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
* filesystem with a blocksize of 4096.
*
* find_metapath() would return a struct metapath structure set to:
- * mp_offset = 101342453, mp_height = 3, mp_list[0] = 0, mp_list[1] = 48,
- * and mp_list[2] = 165.
+ * mp_fheight = 3, mp_list[0] = 0, mp_list[1] = 48, and mp_list[2] = 165.
*
* That means that in order to get to the block containing the byte at
* offset 101342453, we would load the indirect block pointed to by pointer
--
2.17.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Cluster-devel] [PATCH 3/9] GFS2: Fix allocation error bug with recursive rgrp glocking
2018-06-04 16:29 [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window) Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 1/9] gfs2: Remove sdp->sd_jheightsize Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 2/9] gfs2: Update find_metapath comment Bob Peterson
@ 2018-06-04 16:29 ` Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 4/9] GFS2: gfs2_free_extlen can return an extent that is too long Bob Peterson
` (5 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Bob Peterson @ 2018-06-04 16:29 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Andreas Gruenbacher <agruenba@redhat.com>
Before this patch function gfs2_write_begin, upon discovering an
error, called gfs2_trim_blocks while the rgrp glock was still held.
That's because gfs2_inplace_release is not called until later.
This patch reorganizes the logic a bit so gfs2_inplace_release
is called to release the lock prior to the call to gfs2_trim_blocks,
thus preventing the glock recursion.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/aops.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index f58716567972..66e7172e0134 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -747,18 +747,21 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
put_page(page);
gfs2_trans_end(sdp);
- if (pos + len > ip->i_inode.i_size)
- gfs2_trim_blocks(&ip->i_inode);
- goto out_trans_fail;
+ if (alloc_required) {
+ gfs2_inplace_release(ip);
+ if (pos + len > ip->i_inode.i_size)
+ gfs2_trim_blocks(&ip->i_inode);
+ }
+ goto out_qunlock;
out_endtrans:
gfs2_trans_end(sdp);
out_trans_fail:
- if (alloc_required) {
+ if (alloc_required)
gfs2_inplace_release(ip);
out_qunlock:
+ if (alloc_required)
gfs2_quota_unlock(ip);
- }
out_unlock:
if (&ip->i_inode == sdp->sd_rindex) {
gfs2_glock_dq(&m_ip->i_gh);
--
2.17.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Cluster-devel] [PATCH 4/9] GFS2: gfs2_free_extlen can return an extent that is too long
2018-06-04 16:29 [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window) Bob Peterson
` (2 preceding siblings ...)
2018-06-04 16:29 ` [Cluster-devel] [PATCH 3/9] GFS2: Fix allocation error bug with recursive rgrp glocking Bob Peterson
@ 2018-06-04 16:29 ` Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 5/9] gfs2: hole_size improvement Bob Peterson
` (4 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Bob Peterson @ 2018-06-04 16:29 UTC (permalink / raw)
To: cluster-devel.redhat.com
Function gfs2_free_extlen calculates the length of an extent of
free blocks that may be reserved. The end pointer was calculated as
end = start + bh->b_size but b_size is incorrect because the
bitmap usually stops prior to the end of the buffer data on
the last bitmap.
What this means is that when you do a write, you can reserve a
chunk of blocks that runs off the end of the last bitmap. For
example, I've got a file system where there is only one bitmap
for each rgrp, so ri_length==1. I saw cases in which iozone
tried to do a big write, grabbed a large block reservation,
chose rgrp 5464152, which has ri_data0 5464153 and ri_data 8188.
So 5464153 + 8188 = 5472341 which is the end of the rgrp.
When it grabbed a reservation it got back: 5470936, length 7229.
But 5470936 + 7229 = 5478165. So the reservation starts inside
the rgrp but runs 5824 blocks past the end of the bitmap.
This patch fixes the calculation so it won't exceed the last
bitmap. It also adds a BUG_ON to guard against overflows in the
future.
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/incore.h | 1 +
fs/gfs2/rgrp.c | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 0bbbaa9b05cb..d2ad817e089f 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -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)
{
+ BUG_ON(rbm->offset >= rbm->rgd->rd_data);
return rbm->rgd->rd_data0 + (rbm_bi(rbm)->bi_start * GFS2_NBBY) +
rbm->offset;
}
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 8b683917a27e..6bc5cfe710d1 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -372,8 +372,8 @@ static u32 gfs2_free_extlen(const struct gfs2_rbm *rrbm, u32 len)
start = bi->bi_bh->b_data;
if (bi->bi_clone)
start = bi->bi_clone;
- end = start + bi->bi_bh->b_size;
start += bi->bi_offset;
+ end = start + bi->bi_len;
BUG_ON(rbm.offset & 3);
start += (rbm.offset / GFS2_NBBY);
bytes = min_t(u32, len / GFS2_NBBY, (end - start));
--
2.17.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Cluster-devel] [PATCH 5/9] gfs2: hole_size improvement
2018-06-04 16:29 [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window) Bob Peterson
` (3 preceding siblings ...)
2018-06-04 16:29 ` [Cluster-devel] [PATCH 4/9] GFS2: gfs2_free_extlen can return an extent that is too long Bob Peterson
@ 2018-06-04 16:29 ` Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 6/9] gfs2: gfs2_stuffed_write_end cleanup Bob Peterson
` (3 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Bob Peterson @ 2018-06-04 16:29 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Andreas Gruenbacher <agruenba@redhat.com>
Reimplement function hole_size based on a generic function for walking
the metadata tree and rename hole_size to gfs2_hole_size. While
previously, multiple invocations of hole_size were sometimes needed to
walk across the entire hole, the new implementation always returns the
entire hole at once (provided that the caller is interested in the total
size).
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/bmap.c | 210 +++++++++++++++++++++++++++++++++++--------------
1 file changed, 153 insertions(+), 57 deletions(-)
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index fcf2f7d166de..69f846418ad5 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -278,6 +278,21 @@ static inline __be64 *metapointer(unsigned int height, const struct metapath *mp
return p + mp->mp_list[height];
}
+static inline const __be64 *metaend(unsigned int height, const struct metapath *mp)
+{
+ const struct buffer_head *bh = mp->mp_bh[height];
+ return (const __be64 *)(bh->b_data + bh->b_size);
+}
+
+static void clone_metapath(struct metapath *clone, struct metapath *mp)
+{
+ unsigned int hgt;
+
+ *clone = *mp;
+ for (hgt = 0; hgt < mp->mp_aheight; hgt++)
+ get_bh(clone->mp_bh[hgt]);
+}
+
static void gfs2_metapath_ra(struct gfs2_glock *gl, __be64 *start, __be64 *end)
{
const __be64 *t;
@@ -419,6 +434,142 @@ static inline unsigned int gfs2_extent_length(void *start, unsigned int len, __b
return (ptr - first);
}
+typedef const __be64 *(*gfs2_metadata_walker)(
+ struct metapath *mp,
+ const __be64 *start, const __be64 *end,
+ u64 factor, void *data);
+
+#define WALK_STOP ((__be64 *)0)
+#define WALK_NEXT ((__be64 *)1)
+
+static int gfs2_walk_metadata(struct inode *inode, sector_t lblock,
+ u64 len, struct metapath *mp, gfs2_metadata_walker walker,
+ void *data)
+{
+ struct metapath clone;
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
+ const __be64 *start, *end, *ptr;
+ u64 factor = 1;
+ unsigned int hgt;
+ int ret = 0;
+
+ for (hgt = ip->i_height - 1; hgt >= mp->mp_aheight; hgt--)
+ factor *= sdp->sd_inptrs;
+
+ for (;;) {
+ u64 step;
+
+ /* Walk indirect block. */
+ start = metapointer(hgt, mp);
+ end = metaend(hgt, mp);
+
+ step = (end - start) * factor;
+ if (step > len)
+ end = start + DIV_ROUND_UP_ULL(len, factor);
+
+ ptr = walker(mp, start, end, factor, data);
+ if (ptr == WALK_STOP)
+ break;
+ if (step >= len)
+ break;
+ len -= step;
+ if (ptr != WALK_NEXT) {
+ BUG_ON(!*ptr);
+ mp->mp_list[hgt] += ptr - start;
+ goto fill_up_metapath;
+ }
+
+lower_metapath:
+ /* Decrease height of metapath. */
+ if (mp != &clone) {
+ clone_metapath(&clone, mp);
+ mp = &clone;
+ }
+ brelse(mp->mp_bh[hgt]);
+ mp->mp_bh[hgt] = NULL;
+ if (!hgt)
+ break;
+ hgt--;
+ factor *= sdp->sd_inptrs;
+
+ /* Advance in metadata tree. */
+ (mp->mp_list[hgt])++;
+ start = metapointer(hgt, mp);
+ end = metaend(hgt, mp);
+ if (start >= end) {
+ mp->mp_list[hgt] = 0;
+ if (!hgt)
+ break;
+ goto lower_metapath;
+ }
+
+fill_up_metapath:
+ /* Increase height of metapath. */
+ if (mp != &clone) {
+ clone_metapath(&clone, mp);
+ mp = &clone;
+ }
+ ret = fillup_metapath(ip, mp, ip->i_height - 1);
+ if (ret < 0)
+ break;
+ hgt += ret;
+ for (; ret; ret--)
+ do_div(factor, sdp->sd_inptrs);
+ mp->mp_aheight = hgt + 1;
+ }
+ if (mp == &clone)
+ release_metapath(mp);
+ return ret;
+}
+
+struct gfs2_hole_walker_args {
+ u64 blocks;
+};
+
+static const __be64 *gfs2_hole_walker(struct metapath *mp,
+ const __be64 *start, const __be64 *end,
+ u64 factor, void *data)
+{
+ struct gfs2_hole_walker_args *args = data;
+ const __be64 *ptr;
+
+ for (ptr = start; ptr < end; ptr++) {
+ if (*ptr) {
+ args->blocks += (ptr - start) * factor;
+ if (mp->mp_aheight == mp->mp_fheight)
+ return WALK_STOP;
+ return ptr; /* increase height */
+ }
+ }
+ args->blocks += (end - start) * factor;
+ return WALK_NEXT;
+}
+
+/**
+ * gfs2_hole_size - figure out the size of a hole
+ * @inode: The inode
+ * @lblock: The logical starting block number
+ * @len: How far to look (in blocks)
+ * @mp: The metapath at lblock
+ * @iomap: The iomap to store the hole size in
+ *
+ * This function modifies @mp.
+ *
+ * Returns: errno on error
+ */
+static int gfs2_hole_size(struct inode *inode, sector_t lblock, u64 len,
+ struct metapath *mp, struct iomap *iomap)
+{
+ struct gfs2_hole_walker_args args = { };
+ int ret = 0;
+
+ ret = gfs2_walk_metadata(inode, lblock, len, mp, gfs2_hole_walker, &args);
+ if (!ret)
+ iomap->length = args.blocks << inode->i_blkbits;
+ return ret;
+}
+
static inline void bmap_lock(struct gfs2_inode *ip, int create)
{
if (create)
@@ -615,62 +766,6 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
return 0;
}
-/**
- * hole_size - figure out the size of a hole
- * @inode: The inode
- * @lblock: The logical starting block number
- * @mp: The metapath
- *
- * Returns: The hole size in bytes
- *
- */
-static u64 hole_size(struct inode *inode, sector_t lblock, struct metapath *mp)
-{
- struct gfs2_inode *ip = GFS2_I(inode);
- struct gfs2_sbd *sdp = GFS2_SB(inode);
- struct metapath mp_eof;
- u64 factor = 1;
- int hgt;
- u64 holesz = 0;
- const __be64 *first, *end, *ptr;
- const struct buffer_head *bh;
- u64 lblock_stop = (i_size_read(inode) - 1) >> inode->i_blkbits;
- int zeroptrs;
- bool done = false;
-
- /* Get another metapath, to the very last byte */
- find_metapath(sdp, lblock_stop, &mp_eof, ip->i_height);
- for (hgt = ip->i_height - 1; hgt >= 0 && !done; hgt--) {
- bh = mp->mp_bh[hgt];
- if (bh) {
- zeroptrs = 0;
- first = metapointer(hgt, mp);
- end = (const __be64 *)(bh->b_data + bh->b_size);
-
- for (ptr = first; ptr < end; ptr++) {
- if (*ptr) {
- done = true;
- break;
- } else {
- zeroptrs++;
- }
- }
- } else {
- zeroptrs = sdp->sd_inptrs;
- }
- if (factor * zeroptrs >= lblock_stop - lblock + 1) {
- holesz = lblock_stop - lblock + 1;
- break;
- }
- holesz += factor * zeroptrs;
-
- factor *= sdp->sd_inptrs;
- if (hgt && (mp->mp_list[hgt - 1] < mp_eof.mp_list[hgt - 1]))
- (mp->mp_list[hgt - 1])++;
- }
- return holesz << inode->i_blkbits;
-}
-
static void gfs2_stuffed_iomap(struct inode *inode, struct iomap *iomap)
{
struct gfs2_inode *ip = GFS2_I(inode);
@@ -726,6 +821,7 @@ int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
lblock = pos >> inode->i_blkbits;
lend = (pos + length + sdp->sd_sb.sb_bsize - 1) >> inode->i_blkbits;
+ len = lend - lblock;
iomap->offset = lblock << inode->i_blkbits;
iomap->addr = IOMAP_NULL_ADDR;
@@ -780,7 +876,7 @@ int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
if (pos >= size)
ret = -ENOENT;
else if (height <= ip->i_height)
- iomap->length = hole_size(inode, lblock, &mp);
+ ret = gfs2_hole_size(inode, lblock, len, &mp, iomap);
else
iomap->length = size - pos;
}
--
2.17.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Cluster-devel] [PATCH 6/9] gfs2: gfs2_stuffed_write_end cleanup
2018-06-04 16:29 [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window) Bob Peterson
` (4 preceding siblings ...)
2018-06-04 16:29 ` [Cluster-devel] [PATCH 5/9] gfs2: hole_size improvement Bob Peterson
@ 2018-06-04 16:29 ` Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 7/9] gfs2: Remove ordered write mode handling from gfs2_trans_add_data Bob Peterson
` (2 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Bob Peterson @ 2018-06-04 16:29 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Andreas Gruenbacher <agruenba@redhat.com>
First, change the sanity check in gfs2_stuffed_write_end to check for
the actual write size instead of the requested write size.
Second, use the existing teardown code in gfs2_write_end instead of
duplicating it in gfs2_stuffed_write_end.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/aops.c | 49 ++++++++++++++++++-------------------------------
1 file changed, 18 insertions(+), 31 deletions(-)
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 66e7172e0134..69f25e3c97ce 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -817,7 +817,6 @@ static void adjust_fs_space(struct inode *inode)
* @inode: The inode
* @dibh: The buffer_head containing the on-disk inode
* @pos: The file position
- * @len: The length of the write
* @copied: How much was actually copied by the VFS
* @page: The page
*
@@ -827,17 +826,15 @@ static void adjust_fs_space(struct inode *inode)
* Returns: errno
*/
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 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;
void *kaddr;
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);
memcpy(buf + pos, kaddr + pos, copied);
@@ -853,20 +850,6 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
i_size_write(inode, to);
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;
}
@@ -880,9 +863,8 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
* @page: The page that has been written
* @fsdata: The fsdata (unused in GFS2)
*
- * The main write_end function for GFS2. We have a separate one for
- * stuffed files as they are slightly different, otherwise we just
- * put our locking around the VFS provided functions.
+ * The main write_end function for GFS2. We just put our locking around the VFS
+ * provided functions.
*
* Returns: errno
*/
@@ -903,32 +885,37 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == NULL);
ret = gfs2_meta_inode_buffer(ip, &dibh);
- if (unlikely(ret)) {
- unlock_page(page);
- put_page(page);
- goto failed;
- }
+ if (unlikely(ret))
+ goto out;
- if (gfs2_is_stuffed(ip))
- return gfs2_stuffed_write_end(inode, dibh, pos, len, copied, page);
+ if (gfs2_is_stuffed(ip)) {
+ ret = gfs2_stuffed_write_end(inode, dibh, pos, copied, page);
+ page = NULL;
+ goto out2;
+ }
if (!gfs2_is_writeback(ip))
gfs2_page_add_databufs(ip, page, pos & ~PAGE_MASK, len);
ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
+ page = NULL;
if (tr->tr_num_buf_new)
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
else
gfs2_trans_add_meta(ip->i_gl, dibh);
-
+out2:
if (inode == sdp->sd_rindex) {
adjust_fs_space(inode);
sdp->sd_rindex_uptodate = 0;
}
brelse(dibh);
-failed:
+out:
+ if (page) {
+ unlock_page(page);
+ put_page(page);
+ }
gfs2_trans_end(sdp);
gfs2_inplace_release(ip);
if (ip->i_qadata && ip->i_qadata->qa_qd_num)
--
2.17.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Cluster-devel] [PATCH 7/9] gfs2: Remove ordered write mode handling from gfs2_trans_add_data
2018-06-04 16:29 [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window) Bob Peterson
` (5 preceding siblings ...)
2018-06-04 16:29 ` [Cluster-devel] [PATCH 6/9] gfs2: gfs2_stuffed_write_end cleanup Bob Peterson
@ 2018-06-04 16:29 ` Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 8/9] gfs2: Iomap cleanups and improvements Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 9/9] MAINTAINERS: Add Andreas Gruenbacher as a maintainer for gfs2 Bob Peterson
8 siblings, 0 replies; 14+ messages in thread
From: Bob Peterson @ 2018-06-04 16:29 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Andreas Gruenbacher <agruenba@redhat.com>
In journaled data mode, we need to add each buffer head to the current
transaction. In ordered write mode, we only need to add the inode to
the ordered inode list. So far, both cases are handled in
gfs2_trans_add_data. This makes the code look misleading and is
inefficient for small block sizes as well. Handle both cases separately
instead.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/aops.c | 7 ++++---
fs/gfs2/bmap.c | 12 ++++++++----
fs/gfs2/log.h | 7 ++++++-
fs/gfs2/quota.c | 5 ++++-
fs/gfs2/trans.c | 27 ++++++++-------------------
5 files changed, 30 insertions(+), 28 deletions(-)
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 69f25e3c97ce..35f5ee23566d 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -54,8 +54,7 @@ static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
continue;
if (start >= to)
break;
- if (gfs2_is_jdata(ip))
- set_buffer_uptodate(bh);
+ set_buffer_uptodate(bh);
gfs2_trans_add_data(ip->i_gl, bh);
}
}
@@ -894,8 +893,10 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
goto out2;
}
- if (!gfs2_is_writeback(ip))
+ if (gfs2_is_jdata(ip))
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);
page = NULL;
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 69f846418ad5..5226c3bfbcf7 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -89,10 +89,12 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
map_bh(bh, inode->i_sb, block);
set_buffer_uptodate(bh);
- if (!gfs2_is_jdata(ip))
- mark_buffer_dirty(bh);
- if (!gfs2_is_writeback(ip))
+ if (gfs2_is_jdata(ip))
gfs2_trans_add_data(ip->i_gl, bh);
+ else {
+ mark_buffer_dirty(bh);
+ gfs2_ordered_add_inode(ip);
+ }
if (release) {
unlock_page(page);
@@ -1028,8 +1030,10 @@ static int gfs2_block_zero_range(struct inode *inode, loff_t from,
err = 0;
}
- if (!gfs2_is_writeback(ip))
+ if (gfs2_is_jdata(ip))
gfs2_trans_add_data(ip->i_gl, bh);
+ else
+ gfs2_ordered_add_inode(ip);
zero_user(page, offset, length);
mark_buffer_dirty(bh);
diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h
index 1862e310a067..20241436126d 100644
--- a/fs/gfs2/log.h
+++ b/fs/gfs2/log.h
@@ -14,6 +14,7 @@
#include <linux/spinlock.h>
#include <linux/writeback.h>
#include "incore.h"
+#include "inode.h"
/**
* 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,
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)) {
spin_lock(&sdp->sd_ordered_lock);
if (!test_and_set_bit(GIF_ORDERED, &ip->i_flags))
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 7a98abd340ee..e8585dfd209f 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -735,7 +735,10 @@ static int gfs2_write_buf_to_page(struct gfs2_inode *ip, unsigned long index,
if (!buffer_uptodate(bh))
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 (to_write > (bsize - boff)) {
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index c75cacaa349b..064c9a0ef046 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -143,32 +143,21 @@ static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl,
* @gl: The inode glock associated with the buffer
* @bh: The buffer to add
*
- * This is used in two distinct cases:
- * i) In ordered write mode
- * We put the data buffer on a list so that we can ensure that it's
- * synced to disk at the right time
- * ii) In journaled data mode
- * We need to journal the data block in the same way as metadata in
- * the functions above. The difference is that here we have a tag
- * which is two __be64's being the block number (as per meta data)
- * 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.
+ * This is used in journaled data mode.
+ * We need to journal the data block in the same way as metadata in
+ * the functions above. The difference is that here we have a tag
+ * which is two __be64's being the block number (as per meta data)
+ * 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)
{
struct gfs2_trans *tr = current->journal_info;
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;
- if (!gfs2_is_jdata(ip)) {
- gfs2_ordered_add_inode(ip);
- return;
- }
-
lock_buffer(bh);
if (buffer_pinned(bh)) {
set_bit(TR_TOUCHED, &tr->tr_flags);
--
2.17.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Cluster-devel] [PATCH 8/9] gfs2: Iomap cleanups and improvements
2018-06-04 16:29 [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window) Bob Peterson
` (6 preceding siblings ...)
2018-06-04 16:29 ` [Cluster-devel] [PATCH 7/9] gfs2: Remove ordered write mode handling from gfs2_trans_add_data Bob Peterson
@ 2018-06-04 16:29 ` Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 9/9] MAINTAINERS: Add Andreas Gruenbacher as a maintainer for gfs2 Bob Peterson
8 siblings, 0 replies; 14+ messages in thread
From: Bob Peterson @ 2018-06-04 16:29 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Andreas Gruenbacher <agruenba@redhat.com>
Clean up gfs2_iomap_alloc and gfs2_iomap_get. Document how
gfs2_iomap_alloc works: it now needs to be called separately after
gfs2_iomap_get where necessary; this will be used later by iomap write.
Move gfs2_iomap_ops into bmap.c.
Introduce a new gfs2_iomap_get_alloc helper and use it in
fallocate_chunk: gfs2_iomap_begin will become unsuitable for fallocate
with proper iomap write support.
In gfs2_block_map and fallocate_chunk, zero-initialize struct iomap.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
fs/gfs2/bmap.c | 205 ++++++++++++++++++++++++++++--------------------
fs/gfs2/bmap.h | 6 +-
fs/gfs2/file.c | 6 +-
fs/gfs2/inode.c | 4 -
4 files changed, 126 insertions(+), 95 deletions(-)
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 5226c3bfbcf7..a7b586e02693 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -572,22 +572,6 @@ static int gfs2_hole_size(struct inode *inode, sector_t lblock, u64 len,
return ret;
}
-static inline void bmap_lock(struct gfs2_inode *ip, int create)
-{
- if (create)
- down_write(&ip->i_rw_mutex);
- else
- down_read(&ip->i_rw_mutex);
-}
-
-static inline void bmap_unlock(struct gfs2_inode *ip, int create)
-{
- if (create)
- up_write(&ip->i_rw_mutex);
- else
- up_read(&ip->i_rw_mutex);
-}
-
static inline __be64 *gfs2_indirect_init(struct metapath *mp,
struct gfs2_glock *gl, unsigned int i,
unsigned offset, u64 bn)
@@ -614,15 +598,11 @@ enum alloc_state {
};
/**
- * gfs2_bmap_alloc - Build a metadata tree of the requested height
+ * gfs2_iomap_alloc - Build a metadata tree of the requested height
* @inode: The GFS2 inode
- * @lblock: The logical starting block of the extent
- * @bh_map: This is used to return the mapping details
- * @zero_new: True if newly allocated blocks should be zeroed
+ * @iomap: The iomap structure
+ * @flags: iomap flags
* @mp: The metapath, with proper height information calculated
- * @maxlen: The max number of data blocks to alloc
- * @dblock: Pointer to return the resulting new block
- * @dblks: Pointer to return the number of blocks allocated
*
* In this routine we may have to alloc:
* i) Indirect blocks to grow the metadata tree height
@@ -635,6 +615,13 @@ enum alloc_state {
* blocks are available, there will only be one request per bmap call)
* and uses the state machine to initialise the blocks in order.
*
+ * Right now, this function will allocate at most one indirect block
+ * worth of data -- with a default block size of 4K, that's slightly
+ * less than 2M. If this limitation is ever removed to allow huge
+ * allocations, we would probably still want to limit the iomap size we
+ * return to avoid stalling other tasks during huge writes; the next
+ * iomap iteration would then find the blocks already allocated.
+ *
* Returns: errno on error
*/
@@ -649,6 +636,7 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
unsigned dblks = 0;
unsigned ptrs_per_blk;
const unsigned end_of_metadata = mp->mp_fheight - 1;
+ int ret;
enum alloc_state state;
__be64 *ptr;
__be64 zero_bn = 0;
@@ -659,6 +647,8 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
gfs2_trans_add_meta(ip->i_gl, dibh);
+ down_write(&ip->i_rw_mutex);
+
if (mp->mp_fheight == mp->mp_aheight) {
struct buffer_head *bh;
int eob;
@@ -694,11 +684,10 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
blks = dblks + iblks;
i = mp->mp_aheight;
do {
- int error;
n = blks - alloced;
- error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL);
- if (error)
- return error;
+ ret = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL);
+ if (ret)
+ goto out;
alloced += n;
if (state != ALLOC_DATA || gfs2_is_jdata(ip))
gfs2_trans_add_unrevoke(sdp, bn, n);
@@ -754,7 +743,7 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
dblks = n;
ptr = metapointer(end_of_metadata, mp);
iomap->addr = bn << inode->i_blkbits;
- iomap->flags |= IOMAP_F_NEW;
+ iomap->flags |= IOMAP_F_MERGED | IOMAP_F_NEW;
while (n-- > 0)
*ptr++ = cpu_to_be64(bn++);
break;
@@ -764,8 +753,10 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
iomap->length = (u64)dblks << inode->i_blkbits;
ip->i_height = mp->mp_fheight;
gfs2_add_inode_blocks(&ip->i_inode, alloced);
- gfs2_dinode_out(ip, mp->mp_bh[0]->b_data);
- return 0;
+ gfs2_dinode_out(ip, dibh->b_data);
+out:
+ up_write(&ip->i_rw_mutex);
+ return ret;
}
static void gfs2_stuffed_iomap(struct inode *inode, struct iomap *iomap)
@@ -781,110 +772,130 @@ static void gfs2_stuffed_iomap(struct inode *inode, struct iomap *iomap)
}
/**
- * gfs2_iomap_begin - Map blocks from an inode to disk blocks
+ * gfs2_iomap_get - Map blocks from an inode to disk blocks
* @inode: The inode
* @pos: Starting position in bytes
* @length: Length to map, in bytes
* @flags: iomap flags
* @iomap: The iomap structure
+ * @mp: The metapath
*
* Returns: errno
*/
-int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
- unsigned flags, struct iomap *iomap)
+static int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
+ unsigned flags, struct iomap *iomap,
+ struct metapath *mp)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
- struct metapath mp = { .mp_aheight = 1, };
__be64 *ptr;
sector_t lblock;
- sector_t lend;
- int ret = 0;
+ sector_t lblock_stop;
+ int ret;
int eob;
- unsigned int len;
+ u64 len;
struct buffer_head *bh;
u8 height;
- trace_gfs2_iomap_start(ip, pos, length, flags);
- if (!length) {
- ret = -EINVAL;
- goto out;
- }
+ if (!length)
+ return -EINVAL;
if (gfs2_is_stuffed(ip)) {
if (flags & IOMAP_REPORT) {
+ if (pos >= i_size_read(inode))
+ return -ENOENT;
gfs2_stuffed_iomap(inode, iomap);
- if (pos >= iomap->length)
- ret = -ENOENT;
- goto out;
+ return 0;
}
BUG_ON(!(flags & IOMAP_WRITE));
}
-
lblock = pos >> inode->i_blkbits;
- lend = (pos + length + sdp->sd_sb.sb_bsize - 1) >> inode->i_blkbits;
- len = lend - lblock;
-
iomap->offset = lblock << inode->i_blkbits;
- iomap->addr = IOMAP_NULL_ADDR;
- iomap->type = IOMAP_HOLE;
- iomap->length = (u64)(lend - lblock) << inode->i_blkbits;
- iomap->flags = IOMAP_F_MERGED;
- bmap_lock(ip, flags & IOMAP_WRITE);
+ lblock_stop = (pos + length - 1) >> inode->i_blkbits;
+ len = lblock_stop - lblock + 1;
+
+ down_read(&ip->i_rw_mutex);
- ret = gfs2_meta_inode_buffer(ip, &mp.mp_bh[0]);
+ ret = gfs2_meta_inode_buffer(ip, &mp->mp_bh[0]);
if (ret)
- goto out_release;
+ goto unlock;
height = ip->i_height;
while ((lblock + 1) * sdp->sd_sb.sb_bsize > sdp->sd_heightsize[height])
height++;
- find_metapath(sdp, lblock, &mp, height);
+ find_metapath(sdp, lblock, mp, height);
if (height > ip->i_height || gfs2_is_stuffed(ip))
goto do_alloc;
- ret = lookup_metapath(ip, &mp);
+ ret = lookup_metapath(ip, mp);
if (ret)
- goto out_release;
+ goto unlock;
- if (mp.mp_aheight != ip->i_height)
+ if (mp->mp_aheight != ip->i_height)
goto do_alloc;
- ptr = metapointer(ip->i_height - 1, &mp);
+ ptr = metapointer(ip->i_height - 1, mp);
if (*ptr == 0)
goto do_alloc;
- iomap->type = IOMAP_MAPPED;
- iomap->addr = be64_to_cpu(*ptr) << inode->i_blkbits;
+ bh = mp->mp_bh[ip->i_height - 1];
+ len = gfs2_extent_length(bh->b_data, bh->b_size, ptr, len, &eob);
- bh = mp.mp_bh[ip->i_height - 1];
- len = gfs2_extent_length(bh->b_data, bh->b_size, ptr, lend - lblock, &eob);
+ iomap->addr = be64_to_cpu(*ptr) << inode->i_blkbits;
+ iomap->length = len << inode->i_blkbits;
+ iomap->type = IOMAP_MAPPED;
+ iomap->flags = IOMAP_F_MERGED;
if (eob)
iomap->flags |= IOMAP_F_BOUNDARY;
- iomap->length = (u64)len << inode->i_blkbits;
-out_release:
- release_metapath(&mp);
- bmap_unlock(ip, flags & IOMAP_WRITE);
out:
- trace_gfs2_iomap_end(ip, iomap, ret);
+ iomap->bdev = inode->i_sb->s_bdev;
+unlock:
+ up_read(&ip->i_rw_mutex);
return ret;
do_alloc:
- if (flags & IOMAP_WRITE) {
- ret = gfs2_iomap_alloc(inode, iomap, flags, &mp);
- } else if (flags & IOMAP_REPORT) {
+ iomap->addr = IOMAP_NULL_ADDR;
+ iomap->length = len << inode->i_blkbits;
+ iomap->type = IOMAP_HOLE;
+ iomap->flags = 0;
+ if (flags & IOMAP_REPORT) {
loff_t size = i_size_read(inode);
if (pos >= size)
ret = -ENOENT;
- else if (height <= ip->i_height)
- ret = gfs2_hole_size(inode, lblock, len, &mp, iomap);
+ else if (height == ip->i_height)
+ ret = gfs2_hole_size(inode, lblock, len, mp, iomap);
else
iomap->length = size - pos;
}
- goto out_release;
+ goto out;
}
+static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
+ unsigned flags, struct iomap *iomap)
+{
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct metapath mp = { .mp_aheight = 1, };
+ int ret;
+
+ trace_gfs2_iomap_start(ip, pos, length, flags);
+ if (flags & IOMAP_WRITE) {
+ ret = gfs2_iomap_get(inode, pos, length, flags, iomap, &mp);
+ if (!ret && iomap->type == IOMAP_HOLE)
+ ret = gfs2_iomap_alloc(inode, iomap, flags, &mp);
+ release_metapath(&mp);
+ } else {
+ ret = gfs2_iomap_get(inode, pos, length, flags, iomap, &mp);
+ release_metapath(&mp);
+ }
+ trace_gfs2_iomap_end(ip, iomap, ret);
+ return ret;
+}
+
+const struct iomap_ops gfs2_iomap_ops = {
+ .iomap_begin = gfs2_iomap_begin,
+};
+
/**
* gfs2_block_map - Map one or more blocks of an inode to a disk block
* @inode: The inode
@@ -910,25 +921,34 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,
struct buffer_head *bh_map, int create)
{
struct gfs2_inode *ip = GFS2_I(inode);
- struct iomap iomap;
- int ret, flags = 0;
+ loff_t pos = (loff_t)lblock << inode->i_blkbits;
+ loff_t length = bh_map->b_size;
+ struct metapath mp = { .mp_aheight = 1, };
+ struct iomap iomap = { };
+ int ret;
clear_buffer_mapped(bh_map);
clear_buffer_new(bh_map);
clear_buffer_boundary(bh_map);
trace_gfs2_bmap(ip, bh_map, lblock, create, 1);
- if (create)
- flags |= IOMAP_WRITE;
- ret = gfs2_iomap_begin(inode, (loff_t)lblock << inode->i_blkbits,
- bh_map->b_size, flags, &iomap);
- if (ret) {
- if (!create && ret == -ENOENT) {
- /* Return unmapped buffer beyond the end of file. */
+ if (create) {
+ ret = gfs2_iomap_get(inode, pos, length, IOMAP_WRITE, &iomap, &mp);
+ if (!ret && iomap.type == IOMAP_HOLE)
+ ret = gfs2_iomap_alloc(inode, &iomap, IOMAP_WRITE, &mp);
+ release_metapath(&mp);
+ } else {
+ ret = gfs2_iomap_get(inode, pos, length, 0, &iomap, &mp);
+ release_metapath(&mp);
+
+ /* Return unmapped buffer beyond the end of file. */
+ if (ret == -ENOENT) {
ret = 0;
+ goto out;
}
- goto out;
}
+ if (ret)
+ goto out;
if (iomap.length > bh_map->b_size) {
iomap.length = bh_map->b_size;
@@ -1143,6 +1163,19 @@ static int trunc_start(struct inode *inode, u64 newsize)
return error;
}
+int gfs2_iomap_get_alloc(struct inode *inode, loff_t pos, loff_t length,
+ struct iomap *iomap)
+{
+ struct metapath mp = { .mp_aheight = 1, };
+ int ret;
+
+ ret = gfs2_iomap_get(inode, pos, length, IOMAP_WRITE, iomap, &mp);
+ if (!ret && iomap->type == IOMAP_HOLE)
+ ret = gfs2_iomap_alloc(inode, iomap, IOMAP_WRITE, &mp);
+ release_metapath(&mp);
+ return ret;
+}
+
/**
* sweep_bh_for_rgrps - find an rgrp in a meta buffer and free blocks therein
* @ip: inode
diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h
index c3402fe00653..6b18fb323f0a 100644
--- a/fs/gfs2/bmap.h
+++ b/fs/gfs2/bmap.h
@@ -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_block_map(struct inode *inode, sector_t lblock,
struct buffer_head *bh, int create);
-extern int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
- unsigned flags, struct iomap *iomap);
+extern int gfs2_iomap_get_alloc(struct inode *inode, loff_t pos, loff_t length,
+ struct iomap *iomap);
extern int gfs2_extent_map(struct inode *inode, u64 lblock, int *new,
u64 *dblock, unsigned *extlen);
extern int gfs2_setattr_size(struct inode *inode, u64 size);
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 4b71f021a9e2..7137db7b0119 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -733,7 +733,7 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
struct gfs2_inode *ip = GFS2_I(inode);
loff_t end = offset + len;
struct buffer_head *dibh;
- struct iomap iomap;
+ struct iomap iomap = { };
int error;
error = gfs2_meta_inode_buffer(ip, &dibh);
@@ -749,8 +749,8 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
}
while (offset < end) {
- error = gfs2_iomap_begin(inode, offset, end - offset,
- IOMAP_WRITE, &iomap);
+ error = gfs2_iomap_get_alloc(inode, offset, end - offset,
+ &iomap);
if (error)
goto out;
offset = iomap.offset + iomap.length;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 8700eb815638..feda55f67050 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -2006,10 +2006,6 @@ static int gfs2_getattr(const struct path *path, struct kstat *stat,
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,
u64 start, u64 len)
{
--
2.17.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Cluster-devel] [PATCH 9/9] MAINTAINERS: Add Andreas Gruenbacher as a maintainer for gfs2
2018-06-04 16:29 [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window) Bob Peterson
` (7 preceding siblings ...)
2018-06-04 16:29 ` [Cluster-devel] [PATCH 8/9] gfs2: Iomap cleanups and improvements Bob Peterson
@ 2018-06-04 16:29 ` Bob Peterson
8 siblings, 0 replies; 14+ messages in thread
From: Bob Peterson @ 2018-06-04 16:29 UTC (permalink / raw)
To: cluster-devel.redhat.com
Add Andreas Gruenbacher as a maintainer for the gfs2 file system
and remove Steve Whitehouse.
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
MAINTAINERS | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index b60179d948bb..73745884a595 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5939,8 +5939,8 @@ S: Maintained
F: scripts/get_maintainer.pl
GFS2 FILE SYSTEM
-M: Steven Whitehouse <swhiteho@redhat.com>
M: Bob Peterson <rpeterso@redhat.com>
+M: Andreas Gruenbacher <agruenba@redhat.com>
L: cluster-devel at redhat.com
W: http://sources.redhat.com/cluster/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git
--
2.17.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
end of thread, other threads:[~2018-06-04 16:29 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-06-04 16:29 [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window) Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 1/9] gfs2: Remove sdp->sd_jheightsize Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 2/9] gfs2: Update find_metapath comment Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 3/9] GFS2: Fix allocation error bug with recursive rgrp glocking Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 4/9] GFS2: gfs2_free_extlen can return an extent that is too long Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 5/9] gfs2: hole_size improvement Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 6/9] gfs2: gfs2_stuffed_write_end cleanup Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 7/9] gfs2: Remove ordered write mode handling from gfs2_trans_add_data Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 8/9] gfs2: Iomap cleanups and improvements Bob Peterson
2018-06-04 16:29 ` [Cluster-devel] [PATCH 9/9] MAINTAINERS: Add Andreas Gruenbacher as a maintainer for gfs2 Bob Peterson
-- strict thread matches above, loose matches on Subject: below --
2018-04-02 15:44 [Cluster-devel] [PATCH 0/9] GFS2: Pre-pull patch posting (merge window) Bob Peterson
2017-05-03 13:45 Bob Peterson
2016-05-20 16:22 Bob Peterson
2015-04-13 15:10 Bob Peterson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).