Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitdiff... Commit: 69e10fb140f531c3c9f5208522e09638b7e09d3d Parent: 3acf36d2b12572711ba83fea6fde7f7b7ffe8242 Author: Bob Peterson rpeterso@redhat.com AuthorDate: Wed Aug 10 16:28:02 2011 -0500 Committer: Bob Peterson rpeterso@redhat.com CommitterDate: Mon Aug 29 12:55:36 2011 -0500
libgfs2: expand capabilities to operate on gfs1
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 | 19 +++++++- gfs2/libgfs2/ondisk.c | 10 +++- gfs2/libgfs2/rgrp.c | 9 ++- 5 files changed, 250 insertions(+), 27 deletions(-)
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c index 4c8d31e..629729d 100644 --- a/gfs2/libgfs2/fs_ops.c +++ b/gfs2/libgfs2/fs_ops.c @@ -179,7 +179,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; @@ -233,7 +236,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) { @@ -830,6 +833,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)) @@ -843,6 +848,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)); @@ -893,8 +902,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");
@@ -1241,13 +1260,21 @@ int dir_add(struct gfs2_inode *dip, const char *filename, int len, return err; }
-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)); @@ -1262,7 +1289,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)); @@ -1270,14 +1297,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 + @@ -1303,8 +1330,25 @@ 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; @@ -1312,12 +1356,16 @@ struct gfs2_inode *createi(struct gfs2_inode *dip, const char *filename, struct gfs2_buffer_head *bh; struct gfs2_inode *ip; int err = 0; + 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;
err = dir_add(dip, filename, strlen(filename), &inum, IF2DT(mode)); @@ -1326,12 +1374,17 @@ struct gfs2_inode *createi(struct gfs2_inode *dip, const char *filename, return NULL; }
- 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); } @@ -1339,6 +1392,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 @@ -1552,7 +1617,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) @@ -1638,7 +1703,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) @@ -1695,7 +1760,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--; } } @@ -1759,7 +1827,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 394cc47..2bd5282 100644 --- a/gfs2/libgfs2/gfs1.c +++ b/gfs2/libgfs2/gfs1.c @@ -6,6 +6,7 @@ #include <string.h> #include <stdint.h> #include <inttypes.h> +#include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> @@ -33,6 +34,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) @@ -161,6 +169,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 */ /* ------------------------------------------------------------------------ */ @@ -303,3 +403,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 c92781a..7f529d6 100644 --- a/gfs2/libgfs2/libgfs2.h +++ b/gfs2/libgfs2/libgfs2.h @@ -176,6 +176,7 @@ struct gfs2_sbd { unsigned int bsize; /* The block size of the FS (in bytes) */ unsigned int jsize; /* Size of journals (in MB) */ unsigned int rgsize; /* Size of resource groups (in MB) */ + unsigned int utsize; /* Size of unlinked tag files (in MB) */ unsigned int qcsize; /* Size of quota change files (in MB) */
int debug; @@ -254,6 +255,7 @@ struct metapath { #define GFS2_DEFAULT_BSIZE (4096) #define GFS2_DEFAULT_JSIZE (128) #define GFS2_DEFAULT_RGSIZE (256) +#define GFS2_DEFAULT_UTSIZE (1) #define GFS2_DEFAULT_QCSIZE (1) #define GFS2_DEFAULT_LOCKPROTO "lock_dlm" #define GFS2_MIN_GROW_SIZE (10) @@ -370,8 +372,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, @@ -581,13 +591,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); @@ -596,6 +608,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 { @@ -684,6 +700,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 d889e2b..adbf4e9 100644 --- a/gfs2/libgfs2/ondisk.c +++ b/gfs2/libgfs2/ondisk.c @@ -100,15 +100,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 @@ -235,7 +240,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) @@ -247,7 +252,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); }
@@ -345,6 +350,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 2ec55b5..97f22bb 100644 --- a/gfs2/libgfs2/rgrp.c +++ b/gfs2/libgfs2/rgrp.c @@ -158,9 +158,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; }