From: Bob Peterson <rpete...@redhat.com> This patch expands many of the libgfs2 functions so that they may operate on gfs1 file systems, depending on the sdp->gfs1 variable.
rhbz#675723 --- gfs2/libgfs2/fs_ops.c | 113 +++++++++++++++++++++++++++++++++++-------- gfs2/libgfs2/gfs1.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ gfs2/libgfs2/libgfs2.h | 17 ++++++- gfs2/libgfs2/ondisk.c | 10 +++- gfs2/libgfs2/rgrp.c | 9 ++- 5 files changed, 248 insertions(+), 27 deletions(-) diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c index 6ffee9d..e99cc2a 100644 --- a/gfs2/libgfs2/fs_ops.c +++ b/gfs2/libgfs2/fs_ops.c @@ -177,7 +177,10 @@ found: rg->rg_free--; bmodified(bh); - gfs2_rgrp_out(rg, rl->bh[0]); + if (sdp->gfs1) + gfs_rgrp_out((struct gfs_rgrp *)rg, rl->bh[0]); + else + gfs2_rgrp_out(rg, rl->bh[0]); sdp->blks_alloced++; return ri->ri_data0 + bn; @@ -231,7 +234,7 @@ void unstuff_dinode(struct gfs2_inode *ip) struct gfs2_sbd *sdp = ip->i_sbd; struct gfs2_buffer_head *bh; uint64_t block = 0; - int isdir = !!(S_ISDIR(ip->i_di.di_mode)); + int isdir = S_ISDIR(ip->i_di.di_mode) || is_gfs_dir(&ip->i_di); if (ip->i_di.di_size) { if (isdir) { @@ -828,6 +831,8 @@ void gfs2_get_leaf_nr(struct gfs2_inode *dip, uint32_t lindex, uint64_t leaf_no; int count; + if (dip->i_sbd->gfs1) + return gfs_get_leaf_nr(dip, lindex, leaf_out); count = gfs2_readi(dip, (char *)&leaf_no, lindex * sizeof(uint64_t), sizeof(uint64_t)); if (count != sizeof(uint64_t)) @@ -841,6 +846,10 @@ void gfs2_put_leaf_nr(struct gfs2_inode *dip, uint32_t inx, uint64_t leaf_out) uint64_t leaf_no; int count; + if (dip->i_sbd->gfs1) { + gfs_put_leaf_nr(dip, inx, leaf_out); + return; + } leaf_no = cpu_to_be64(leaf_out); count = gfs2_writei(dip, (char *)&leaf_no, inx * sizeof(uint64_t), sizeof(uint64_t)); @@ -891,8 +900,12 @@ static void dir_split_leaf(struct gfs2_inode *dip, uint32_t lindex, for (x = 0; x < half_len; x++) lp[x] = cpu_to_be64(bn); - count = gfs2_writei(dip, (char *)lp, start * sizeof(uint64_t), - half_len * sizeof(uint64_t)); + if (dip->i_sbd->gfs1) + count = gfs1_writei(dip, (char *)lp, start * sizeof(uint64_t), + half_len * sizeof(uint64_t)); + else + count = gfs2_writei(dip, (char *)lp, start * sizeof(uint64_t), + half_len * sizeof(uint64_t)); if (count != half_len * sizeof(uint64_t)) die("dir_split_leaf (2)\n"); @@ -985,8 +998,14 @@ static void dir_double_exhash(struct gfs2_inode *dip) *to++ = *from; } - count = gfs2_writei(dip, (char *)buf + sdp->sd_hash_bsize, - block * sdp->bsize, sdp->bsize); + if (sdp->gfs1) + count = gfs1_writei(dip, (char *)buf + + sdp->sd_hash_bsize, + block * sdp->bsize, sdp->bsize); + else + count = gfs2_writei(dip, (char *)buf + + sdp->sd_hash_bsize, + block * sdp->bsize, sdp->bsize); if (count != sdp->bsize) die("dir_double_exhash (2)\n"); @@ -1235,13 +1254,21 @@ void dir_add(struct gfs2_inode *dip, const char *filename, int len, dir_l_add(dip, filename, len, inum, type); } -struct gfs2_buffer_head *init_dinode(struct gfs2_sbd *sdp, - struct gfs2_inum *inum, unsigned int mode, - uint32_t flags, struct gfs2_inum *parent) +static struct gfs2_buffer_head *__init_dinode(struct gfs2_sbd *sdp, + struct gfs2_inum *inum, + unsigned int mode, + uint32_t flags, + struct gfs2_inum *parent, + int gfs1) { struct gfs2_buffer_head *bh; struct gfs2_dinode di; + int is_dir; + if (gfs1) + is_dir = (IF2DT(mode) == GFS_FILE_DIR); + else + is_dir = S_ISDIR(mode); bh = bget(sdp, inum->no_addr); memset(&di, 0, sizeof(struct gfs2_dinode)); @@ -1256,7 +1283,7 @@ struct gfs2_buffer_head *init_dinode(struct gfs2_sbd *sdp, di.di_goal_meta = di.di_goal_data = bh->b_blocknr; di.di_flags = flags; - if (S_ISDIR(mode)) { + if (is_dir) { struct gfs2_dirent de1, de2; memset(&de1, 0, sizeof(struct gfs2_dirent)); @@ -1264,14 +1291,14 @@ struct gfs2_buffer_head *init_dinode(struct gfs2_sbd *sdp, de1.de_hash = gfs2_disk_hash(".", 1); de1.de_rec_len = GFS2_DIRENT_SIZE(1); de1.de_name_len = 1; - de1.de_type = IF2DT(S_IFDIR); + de1.de_type = (gfs1 ? GFS_FILE_DIR : IF2DT(S_IFDIR)); memset(&de2, 0, sizeof(struct gfs2_dirent)); de2.de_inum = *parent; de2.de_hash = gfs2_disk_hash("..", 2); de2.de_rec_len = sdp->bsize - sizeof(struct gfs2_dinode) - de1.de_rec_len; de2.de_name_len = 2; - de2.de_type = IF2DT(S_IFDIR); + de2.de_type = (gfs1 ? GFS_FILE_DIR : IF2DT(S_IFDIR)); gfs2_dirent_out(&de1, bh->b_data + sizeof(struct gfs2_dinode)); memcpy(bh->b_data + @@ -1297,30 +1324,56 @@ struct gfs2_buffer_head *init_dinode(struct gfs2_sbd *sdp, return bh; } -struct gfs2_inode *createi(struct gfs2_inode *dip, const char *filename, - unsigned int mode, uint32_t flags) +struct gfs2_buffer_head *init_dinode(struct gfs2_sbd *sdp, + struct gfs2_inum *inum, + unsigned int mode, uint32_t flags, + struct gfs2_inum *parent) +{ + return __init_dinode(sdp, inum, mode, flags, parent, 0); +} + +struct gfs2_buffer_head *init_gfs_dinode(struct gfs2_sbd *sdp, + struct gfs2_inum *inum, + unsigned int mode, uint32_t flags, + struct gfs2_inum *parent) +{ + return __init_dinode(sdp, inum, mode, flags, parent, 1); +} + +static struct gfs2_inode *__createi(struct gfs2_inode *dip, + const char *filename, unsigned int mode, + uint32_t flags, int if_gfs1) { struct gfs2_sbd *sdp = dip->i_sbd; uint64_t bn; struct gfs2_inum inum; struct gfs2_buffer_head *bh; struct gfs2_inode *ip; + int is_dir; gfs2_lookupi(dip, filename, strlen(filename), &ip); if (!ip) { bn = dinode_alloc(sdp); - inum.no_formal_ino = sdp->md.next_inum++; + if (if_gfs1) + inum.no_formal_ino = bn; + else + inum.no_formal_ino = sdp->md.next_inum++; inum.no_addr = bn; dir_add(dip, filename, strlen(filename), &inum, IF2DT(mode)); - if(S_ISDIR(mode)) { + if (if_gfs1) + is_dir = (IF2DT(mode) == GFS_FILE_DIR); + else + is_dir = S_ISDIR(mode); + if (is_dir) { bmodified(dip->i_bh); dip->i_di.di_nlink++; } - bh = init_dinode(sdp, &inum, mode, flags, &dip->i_di.di_num); + bh = __init_dinode(sdp, &inum, mode, flags, &dip->i_di.di_num, + if_gfs1); ip = inode_get(sdp, bh); bmodified(bh); } @@ -1328,6 +1381,18 @@ struct gfs2_inode *createi(struct gfs2_inode *dip, const char *filename, return ip; } +struct gfs2_inode *createi(struct gfs2_inode *dip, const char *filename, + unsigned int mode, uint32_t flags) +{ + return __createi(dip, filename, mode, flags, 0); +} + +struct gfs2_inode *gfs_createi(struct gfs2_inode *dip, const char *filename, + unsigned int mode, uint32_t flags) +{ + return __createi(dip, filename, mode, flags, 1); +} + /** * gfs2_filecmp - Compare two filenames * @file1: The first filename @@ -1541,7 +1606,7 @@ int dir_search(struct gfs2_inode *dip, const char *filename, int len, { int error; - if(!S_ISDIR(dip->i_di.di_mode)) + if(!S_ISDIR(dip->i_di.di_mode) && !is_gfs_dir(&dip->i_di)) return -1; if (dip->i_di.di_flags & GFS2_DIF_EXHASH) @@ -1627,7 +1692,7 @@ int gfs2_dirent_del(struct gfs2_inode *dip, const char *filename, int len) { int error; - if(!S_ISDIR(dip->i_di.di_mode)) + if(!S_ISDIR(dip->i_di.di_mode) && !is_gfs_dir(&dip->i_di)) return -1; if (dip->i_di.di_flags & GFS2_DIF_EXHASH) @@ -1684,7 +1749,10 @@ void gfs2_free_block(struct gfs2_sbd *sdp, uint64_t block) if (rgd) { gfs2_set_bitmap(sdp, block, GFS2_BLKST_FREE); rgd->rg.rg_free++; /* adjust the free count */ - gfs2_rgrp_out(&rgd->rg, rgd->bh[0]); /* back to the buffer */ + if (sdp->gfs1) + gfs_rgrp_out((struct gfs_rgrp *)&rgd->rg, rgd->bh[0]); + else + gfs2_rgrp_out(&rgd->rg, rgd->bh[0]); sdp->blks_alloced--; } } @@ -1748,7 +1816,10 @@ int gfs2_freedi(struct gfs2_sbd *sdp, uint64_t diblock) rgd = gfs2_blk2rgrpd(sdp, diblock); rgd->rg.rg_free++; rgd->rg.rg_dinodes--; /* one less inode in use */ - gfs2_rgrp_out(&rgd->rg, rgd->bh[0]); + if (sdp->gfs1) + gfs_rgrp_out((struct gfs_rgrp *)&rgd->rg, rgd->bh[0]); + else + gfs2_rgrp_out(&rgd->rg, rgd->bh[0]); sdp->dinodes_alloced--; return 0; } diff --git a/gfs2/libgfs2/gfs1.c b/gfs2/libgfs2/gfs1.c index 5b8d4ed..d1e8ab8 100644 --- a/gfs2/libgfs2/gfs1.c +++ b/gfs2/libgfs2/gfs1.c @@ -4,6 +4,7 @@ #include <string.h> #include <stdint.h> #include <inttypes.h> +#include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> @@ -31,6 +32,13 @@ gfs1_metapointer(struct gfs2_buffer_head *bh, unsigned int height, return ((uint64_t *)(bh->b_data + head_size)) + mp->mp_list[height]; } +int is_gfs_dir(struct gfs2_dinode *dinode) +{ + if (dinode->__pad1 == GFS_FILE_DIR) + return 1; + return 0; +} + void gfs1_lookup_block(struct gfs2_inode *ip, struct gfs2_buffer_head *bh, unsigned int height, struct metapath *mp, int create, int *new, uint64_t *block) @@ -159,6 +167,98 @@ void gfs1_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new, free(mp); } +int gfs1_writei(struct gfs2_inode *ip, char *buf, uint64_t offset, + unsigned int size) +{ + struct gfs2_sbd *sdp = ip->i_sbd; + struct gfs2_buffer_head *bh; + uint64_t lblock, dblock; + uint32_t extlen = 0; + unsigned int amount; + int new; + int journaled = fs_is_jdata(ip); + const uint64_t start = offset; + int copied = 0; + int error = 0; + + if (!size) + goto fail; /* Not really an error */ + + + if (!ip->i_di.di_height && /* stuffed */ + ((start + size) > (sdp->bsize - sizeof(struct gfs_dinode)))) + unstuff_dinode(ip); + + if (journaled) { + lblock = offset / sdp->sd_jbsize; + offset %= sdp->sd_jbsize; + } else { + lblock = offset >> sdp->sd_sb.sb_bsize_shift; + offset &= sdp->bsize - 1; + } + + if (!ip->i_di.di_height) /* stuffed */ + offset += sizeof(struct gfs_dinode); + else if (journaled) + offset += sizeof(struct gfs2_meta_header); + + while (copied < size) { + amount = size - copied; + if (amount > sdp->bsize - offset) + amount = sdp->bsize - offset; + + if (!extlen){ + new = TRUE; + gfs1_block_map(ip, lblock, &new, &dblock, &extlen, 0); + if (!dblock) + return -1; + } + + if (dblock == ip->i_di.di_num.no_addr) + bh = ip->i_bh; + else + bh = bread(sdp, dblock); + + if (journaled && dblock != ip->i_di.di_num.no_addr ) { + struct gfs2_meta_header mh; + + mh.mh_magic = GFS2_MAGIC; + mh.mh_type = GFS2_METATYPE_JD; + mh.mh_format = GFS2_FORMAT_JD; + gfs2_meta_header_out(&mh, bh); + } + + memcpy(bh->b_data + offset, buf + copied, amount); + bmodified(bh); + if (bh != ip->i_bh) + brelse(bh); + + copied += amount; + lblock++; + dblock++; + extlen--; + + offset = (journaled) ? sizeof(struct gfs2_meta_header) : 0; + } + + out: + if (ip->i_di.di_size < start + copied) { + bmodified(ip->i_bh); + ip->i_di.di_size = start + copied; + } + ip->i_di.di_mtime = ip->i_di.di_ctime = time(NULL); + + gfs2_dinode_out(&ip->i_di, ip->i_bh); + + return copied; + + fail: + if (copied) + goto out; + + return error; +} + /* ------------------------------------------------------------------------ */ /* gfs_dinode_in */ /* ------------------------------------------------------------------------ */ @@ -301,3 +401,29 @@ void gfs_rgrp_out(struct gfs_rgrp *rgrp, struct gfs2_buffer_head *rbh) memcpy(str->rg_reserved, rgrp->rg_reserved, 64); bmodified(rbh); } + +void gfs_get_leaf_nr(struct gfs2_inode *dip, uint32_t lindex, + uint64_t *leaf_out) +{ + uint64_t leaf_no; + int count; + + count = gfs2_readi(dip, (char *)&leaf_no, lindex * sizeof(uint64_t), + sizeof(uint64_t)); + if (count != sizeof(uint64_t)) + die("gfs_get_leaf_nr: Bad internal read.\n"); + + *leaf_out = be64_to_cpu(leaf_no); +} + +void gfs_put_leaf_nr(struct gfs2_inode *dip, uint32_t inx, uint64_t leaf_out) +{ + uint64_t leaf_no; + int count; + + leaf_no = cpu_to_be64(leaf_out); + count = gfs1_writei(dip, (char *)&leaf_no, inx * sizeof(uint64_t), + sizeof(uint64_t)); + if (count != sizeof(uint64_t)) + die("gfs_put_leaf_nr: Bad internal write.\n"); +} diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h index 22c6552..58442e8 100644 --- a/gfs2/libgfs2/libgfs2.h +++ b/gfs2/libgfs2/libgfs2.h @@ -366,8 +366,16 @@ extern struct gfs2_buffer_head *init_dinode(struct gfs2_sbd *sdp, struct gfs2_inum *inum, unsigned int mode, uint32_t flags, struct gfs2_inum *parent); +extern struct gfs2_buffer_head *init_gfs_dinode(struct gfs2_sbd *sdp, + struct gfs2_inum *inum, + unsigned int mode, + uint32_t flags, + struct gfs2_inum *parent); extern struct gfs2_inode *createi(struct gfs2_inode *dip, const char *filename, unsigned int mode, uint32_t flags); +extern struct gfs2_inode *gfs_createi(struct gfs2_inode *dip, + const char *filename, unsigned int mode, + uint32_t flags); extern void dirent2_del(struct gfs2_inode *dip, struct gfs2_buffer_head *bh, struct gfs2_dirent *prev, struct gfs2_dirent *cur); extern int dir_search(struct gfs2_inode *dip, const char *filename, int len, @@ -577,13 +585,15 @@ struct gfs_log_descriptor { char ld_reserved[64]; }; +extern int is_gfs_dir(struct gfs2_dinode *dinode); extern void gfs1_lookup_block(struct gfs2_inode *ip, struct gfs2_buffer_head *bh, unsigned int height, struct metapath *mp, int create, int *new, uint64_t *block); extern void gfs1_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new, uint64_t *dblock, uint32_t *extlen, int prealloc); -extern int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1); +extern int gfs1_writei(struct gfs2_inode *ip, char *buf, uint64_t offset, + unsigned int size); extern int gfs1_ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int quiet); extern struct gfs2_inode *gfs_inode_get(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh); @@ -592,6 +602,10 @@ extern struct gfs2_inode *gfs_inode_read(struct gfs2_sbd *sdp, extern void gfs_jindex_in(struct gfs_jindex *jindex, char *buf); extern void gfs_rgrp_in(struct gfs_rgrp *rg, struct gfs2_buffer_head *bh); extern void gfs_rgrp_out(struct gfs_rgrp *rg, struct gfs2_buffer_head *bh); +extern void gfs_get_leaf_nr(struct gfs2_inode *dip, uint32_t lindex, + uint64_t *leaf_out); +extern void gfs_put_leaf_nr(struct gfs2_inode *dip, uint32_t inx, + uint64_t leaf_out); /* gfs2_log.c */ struct gfs2_options { @@ -685,6 +699,7 @@ extern int clean_journal(struct gfs2_inode *ip, struct gfs2_log_header *head); /* rgrp.c */ extern int gfs2_compute_bitstructs(struct gfs2_sbd *sdp, struct rgrp_list *rgd); extern struct rgrp_list *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk); +extern uint64_t __gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd); extern uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd); extern void gfs2_rgrp_relse(struct rgrp_list *rgd); extern void gfs2_rgrp_free(osi_list_t *rglist); diff --git a/gfs2/libgfs2/ondisk.c b/gfs2/libgfs2/ondisk.c index 351198a..507cebb 100644 --- a/gfs2/libgfs2/ondisk.c +++ b/gfs2/libgfs2/ondisk.c @@ -98,15 +98,20 @@ void gfs2_sb_in(struct gfs2_sb *sb, struct gfs2_buffer_head *bh) CPIN_32(sb, str, sb_fs_format); CPIN_32(sb, str, sb_multihost_format); + CPIN_32(sb, str, __pad0); /* gfs sb_flags */ CPIN_32(sb, str, sb_bsize); CPIN_32(sb, str, sb_bsize_shift); + CPIN_32(sb, str, __pad1); /* gfs sb_seg_size */ gfs2_inum_in(&sb->sb_master_dir, (char *)&str->sb_master_dir); gfs2_inum_in(&sb->sb_root_dir, (char *)&str->sb_root_dir); CPIN_08(sb, str, sb_lockproto, GFS2_LOCKNAME_LEN); CPIN_08(sb, str, sb_locktable, GFS2_LOCKNAME_LEN); + gfs2_inum_in(&sb->__pad2, (char *)&str->__pad2); /* gfs rindex */ + gfs2_inum_in(&sb->__pad3, (char *)&str->__pad3); /* gfs quota */ + gfs2_inum_in(&sb->__pad4, (char *)&str->__pad4); /* gfs license */ #ifdef GFS2_HAS_UUID CPIN_08(sb, str, sb_uuid, sizeof(sb->sb_uuid)); #endif @@ -233,7 +238,7 @@ void gfs2_rgrp_in(struct gfs2_rgrp *rg, struct gfs2_buffer_head *bh) CPIN_32(rg, str, rg_free); CPIN_32(rg, str, rg_dinodes); - CPIN_08(rg, str, rg_reserved, 36); + CPIN_08(rg, str, rg_reserved, 80); } void gfs2_rgrp_out(struct gfs2_rgrp *rg, struct gfs2_buffer_head *bh) @@ -245,7 +250,7 @@ void gfs2_rgrp_out(struct gfs2_rgrp *rg, struct gfs2_buffer_head *bh) CPOUT_32(rg, str, rg_free); CPOUT_32(rg, str, rg_dinodes); - CPOUT_08(rg, str, rg_reserved, 36); + CPOUT_08(rg, str, rg_reserved, 80); bmodified(bh); } @@ -343,6 +348,7 @@ void gfs2_dinode_out(struct gfs2_dinode *di, struct gfs2_buffer_head *bh) CPOUT_32(di, str, di_flags); CPOUT_32(di, str, di_payload_format); + CPOUT_16(di, str, __pad1); CPOUT_16(di, str, di_height); CPOUT_16(di, str, di_depth); diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c index 0f34e33..cd3667f 100644 --- a/gfs2/libgfs2/rgrp.c +++ b/gfs2/libgfs2/rgrp.c @@ -156,9 +156,12 @@ uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd) return error; } } - - if (rgd->bh && rgd->bh[0]) - gfs2_rgrp_in(&rgd->rg, rgd->bh[0]); + if (rgd->bh && rgd->bh[0]) { + if (sdp->gfs1) + gfs_rgrp_in((struct gfs_rgrp *)&rgd->rg, rgd->bh[0]); + else + gfs2_rgrp_in(&rgd->rg, rgd->bh[0]); + } return 0; } -- 1.7.7.5