diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/gfs2/bmap.c | 67 | ||||
-rw-r--r-- | fs/gfs2/bmap.h | 7 | ||||
-rw-r--r-- | fs/gfs2/dir.c | 2 | ||||
-rw-r--r-- | fs/gfs2/ops_address.c | 3 | ||||
-rw-r--r-- | fs/gfs2/ops_vm.c | 2 | ||||
-rw-r--r-- | fs/gfs2/page.c | 60 | ||||
-rw-r--r-- | fs/gfs2/page.h | 2 |
7 files changed, 66 insertions, 77 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 98fa07c..72b19c5 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -48,6 +48,65 @@ struct strip_mine { }; /** + * gfs2_unstuffer_page - unstuff a stuffed inode into a block cached by a page + * @ip: the inode + * @dibh: the dinode buffer + * @block: the block number that was allocated + * @private: any locked page held by the caller process + * + * Returns: errno + */ + +static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh, + uint64_t block, struct page *page) +{ + struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); + struct inode *inode = &ip->i_inode; + struct buffer_head *bh; + int release = 0; + + if (!page || page->index) { + page = grab_cache_page(inode->i_mapping, 0); + if (!page) + return -ENOMEM; + release = 1; + } + + if (!PageUptodate(page)) { + void *kaddr = kmap(page); + + memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), + ip->i_di.di_size); + memset(kaddr + ip->i_di.di_size, 0, + PAGE_CACHE_SIZE - ip->i_di.di_size); + kunmap(page); + + SetPageUptodate(page); + } + + if (!page_has_buffers(page)) + create_empty_buffers(page, 1 << inode->i_blkbits, + (1 << BH_Uptodate)); + + bh = page_buffers(page); + + if (!buffer_mapped(bh)) + map_bh(bh, inode->i_sb, block); + + set_buffer_uptodate(bh); + if ((sdp->sd_args.ar_data == GFS2_DATA_ORDERED) || gfs2_is_jdata(ip)) + gfs2_trans_add_bh(ip->i_gl, bh, 0); + mark_buffer_dirty(bh); + + if (release) { + unlock_page(page); + page_cache_release(page); + } + + return 0; +} + +/** * gfs2_unstuff_dinode - Unstuff a dinode when the data has grown too big * @ip: The GFS2 inode to unstuff * @unstuffer: the routine that handles unstuffing a non-zero length file @@ -59,8 +118,7 @@ struct strip_mine { * Returns: errno */ -int gfs2_unstuff_dinode(struct gfs2_inode *ip, gfs2_unstuffer_t unstuffer, - void *private) +int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) { struct buffer_head *bh, *dibh; uint64_t block = 0; @@ -90,7 +148,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, gfs2_unstuffer_t unstuffer, } else { block = gfs2_alloc_data(ip); - error = unstuffer(ip, dibh, block, private); + error = gfs2_unstuffer_page(ip, dibh, block, page); if (error) goto out_brelse; } @@ -786,8 +844,7 @@ static int do_grow(struct gfs2_inode *ip, uint64_t size) if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { if (gfs2_is_stuffed(ip)) { - error = gfs2_unstuff_dinode(ip, gfs2_unstuffer_page, - NULL); + error = gfs2_unstuff_dinode(ip, NULL); if (error) goto out_end_trans; } diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h index 06ccb2d..1a26541 100644 --- a/fs/gfs2/bmap.h +++ b/fs/gfs2/bmap.h @@ -10,12 +10,7 @@ #ifndef __BMAP_DOT_H__ #define __BMAP_DOT_H__ -typedef int (*gfs2_unstuffer_t) (struct gfs2_inode * ip, - struct buffer_head * dibh, uint64_t block, - void *private); -int gfs2_unstuff_dinode(struct gfs2_inode *ip, gfs2_unstuffer_t unstuffer, - void *private); - +int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page); int gfs2_block_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, int *boundary); int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen); diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index f62223b..563b99e 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -173,7 +173,7 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf, return -EINVAL; if (gfs2_is_stuffed(ip)) { - error = gfs2_unstuff_dinode(ip, NULL, NULL); + error = gfs2_unstuff_dinode(ip, NULL); if (error) return error; } diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index d33f6aa..93e00a8 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -395,8 +395,7 @@ static int gfs2_prepare_write(struct file *file, struct page *page, if (gfs2_is_stuffed(ip)) { if (end > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { - error = gfs2_unstuff_dinode(ip, gfs2_unstuffer_page, - page); + error = gfs2_unstuff_dinode(ip, page); if (error == 0) goto prepare_write; } else if (!PageUptodate(page)) diff --git a/fs/gfs2/ops_vm.c b/fs/gfs2/ops_vm.c index 08709f1..910722d 100644 --- a/fs/gfs2/ops_vm.c +++ b/fs/gfs2/ops_vm.c @@ -104,7 +104,7 @@ static int alloc_page_backing(struct gfs2_inode *ip, struct page *page) goto out_ipres; if (gfs2_is_stuffed(ip)) { - error = gfs2_unstuff_dinode(ip, gfs2_unstuffer_page, NULL); + error = gfs2_unstuff_dinode(ip, NULL); if (error) goto out_trans; } diff --git a/fs/gfs2/page.c b/fs/gfs2/page.c index b93caf2..0d6befe 100644 --- a/fs/gfs2/page.c +++ b/fs/gfs2/page.c @@ -114,66 +114,6 @@ void gfs2_page_sync(struct gfs2_glock *gl, int flags) } /** - * gfs2_unstuffer_page - unstuff a stuffed inode into a block cached by a page - * @ip: the inode - * @dibh: the dinode buffer - * @block: the block number that was allocated - * @private: any locked page held by the caller process - * - * Returns: errno - */ - -int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh, - uint64_t block, void *private) -{ - struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); - struct inode *inode = &ip->i_inode; - struct page *page = (struct page *)private; - struct buffer_head *bh; - int release = 0; - - if (!page || page->index) { - page = grab_cache_page(inode->i_mapping, 0); - if (!page) - return -ENOMEM; - release = 1; - } - - if (!PageUptodate(page)) { - void *kaddr = kmap(page); - - memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), - ip->i_di.di_size); - memset(kaddr + ip->i_di.di_size, 0, - PAGE_CACHE_SIZE - ip->i_di.di_size); - kunmap(page); - - SetPageUptodate(page); - } - - if (!page_has_buffers(page)) - create_empty_buffers(page, 1 << inode->i_blkbits, - (1 << BH_Uptodate)); - - bh = page_buffers(page); - - if (!buffer_mapped(bh)) - map_bh(bh, inode->i_sb, block); - - set_buffer_uptodate(bh); - if ((sdp->sd_args.ar_data == GFS2_DATA_ORDERED) || gfs2_is_jdata(ip)) - gfs2_trans_add_bh(ip->i_gl, bh, 0); - mark_buffer_dirty(bh); - - if (release) { - unlock_page(page); - page_cache_release(page); - } - - return 0; -} - -/** * gfs2_block_truncate_page - Deal with zeroing out data for truncate * * This is partly borrowed from ext3. diff --git a/fs/gfs2/page.h b/fs/gfs2/page.h index 2c853a9..67a4f4b 100644 --- a/fs/gfs2/page.h +++ b/fs/gfs2/page.h @@ -14,8 +14,6 @@ void gfs2_pte_inval(struct gfs2_glock *gl); void gfs2_page_inval(struct gfs2_glock *gl); void gfs2_page_sync(struct gfs2_glock *gl, int flags); -int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh, - uint64_t block, void *private); int gfs2_block_truncate_page(struct address_space *mapping); void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page, unsigned int from, unsigned int to); |