Skip to content

Commit

Permalink
[GFS2] Add generation number
Browse files Browse the repository at this point in the history
This adds a generation number for the eventual use of NFS to the
ondisk inode. Its backward compatible with the current code since
it doesn't really matter what the generation number is to start with,
and indeed since its set to zero, due to it being taken from padding
in both the inode and rgrp header, it should be fine.

The eventual plan is to use this rather than no_formal_ino in the
NFS filehandles. At that point no_formal_ino will be unused.

At the same time we also add a releasepages call back to the
"normal" address space for gfs2 inodes. Also I've removed a
one-linrer function thats not required any more.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
  • Loading branch information
Steven Whitehouse committed Jul 11, 2006
1 parent ffeb874 commit 4340fe6
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 149 deletions.
46 changes: 20 additions & 26 deletions fs/gfs2/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,17 @@
#include "util.h"

/**
* inode_attr_in - Copy attributes from the dinode into the VFS inode
* gfs2_inode_attr_in - Copy attributes from the dinode into the VFS inode
* @ip: The GFS2 inode (with embedded disk inode data)
* @inode: The Linux VFS inode
*
*/

static void inode_attr_in(struct gfs2_inode *ip, struct inode *inode)
void gfs2_inode_attr_in(struct gfs2_inode *ip)
{
inode->i_ino = ip->i_num.no_formal_ino;
struct inode *inode = &ip->i_inode;

inode->i_ino = ip->i_num.no_addr;

switch (ip->i_di.di_mode & S_IFMT) {
case S_IFBLK:
Expand Down Expand Up @@ -84,18 +86,6 @@ static void inode_attr_in(struct gfs2_inode *ip, struct inode *inode)
inode->i_flags &= ~S_APPEND;
}

/**
* gfs2_inode_attr_in - Copy attributes from the dinode into the VFS inode
* @ip: The GFS2 inode (with embedded disk inode data)
*
*/

void gfs2_inode_attr_in(struct gfs2_inode *ip)
{
struct inode *inode = &ip->i_inode;
inode_attr_in(ip, inode);
}

/**
* gfs2_inode_attr_out - Copy attributes from VFS inode into the dinode
* @ip: The GFS2 inode
Expand Down Expand Up @@ -621,7 +611,8 @@ static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode,
*gid = current->fsgid;
}

static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum *inum)
static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum *inum,
u64 *generation)
{
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
int error;
Expand All @@ -637,14 +628,14 @@ static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum *inum)
if (error)
goto out_ipreserv;

inum->no_addr = gfs2_alloc_di(dip);
inum->no_addr = gfs2_alloc_di(dip, generation);

gfs2_trans_end(sdp);

out_ipreserv:
out_ipreserv:
gfs2_inplace_release(dip);

out:
out:
gfs2_alloc_put(dip);

return error;
Expand All @@ -662,8 +653,9 @@ static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum *inum)
*/

static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
struct gfs2_inum *inum, unsigned int mode,
unsigned int uid, unsigned int gid)
const struct gfs2_inum *inum, unsigned int mode,
unsigned int uid, unsigned int gid,
const u64 *generation)
{
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct gfs2_dinode *di;
Expand All @@ -686,7 +678,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(get_seconds());
di->di_major = di->di_minor = cpu_to_be32(0);
di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr);
di->__pad[0] = di->__pad[1] = 0;
di->di_generation = cpu_to_be64(*generation);
di->di_flags = cpu_to_be32(0);

if (S_ISREG(mode)) {
Expand Down Expand Up @@ -717,7 +709,8 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
}

static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
unsigned int mode, struct gfs2_inum *inum)
unsigned int mode, const struct gfs2_inum *inum,
const u64 *generation)
{
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
unsigned int uid, gid;
Expand All @@ -738,7 +731,7 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
if (error)
goto out_quota;

init_dinode(dip, gl, inum, mode, uid, gid);
init_dinode(dip, gl, inum, mode, uid, gid, generation);
gfs2_quota_change(dip, +1, uid, gid);
gfs2_trans_end(sdp);

Expand Down Expand Up @@ -844,6 +837,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct gfs2_inum inum;
int error;
u64 generation;

if (!name->len || name->len > GFS2_FNAMESIZE)
return ERR_PTR(-ENAMETOOLONG);
Expand All @@ -861,7 +855,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
if (error)
goto fail_gunlock;

error = alloc_dinode(dip, &inum);
error = alloc_dinode(dip, &inum, &generation);
if (error)
goto fail_gunlock;

Expand Down Expand Up @@ -893,7 +887,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
goto fail_gunlock;
}

error = make_dinode(dip, ghs[1].gh_gl, mode, &inum);
error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation);
if (error)
goto fail_gunlock2;

Expand Down
112 changes: 2 additions & 110 deletions fs/gfs2/meta_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "rgrp.h"
#include "trans.h"
#include "util.h"
#include "ops_address.h"

#define buffer_busy(bh) \
((bh)->b_state & ((1ul << BH_Dirty) | (1ul << BH_Lock) | (1ul << BH_Pinned)))
Expand All @@ -50,118 +51,9 @@ static int gfs2_aspace_writepage(struct page *page,
return block_write_full_page(page, aspace_get_block, wbc);
}

/**
* stuck_releasepage - We're stuck in gfs2_releasepage(). Print stuff out.
* @bh: the buffer we're stuck on
*
*/

