From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andreas Gruenbacher Date: Tue, 28 Aug 2018 23:47:26 +0200 Subject: [Cluster-devel] [PATCH 3/8] gfs2: Move empty inode check out of gfs2_unstuff_dinode In-Reply-To: <20180828214731.15199-1-agruenba@redhat.com> References: <20180828214731.15199-1-agruenba@redhat.com> Message-ID: <20180828214731.15199-4-agruenba@redhat.com> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Split up gfs2_unstuff_dinode so that the empty inode check it contains can be moved out of there and into a new gfs2_inode_contains_data helper. We want to use the same check in gfs2_unstuff_dinode that we use for determining how many blocks need to be allocated and reserved. The gfs2_inode_contains_data helper currently still only treats stuffed, zero-length inodes as empty, but other criteria like does the inode contain and direct or indirect pointers could be used. Signed-off-by: Andreas Gruenbacher --- fs/gfs2/bmap.c | 90 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 32 deletions(-) diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index caa0b6d71bce..1963c730e0be 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -44,6 +44,18 @@ struct metapath { static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length); +/* + * gfs2_inode_contains_data - check if inode contains any data + * + * Return true if the inode contains (or may contain) data or indirect blocks. + */ +static bool gfs2_inode_contains_data(struct inode *inode) +{ + struct gfs2_inode *ip = GFS2_I(inode); + + return !gfs2_is_stuffed(ip) || i_size_read(inode) > 0; +} + /** * gfs2_unstuffer_page - unstuff a stuffed inode into a block cached by a page * @ip: the inode @@ -107,20 +119,10 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh, return 0; } -/** - * gfs2_unstuff_dinode - Unstuff a dinode when the data has grown too big - * @ip: The GFS2 inode to unstuff - * @page: The (optional) page. This is looked up if the @page is NULL - * - * This routine unstuffs a dinode and returns it to a "normal" state such - * that the height can be grown in the traditional way. - * - * Returns: errno - */ - -int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) +static int __gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page, + struct buffer_head *dibh, bool contains_data) { - struct buffer_head *bh, *dibh; + struct buffer_head *bh; struct gfs2_dinode *di; u64 block = 0; int isdir = gfs2_is_dir(ip); @@ -128,30 +130,26 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) down_write(&ip->i_rw_mutex); - error = gfs2_meta_inode_buffer(ip, &dibh); - if (error) - goto out; - - if (i_size_read(&ip->i_inode)) { + if (contains_data) { /* Get a free block, fill it with the stuffed data, and write it out to disk */ unsigned int n = 1; error = gfs2_alloc_blocks(ip, &block, &n, 0, NULL); if (error) - goto out_brelse; + goto out; if (isdir) { gfs2_trans_add_unrevoke(GFS2_SB(&ip->i_inode), block, 1); error = gfs2_dir_get_new_buffer(ip, block, &bh); if (error) - goto out_brelse; + goto out; gfs2_buffer_copy_tail(bh, sizeof(struct gfs2_meta_header), dibh, sizeof(struct gfs2_dinode)); brelse(bh); } else { error = gfs2_unstuffer_page(ip, dibh, block, page); if (error) - goto out_brelse; + goto out; } } @@ -161,7 +159,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) di = (struct gfs2_dinode *)dibh->b_data; gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); - if (i_size_read(&ip->i_inode)) { + if (contains_data) { *(__be64 *)(di + 1) = cpu_to_be64(block); gfs2_add_inode_blocks(&ip->i_inode, 1); di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode)); @@ -170,13 +168,35 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) ip->i_height = 1; di->di_height = cpu_to_be16(1); -out_brelse: - brelse(dibh); out: up_write(&ip->i_rw_mutex); return error; } +/** + * gfs2_unstuff_dinode - Unstuff a dinode when the data has grown too big + * @ip: The GFS2 inode to unstuff + * @page: The (optional) page. This is looked up if the @page is NULL + * + * This routine unstuffs a dinode and returns it to a "normal" state such + * that the height can be grown in the traditional way. + * + * Returns: errno + */ + +int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) +{ + bool contains_data = gfs2_inode_contains_data(&ip->i_inode); + struct buffer_head *dibh; + int error; + + error = gfs2_meta_inode_buffer(ip, &dibh); + if (error) + return error; + error = __gfs2_unstuff_dinode(ip, page, dibh, contains_data); + brelse(dibh); + return error; +} /** * find_metapath - Find path through the metadata tree @@ -1044,7 +1064,10 @@ static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos, goto out_trans_fail; if (unstuff) { - ret = gfs2_unstuff_dinode(ip, NULL); + bool contains_data = gfs2_inode_contains_data(inode); + struct buffer_head *dibh = mp.mp_bh[0]; + + ret = __gfs2_unstuff_dinode(ip, NULL, dibh, contains_data); if (ret) goto out_trans_end; release_metapath(&mp); @@ -2076,7 +2099,7 @@ static int do_grow(struct inode *inode, u64 size) struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_alloc_parms ap = { .target = 1, }; - struct buffer_head *dibh; + struct buffer_head *dibh = NULL; int error; int unstuff = 0; @@ -2097,23 +2120,26 @@ static int do_grow(struct inode *inode, u64 size) if (error) goto do_grow_release; + error = gfs2_meta_inode_buffer(ip, &dibh); + if (error) + goto do_end_trans; + if (unstuff) { - error = gfs2_unstuff_dinode(ip, NULL); + bool contains_data = gfs2_inode_contains_data(inode); + + error = __gfs2_unstuff_dinode(ip, NULL, dibh, contains_data); if (error) goto do_end_trans; } - error = gfs2_meta_inode_buffer(ip, &dibh); - if (error) - goto do_end_trans; - i_size_write(inode, size); ip->i_inode.i_mtime = ip->i_inode.i_ctime = current_time(&ip->i_inode); gfs2_trans_add_meta(ip->i_gl, dibh); gfs2_dinode_out(ip, dibh->b_data); - brelse(dibh); do_end_trans: + if (dibh) + brelse(dibh); gfs2_trans_end(sdp); do_grow_release: if (unstuff) { -- 2.17.1