From 629a21e7ecedf779c68dcaa9a186069f57a7c652 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 13 Oct 2006 22:51:24 -0400 Subject: [GFS2] split and annotate gfs2_inum Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse --- fs/gfs2/dir.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'fs/gfs2/dir.c') diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index e24af28b1a12..d67a3760ca30 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -1194,7 +1194,7 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset, int *copied) { const struct gfs2_dirent *dent, *dent_next; - struct gfs2_inum inum; + struct gfs2_inum_host inum; u64 off, off_next; unsigned int x, y; int run = 0; @@ -1456,7 +1456,7 @@ out: */ int gfs2_dir_search(struct inode *dir, const struct qstr *name, - struct gfs2_inum *inum, unsigned int *type) + struct gfs2_inum_host *inum, unsigned int *type) { struct buffer_head *bh; struct gfs2_dirent *dent; @@ -1531,7 +1531,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) */ int gfs2_dir_add(struct inode *inode, const struct qstr *name, - const struct gfs2_inum *inum, unsigned type) + const struct gfs2_inum_host *inum, unsigned type) { struct gfs2_inode *ip = GFS2_I(inode); struct buffer_head *bh; @@ -1666,7 +1666,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name) */ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, - struct gfs2_inum *inum, unsigned int new_type) + struct gfs2_inum_host *inum, unsigned int new_type) { struct buffer_head *bh; struct gfs2_dirent *dent; -- cgit v1.2.1 From b44b84d765b02f813a67b96bf79e3b5d4d621631 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 14 Oct 2006 10:46:30 -0400 Subject: [GFS2] gfs2 misc endianness annotations Signed-off-by: Al Viro Signed-off-by: Steven Whitehouse --- fs/gfs2/dir.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'fs/gfs2/dir.c') diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index d67a3760ca30..59dc823c2833 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -713,12 +713,12 @@ static int get_leaf(struct gfs2_inode *dip, u64 leaf_no, static int get_leaf_nr(struct gfs2_inode *dip, u32 index, u64 *leaf_out) { - u64 leaf_no; + __be64 leaf_no; int error; error = gfs2_dir_read_data(dip, (char *)&leaf_no, - index * sizeof(u64), - sizeof(u64), 0); + index * sizeof(__be64), + sizeof(__be64), 0); if (error != sizeof(u64)) return (error < 0) ? error : -EIO; @@ -837,7 +837,8 @@ static int dir_make_exhash(struct inode *inode) struct gfs2_leaf *leaf; int y; u32 x; - u64 *lp, bn; + __be64 *lp; + u64 bn; int error; error = gfs2_meta_inode_buffer(dip, &dibh); @@ -893,7 +894,7 @@ static int dir_make_exhash(struct inode *inode) gfs2_trans_add_bh(dip->i_gl, dibh, 1); gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); - lp = (u64 *)(dibh->b_data + sizeof(struct gfs2_dinode)); + lp = (__be64 *)(dibh->b_data + sizeof(struct gfs2_dinode)); for (x = sdp->sd_hash_ptrs; x--; lp++) *lp = cpu_to_be64(bn); @@ -929,7 +930,8 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) struct gfs2_leaf *nleaf, *oleaf; struct gfs2_dirent *dent = NULL, *prev = NULL, *next = NULL, *new; u32 start, len, half_len, divider; - u64 bn, *lp, leaf_no; + u64 bn, leaf_no; + __be64 *lp; u32 index; int x, moved = 0; int error; @@ -974,7 +976,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) /* Change the pointers. Don't bother distinguishing stuffed from non-stuffed. This code is complicated enough already. */ - lp = kmalloc(half_len * sizeof(u64), GFP_NOFS | __GFP_NOFAIL); + lp = kmalloc(half_len * sizeof(__be64), GFP_NOFS | __GFP_NOFAIL); /* Change the pointers */ for (x = 0; x < half_len; x++) lp[x] = cpu_to_be64(bn); @@ -1341,7 +1343,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, u32 hsize, len = 0; u32 ht_offset, lp_offset, ht_offset_cur = -1; u32 hash, index; - u64 *lp; + __be64 *lp; int copied = 0; int error = 0; unsigned depth = 0; @@ -1365,7 +1367,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, if (ht_offset_cur != ht_offset) { error = gfs2_dir_read_data(dip, (char *)lp, - ht_offset * sizeof(u64), + ht_offset * sizeof(__be64), sdp->sd_hash_bsize, 1); if (error != sdp->sd_hash_bsize) { if (error >= 0) @@ -1715,7 +1717,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data) u32 hsize, len; u32 ht_offset, lp_offset, ht_offset_cur = -1; u32 index = 0; - u64 *lp; + __be64 *lp; u64 leaf_no; int error = 0; @@ -1735,7 +1737,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data) if (ht_offset_cur != ht_offset) { error = gfs2_dir_read_data(dip, (char *)lp, - ht_offset * sizeof(u64), + ht_offset * sizeof(__be64), sdp->sd_hash_bsize, 1); if (error != sdp->sd_hash_bsize) { if (error >= 0) -- cgit v1.2.1 From 539e5d6b7ae8612c0393fe940d2da5b591318d3d Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 31 Oct 2006 15:07:05 -0500 Subject: [GFS2] Change argument of gfs2_dinode_out Everywhere this was called, a struct gfs2_inode was available, but despite that, it was always called with a struct gfs2_dinode as an argument. By making this change it paves the way to start eliminating fields duplicated between the kernel's struct inode and the struct gfs2_dinode. Signed-off-by: Steven Whitehouse --- fs/gfs2/dir.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'fs/gfs2/dir.c') diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 59dc823c2833..0742761e1e02 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -132,7 +132,7 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf, if (ip->i_di.di_size < offset + size) ip->i_di.di_size = offset + size; ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -232,7 +232,7 @@ out: ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); - gfs2_dinode_out(&ip->i_di, dibh->b_data); + gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); return copied; @@ -907,7 +907,7 @@ static int dir_make_exhash(struct inode *inode) for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ; dip->i_di.di_depth = y; - gfs2_dinode_out(&dip->i_di, dibh->b_data); + gfs2_dinode_out(dip, dibh->b_data); brelse(dibh); @@ -1039,7 +1039,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) error = gfs2_meta_inode_buffer(dip, &dibh); if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) { dip->i_di.di_blocks++; - gfs2_dinode_out(&dip->i_di, dibh->b_data); + gfs2_dinode_out(dip, dibh->b_data); brelse(dibh); } @@ -1119,7 +1119,7 @@ static int dir_double_exhash(struct gfs2_inode *dip) error = gfs2_meta_inode_buffer(dip, &dibh); if (!gfs2_assert_withdraw(sdp, !error)) { dip->i_di.di_depth++; - gfs2_dinode_out(&dip->i_di, dibh->b_data); + gfs2_dinode_out(dip, dibh->b_data); brelse(dibh); } @@ -1517,7 +1517,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) return error; gfs2_trans_add_bh(ip->i_gl, bh, 1); ip->i_di.di_blocks++; - gfs2_dinode_out(&ip->i_di, bh->b_data); + gfs2_dinode_out(ip, bh->b_data); brelse(bh); return 0; } @@ -1561,7 +1561,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name, gfs2_trans_add_bh(ip->i_gl, bh, 1); ip->i_di.di_entries++; ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); - gfs2_dinode_out(&ip->i_di, bh->b_data); + gfs2_dinode_out(ip, bh->b_data); brelse(bh); error = 0; break; @@ -1647,7 +1647,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name) gfs2_trans_add_bh(dip->i_gl, bh, 1); dip->i_di.di_entries--; dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds(); - gfs2_dinode_out(&dip->i_di, bh->b_data); + gfs2_dinode_out(dip, bh->b_data); brelse(bh); mark_inode_dirty(&dip->i_inode); @@ -1695,7 +1695,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, } dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds(); - gfs2_dinode_out(&dip->i_di, bh->b_data); + gfs2_dinode_out(dip, bh->b_data); brelse(bh); return 0; } @@ -1875,7 +1875,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, goto out_end_trans; gfs2_trans_add_bh(dip->i_gl, dibh, 1); - gfs2_dinode_out(&dip->i_di, dibh->b_data); + gfs2_dinode_out(dip, dibh->b_data); brelse(dibh); out_end_trans: -- cgit v1.2.1 From 1a7b1eed5802502fd649e04784becd58557fdcf1 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 1 Nov 2006 14:35:17 -0500 Subject: [GFS2] Shrink gfs2_inode (6) - di_atime/di_mtime/di_ctime Remove the di_[amc]time fields and use inode->i_[amc]time fields instead. This saves 24 bytes from the gfs2_inode. Signed-off-by: Steven Whitehouse --- fs/gfs2/dir.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fs/gfs2/dir.c') diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 0742761e1e02..ca23c8beb3f0 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -131,7 +131,7 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf, memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size); if (ip->i_di.di_size < offset + size) ip->i_di.di_size = offset + size; - ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -229,7 +229,7 @@ out: if (ip->i_di.di_size < offset + copied) ip->i_di.di_size = offset + copied; - ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); @@ -1560,7 +1560,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name, break; gfs2_trans_add_bh(ip->i_gl, bh, 1); ip->i_di.di_entries++; - ip->i_di.di_mtime = ip->i_di.di_ctime = get_seconds(); + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_dinode_out(ip, bh->b_data); brelse(bh); error = 0; @@ -1646,7 +1646,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name) gfs2_consist_inode(dip); gfs2_trans_add_bh(dip->i_gl, bh, 1); dip->i_di.di_entries--; - dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds(); + dip->i_inode.i_mtime.tv_sec = dip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_dinode_out(dip, bh->b_data); brelse(bh); mark_inode_dirty(&dip->i_inode); @@ -1694,7 +1694,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, gfs2_trans_add_bh(dip->i_gl, bh, 1); } - dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds(); + dip->i_inode.i_mtime.tv_sec = dip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_dinode_out(dip, bh->b_data); brelse(bh); return 0; -- cgit v1.2.1 From a9583c7983cbba9726bfe64ee46613d654fc9e26 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 1 Nov 2006 20:09:14 -0500 Subject: [GFS2] Shrink gfs2_inode (7) - di_payload_format This is almost never used. Its there for backward compatibility with GFS1. It doesn't need its own field since it can always be calculated from the inode mode & flags. This saves a bit more space in the gfs2_inode. Signed-off-by: Steven Whitehouse --- fs/gfs2/dir.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs/gfs2/dir.c') diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index ca23c8beb3f0..c82d7cb4a654 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -902,7 +902,6 @@ static int dir_make_exhash(struct inode *inode) dip->i_di.di_size = sdp->sd_sb.sb_bsize / 2; dip->i_di.di_blocks++; dip->i_di.di_flags |= GFS2_DIF_EXHASH; - dip->i_di.di_payload_format = 0; for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ; dip->i_di.di_depth = y; -- cgit v1.2.1 From 9e2dbdac3df300516ffdd9a8631f23164d068a50 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 8 Nov 2006 15:45:46 -0500 Subject: [GFS2] Remove gfs2_inode_attr_in This function wasn't really doing the right thing. There was no need to update the inode size at this point and the updating of the i_blocks field has now been moved to the places where di_blocks is updated. A result of this patch and some those preceeding it is that unlocking a glock is now a much more efficient process, since there is no longer any requirement to copy data from the gfs2 inode into the vfs inode at this point. Signed-off-by: Steven Whitehouse --- fs/gfs2/dir.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'fs/gfs2/dir.c') diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index c82d7cb4a654..a2923fb91bba 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -901,6 +901,7 @@ static int dir_make_exhash(struct inode *inode) dip->i_di.di_size = sdp->sd_sb.sb_bsize / 2; dip->i_di.di_blocks++; + gfs2_set_inode_blocks(&dip->i_inode); dip->i_di.di_flags |= GFS2_DIF_EXHASH; for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ; @@ -1038,6 +1039,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) error = gfs2_meta_inode_buffer(dip, &dibh); if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) { dip->i_di.di_blocks++; + gfs2_set_inode_blocks(&dip->i_inode); gfs2_dinode_out(dip, dibh->b_data); brelse(dibh); } @@ -1516,6 +1518,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) return error; gfs2_trans_add_bh(ip->i_gl, bh, 1); ip->i_di.di_blocks++; + gfs2_set_inode_blocks(&ip->i_inode); gfs2_dinode_out(ip, bh->b_data); brelse(bh); return 0; @@ -1860,6 +1863,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, if (!dip->i_di.di_blocks) gfs2_consist_inode(dip); dip->i_di.di_blocks--; + gfs2_set_inode_blocks(&dip->i_inode); } error = gfs2_dir_write_data(dip, ht, index * sizeof(u64), size); -- cgit v1.2.1 From 5e7d65cd9d3819512b059f4260de0119b985454c Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Fri, 17 Nov 2006 12:27:44 -0500 Subject: [GFS2] Make sentinel dirents compatible with gfs1 When deleting directory entries, we set the inum.no_addr to zero in a dirent when its the first dirent in a block and thus cannot be merged into the previous dirent as is the usual case. In gfs1, inum.no_formal_ino was used instead. This patch changes gfs2 to set both inum.no_addr and inum.no_formal_ino to zero. It also changes the test from just looking at inum.no_addr to look at both inum.no_addr and inum.no_formal_ino and a sentinel is now considered to be a dirent in which _either_ (or both) of them is set to zero. This resolves Red Hat bugzillas: #215809, #211465 Signed-off-by: Steven Whitehouse --- fs/gfs2/dir.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'fs/gfs2/dir.c') diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index a2923fb91bba..0fdcb7713cd9 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -340,10 +340,15 @@ fail: return (copied) ? copied : error; } +static inline int gfs2_dirent_sentinel(const struct gfs2_dirent *dent) +{ + return dent->de_inum.no_addr == 0 || dent->de_inum.no_formal_ino == 0; +} + static inline int __gfs2_dirent_find(const struct gfs2_dirent *dent, const struct qstr *name, int ret) { - if (dent->de_inum.no_addr != 0 && + if (!gfs2_dirent_sentinel(dent) && be32_to_cpu(dent->de_hash) == name->hash && be16_to_cpu(dent->de_name_len) == name->len && memcmp(dent+1, name->name, name->len) == 0) @@ -388,7 +393,7 @@ static int gfs2_dirent_find_space(const struct gfs2_dirent *dent, unsigned actual = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len)); unsigned totlen = be16_to_cpu(dent->de_rec_len); - if (!dent->de_inum.no_addr) + if (gfs2_dirent_sentinel(dent)) actual = GFS2_DIRENT_SIZE(0); if (totlen - actual >= required) return 1; @@ -405,7 +410,7 @@ static int gfs2_dirent_gather(const struct gfs2_dirent *dent, void *opaque) { struct dirent_gather *g = opaque; - if (dent->de_inum.no_addr) { + if (!gfs2_dirent_sentinel(dent)) { g->pdent[g->offset++] = dent; } return 0; @@ -433,10 +438,10 @@ static int gfs2_check_dirent(struct gfs2_dirent *dent, unsigned int offset, if (unlikely(offset + size > len)) goto error; msg = "zero inode number"; - if (unlikely(!first && !dent->de_inum.no_addr)) + if (unlikely(!first && gfs2_dirent_sentinel(dent))) goto error; msg = "name length is greater than space in dirent"; - if (dent->de_inum.no_addr && + if (!gfs2_dirent_sentinel(dent) && unlikely(sizeof(struct gfs2_dirent)+be16_to_cpu(dent->de_name_len) > size)) goto error; @@ -598,7 +603,7 @@ static int dirent_next(struct gfs2_inode *dip, struct buffer_head *bh, return ret; /* Only the first dent could ever have de_inum.no_addr == 0 */ - if (!tmp->de_inum.no_addr) { + if (gfs2_dirent_sentinel(tmp)) { gfs2_consist_inode(dip); return -EIO; } @@ -621,7 +626,7 @@ static void dirent_del(struct gfs2_inode *dip, struct buffer_head *bh, { u16 cur_rec_len, prev_rec_len; - if (!cur->de_inum.no_addr) { + if (gfs2_dirent_sentinel(cur)) { gfs2_consist_inode(dip); return; } @@ -633,7 +638,8 @@ static void dirent_del(struct gfs2_inode *dip, struct buffer_head *bh, out the inode number and return. */ if (!prev) { - cur->de_inum.no_addr = 0; /* No endianess worries */ + cur->de_inum.no_addr = 0; + cur->de_inum.no_formal_ino = 0; return; } @@ -664,7 +670,7 @@ static struct gfs2_dirent *gfs2_init_dirent(struct inode *inode, struct gfs2_dirent *ndent; unsigned offset = 0, totlen; - if (dent->de_inum.no_addr) + if (!gfs2_dirent_sentinel(dent)) offset = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len)); totlen = be16_to_cpu(dent->de_rec_len); BUG_ON(offset + name->len > totlen); @@ -1002,7 +1008,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) if (dirent_next(dip, obh, &next)) next = NULL; - if (dent->de_inum.no_addr && + if (!gfs2_dirent_sentinel(dent) && be32_to_cpu(dent->de_hash) < divider) { struct qstr str; str.name = (char*)(dent+1); -- cgit v1.2.1