static void stuck_releasepage(struct buffer_head *bh)
{
struct inode *inode = bh->b_page->mapping->host;
struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
struct gfs2_bufdata *bd = bh->b_private;
struct gfs2_glock *gl;

fs_warn(sdp, "stuck in gfs2_releasepage() %p\n", inode);
fs_warn(sdp, "blkno = %llu, bh->b_count = %d\n",
(unsigned long long)bh->b_blocknr, atomic_read(&bh->b_count));
fs_warn(sdp, "pinned = %u\n", buffer_pinned(bh));
fs_warn(sdp, "bh->b_private = %s\n", (bd) ? "!NULL" : "NULL");

if (!bd)
return;

gl = bd->bd_gl;

fs_warn(sdp, "gl = (%u, %llu)\n",
gl->gl_name.ln_type, (unsigned long long)gl->gl_name.ln_number);

fs_warn(sdp, "bd_list_tr = %s, bd_le.le_list = %s\n",
(list_empty(&bd->bd_list_tr)) ? "no" : "yes",
(list_empty(&bd->bd_le.le_list)) ? "no" : "yes");

if (gl->gl_ops == &gfs2_inode_glops) {
struct gfs2_inode *ip = gl->gl_object;
unsigned int x;

if (!ip)
return;

fs_warn(sdp, "ip = %llu %llu\n",
(unsigned long long)ip->i_num.no_formal_ino,
(unsigned long long)ip->i_num.no_addr);

for (x = 0; x < GFS2_MAX_META_HEIGHT; x++)
fs_warn(sdp, "ip->i_cache[%u] = %s\n",
x, (ip->i_cache[x]) ? "!NULL" : "NULL");
}
}

/**
* gfs2_aspace_releasepage - free the metadata associated with a page
* @page: the page that's being released
* @gfp_mask: passed from Linux VFS, ignored by us
*
* Call try_to_free_buffers() if the buffers in this page can be
* released.
*
* Returns: 0
*/

static int gfs2_aspace_releasepage(struct page *page, gfp_t gfp_mask)
{
struct inode *aspace = page->mapping->host;
struct gfs2_sbd *sdp = aspace->i_sb->s_fs_info;
struct buffer_head *bh, *head;
struct gfs2_bufdata *bd;
unsigned long t;

if (!page_has_buffers(page))
goto out;

head = bh = page_buffers(page);
do {
t = jiffies;

while (atomic_read(&bh->b_count)) {
if (atomic_read(&aspace->i_writecount)) {
if (time_after_eq(jiffies, t +
gfs2_tune_get(sdp, gt_stall_secs) * HZ)) {
stuck_releasepage(bh);
t = jiffies;
}

yield();
continue;
}

return 0;
}

gfs2_assert_warn(sdp, !buffer_pinned(bh));

bd = bh->b_private;
if (bd) {
gfs2_assert_warn(sdp, bd->bd_bh == bh);
gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr));
gfs2_assert_warn(sdp, list_empty(&bd->bd_le.le_list));
gfs2_assert_warn(sdp, !bd->bd_ail);
kmem_cache_free(gfs2_bufdata_cachep, bd);
bh->b_private = NULL;
}

bh = bh->b_this_page;
}
while (bh != head);

out:
return try_to_free_buffers(page);
}

static const struct address_space_operations aspace_aops = {
.writepage = gfs2_aspace_writepage,
.releasepage = gfs2_aspace_releasepage,
.releasepage = gfs2_releasepage,
};

/**
Expand Down
6 changes: 5 additions & 1 deletion fs/gfs2/ondisk.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ void gfs2_rgrp_in(struct gfs2_rgrp *rg, char *buf)
rg->rg_flags = be32_to_cpu(str->rg_flags);
rg->rg_free = be32_to_cpu(str->rg_free);
rg->rg_dinodes = be32_to_cpu(str->rg_dinodes);
rg->rg_igeneration = be64_to_cpu(str->rg_igeneration);
}

void gfs2_rgrp_out(struct gfs2_rgrp *rg, char *buf)
Expand All @@ -138,7 +139,8 @@ void gfs2_rgrp_out(struct gfs2_rgrp *rg, char *buf)
str->rg_flags = cpu_to_be32(rg->rg_flags);
str->rg_free = cpu_to_be32(rg->rg_free);
str->rg_dinodes = cpu_to_be32(rg->rg_dinodes);

str->__pad = cpu_to_be32(0);
str->rg_igeneration = cpu_to_be64(rg->rg_igeneration);
memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
}

Expand Down Expand Up @@ -172,6 +174,7 @@ void gfs2_dinode_in(struct gfs2_dinode *di, char *buf)

di->di_goal_meta = be64_to_cpu(str->di_goal_meta);
di->di_goal_data = be64_to_cpu(str->di_goal_data);
di->di_generation = be64_to_cpu(str->di_generation);

di->di_flags = be32_to_cpu(str->di_flags);
di->di_payload_format = be32_to_cpu(str->di_payload_format);
Expand Down Expand Up @@ -205,6 +208,7 @@ void gfs2_dinode_out(struct gfs2_dinode *di, char *buf)

str->di_goal_meta = cpu_to_be64(di->di_goal_meta);
str->di_goal_data = cpu_to_be64(di->di_goal_data);
str->di_generation = cpu_to_be64(di->di_generation);

str->di_flags = cpu_to_be32(di->di_flags);
str->di_payload_format = cpu_to_be32(di->di_payload_format);
Expand Down
Loading

0 comments on commit 4340fe6

Please sign in to comment.