Skip to content

Commit

Permalink
[GFS2] Clean up inode number handling
Browse files Browse the repository at this point in the history
This patch cleans up the inode number handling code. The main difference
is that instead of looking up the inodes using a struct gfs2_inum_host
we now use just the no_addr member of this structure. The tests relating
to no_formal_ino can then be done by the calling code. This has
advantages in that we want to do different things in different code
paths if the no_formal_ino doesn't match. In the NFS patch we want to
return -ESTALE, but in the ->lookup() path, its a bug in the fs if the
no_formal_ino doesn't match and thus we can withdraw in this case.

In order to later fix bz #201012, we need to be able to look up an inode
without knowing no_formal_ino, as the only information that is known to
us is the on-disk location of the inode in question.

This patch will also help us to fix bz #236099 at a later date by
cleaning up a lot of the code in that area.

There are no user visible changes as a result of this patch and there
are no changes to the on-disk format either.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
  • Loading branch information
Steven Whitehouse committed Jul 9, 2007
1 parent 41d7db0 commit dbb7cae
Show file tree
Hide file tree
Showing 19 changed files with 162 additions and 170 deletions.
2 changes: 1 addition & 1 deletion fs/gfs2/bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1040,7 +1040,7 @@ static int trunc_end(struct gfs2_inode *ip)
ip->i_di.di_height = 0;
ip->i_di.di_goal_meta =
ip->i_di.di_goal_data =
ip->i_num.no_addr;
ip->i_no_addr;
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
}
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
Expand Down
56 changes: 43 additions & 13 deletions fs/gfs2/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1456,7 +1456,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
if (dip->i_di.di_entries != g.offset) {
fs_warn(sdp, "Number of entries corrupt in dir %llu, "
"ip->i_di.di_entries (%u) != g.offset (%u)\n",
(unsigned long long)dip->i_num.no_addr,
(unsigned long long)dip->i_no_addr,
dip->i_di.di_entries,
g.offset);
error = -EIO;
Expand Down Expand Up @@ -1488,24 +1488,54 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
* Returns: errno
*/

int gfs2_dir_search(struct inode *dir, const struct qstr *name,
struct gfs2_inum_host *inum, unsigned int *type)
struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name)
{
struct buffer_head *bh;
struct gfs2_dirent *dent;
struct inode *inode;

dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
if (dent) {
if (IS_ERR(dent))
return ERR_PTR(PTR_ERR(dent));
inode = gfs2_inode_lookup(dir->i_sb,
be64_to_cpu(dent->de_inum.no_addr),
be16_to_cpu(dent->de_type));
brelse(bh);
return inode;
}
return ERR_PTR(-ENOENT);
}

int gfs2_dir_check(struct inode *dir, const struct qstr *name,
const struct gfs2_inode *ip)
{
struct buffer_head *bh;
struct gfs2_dirent *dent;
int ret = -ENOENT;

dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
if (dent) {
if (IS_ERR(dent))
return PTR_ERR(dent);
if (inum)
gfs2_inum_in(inum, (char *)&dent->de_inum);
if (type)
*type = be16_to_cpu(dent->de_type);
if (ip) {
if (be64_to_cpu(dent->de_inum.no_addr) != ip->i_no_addr)
goto out;
if (be64_to_cpu(dent->de_inum.no_formal_ino) !=
ip->i_no_formal_ino)
goto out;
if (unlikely(IF2DT(ip->i_inode.i_mode) !=
be16_to_cpu(dent->de_type))) {
gfs2_consist_inode(GFS2_I(dir));
ret = -EIO;
goto out;
}
}
ret = 0;
out:
brelse(bh);
return 0;
}
return -ENOENT;
return ret;
}

static int dir_new_leaf(struct inode *inode, const struct qstr *name)
Expand Down Expand Up @@ -1565,7 +1595,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_host *inum, unsigned type)
const struct gfs2_inode *nip, unsigned type)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct buffer_head *bh;
Expand All @@ -1580,7 +1610,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
if (IS_ERR(dent))
return PTR_ERR(dent);
dent = gfs2_init_dirent(inode, dent, name, bh);
gfs2_inum_out(inum, (char *)&dent->de_inum);
gfs2_inum_out(nip, dent);
dent->de_type = cpu_to_be16(type);
if (ip->i_di.di_flags & GFS2_DIF_EXHASH) {
leaf = (struct gfs2_leaf *)bh->b_data;
Expand Down Expand Up @@ -1700,7 +1730,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_host *inum, unsigned int new_type)
const struct gfs2_inode *nip, unsigned int new_type)
{
struct buffer_head *bh;
struct gfs2_dirent *dent;
Expand All @@ -1715,7 +1745,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
return PTR_ERR(dent);

gfs2_trans_add_bh(dip->i_gl, bh, 1);
gfs2_inum_out(inum, (char *)&dent->de_inum);
gfs2_inum_out(nip, dent);
dent->de_type = cpu_to_be16(new_type);

if (dip->i_di.di_flags & GFS2_DIF_EXHASH) {
Expand Down
9 changes: 5 additions & 4 deletions fs/gfs2/dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ struct inode;
struct gfs2_inode;
struct gfs2_inum;

int gfs2_dir_search(struct inode *dir, const struct qstr *filename,
struct gfs2_inum_host *inum, unsigned int *type);
struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *filename);
int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
const struct gfs2_inode *ip);
int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
const struct gfs2_inum_host *inum, unsigned int type);
const struct gfs2_inode *ip, unsigned int type);
int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
filldir_t filldir);
int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
struct gfs2_inum_host *new_inum, unsigned int new_type);
const struct gfs2_inode *nip, unsigned int new_type);

int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);

Expand Down
4 changes: 2 additions & 2 deletions fs/gfs2/glock.c
Original file line number Diff line number Diff line change
Expand Up @@ -1823,8 +1823,8 @@ static int dump_inode(struct glock_iter *gi, struct gfs2_inode *ip)

print_dbg(gi, " Inode:\n");
print_dbg(gi, " num = %llu/%llu\n",
(unsigned long long)ip->i_num.no_formal_ino,
(unsigned long long)ip->i_num.no_addr);
(unsigned long long)ip->i_no_formal_ino,
(unsigned long long)ip->i_no_addr);
print_dbg(gi, " type = %u\n", IF2DT(ip->i_inode.i_mode));
print_dbg(gi, " i_flags =");
for (x = 0; x < 32; x++)
Expand Down
4 changes: 2 additions & 2 deletions fs/gfs2/incore.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ enum {

struct gfs2_inode {
struct inode i_inode;
struct gfs2_inum_host i_num;

u64 i_no_addr;
u64 i_no_formal_ino;
unsigned long i_flags; /* GIF_... */

struct gfs2_dinode_host i_di; /* To be replaced by ref to block */
Expand Down
80 changes: 31 additions & 49 deletions fs/gfs2/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@
static int iget_test(struct inode *inode, void *opaque)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_inum_host *inum = opaque;
u64 *no_addr = opaque;

if (ip->i_num.no_addr == inum->no_addr &&
if (ip->i_no_addr == *no_addr &&
inode->i_private != NULL)
return 1;

Expand All @@ -53,37 +53,37 @@ static int iget_test(struct inode *inode, void *opaque)
static int iget_set(struct inode *inode, void *opaque)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_inum_host *inum = opaque;
u64 *no_addr = opaque;

ip->i_num = *inum;
inode->i_ino = inum->no_addr;
inode->i_ino = (unsigned long)*no_addr;
ip->i_no_addr = *no_addr;
return 0;
}

struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum)
struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr)
{
return ilookup5(sb, (unsigned long)inum->no_addr,
iget_test, inum);
unsigned long hash = (unsigned long)no_addr;
return ilookup5(sb, hash, iget_test, &no_addr);
}

static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum_host *inum)
static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr)
{
return iget5_locked(sb, (unsigned long)inum->no_addr,
iget_test, iget_set, inum);
unsigned long hash = (unsigned long)no_addr;
return iget5_locked(sb, hash, iget_test, iget_set, &no_addr);
}

/**
* gfs2_inode_lookup - Lookup an inode
* @sb: The super block
* @inum: The inode number
* @no_addr: The inode number
* @type: The type of the inode
*
* Returns: A VFS inode, or an error
*/

struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned int type)
struct inode *gfs2_inode_lookup(struct super_block *sb, u64 no_addr, unsigned int type)
{
struct inode *inode = gfs2_iget(sb, inum);
struct inode *inode = gfs2_iget(sb, no_addr);
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_glock *io_gl;
int error;
Expand All @@ -110,12 +110,12 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *i
inode->i_op = &gfs2_dev_iops;
}

error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
if (unlikely(error))
goto fail;
ip->i_gl->gl_object = ip;

error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
if (unlikely(error))
goto fail_put;

Expand Down Expand Up @@ -144,14 +144,12 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
struct gfs2_dinode_host *di = &ip->i_di;
const struct gfs2_dinode *str = buf;

if (ip->i_num.no_addr != be64_to_cpu(str->di_num.no_addr)) {
if (ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)) {
if (gfs2_consist_inode(ip))
gfs2_dinode_print(ip);
return -EIO;
}
if (ip->i_num.no_formal_ino != be64_to_cpu(str->di_num.no_formal_ino))
return -ESTALE;

ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino);
ip->i_inode.i_mode = be32_to_cpu(str->di_mode);
ip->i_inode.i_rdev = 0;
switch (ip->i_inode.i_mode & S_IFMT) {
Expand Down Expand Up @@ -247,7 +245,7 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip)
if (error)
goto out_qs;

rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
if (!rgd) {
gfs2_consist_inode(ip);
error = -EIO;
Expand Down Expand Up @@ -366,8 +364,6 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
struct super_block *sb = dir->i_sb;
struct gfs2_inode *dip = GFS2_I(dir);
struct gfs2_holder d_gh;
struct gfs2_inum_host inum;
unsigned int type;
int error;
struct inode *inode = NULL;
int unlock = 0;
Expand Down Expand Up @@ -395,12 +391,9 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
goto out;
}

error = gfs2_dir_search(dir, name, &inum, &type);
if (error)
goto out;

inode = gfs2_inode_lookup(sb, &inum, type);

inode = gfs2_dir_search(dir, name);
if (IS_ERR(inode))
error = PTR_ERR(inode);
out:
if (unlock)
gfs2_glock_dq_uninit(&d_gh);
Expand Down Expand Up @@ -548,7 +541,7 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
if (!dip->i_inode.i_nlink)
return -EPERM;

error = gfs2_dir_search(&dip->i_inode, name, NULL, NULL);
error = gfs2_dir_check(&dip->i_inode, name, NULL);
switch (error) {
case -ENOENT:
error = 0;
Expand Down Expand Up @@ -588,8 +581,7 @@ 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_host *inum,
u64 *generation)
static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
{
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
int error;
Expand All @@ -605,7 +597,7 @@ static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum_host *inum,
if (error)
goto out_ipreserv;

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

gfs2_trans_end(sdp);

Expand Down Expand Up @@ -760,7 +752,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
goto fail_quota_locks;
}

error = gfs2_dir_add(&dip->i_inode, name, &ip->i_num, IF2DT(ip->i_inode.i_mode));
error = gfs2_dir_add(&dip->i_inode, name, ip, IF2DT(ip->i_inode.i_mode));
if (error)
goto fail_end_trans;

Expand Down Expand Up @@ -844,7 +836,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
struct gfs2_inode *dip = ghs->gh_gl->gl_object;
struct inode *dir = &dip->i_inode;
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct gfs2_inum_host inum;
struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 };
int error;
u64 generation;

Expand All @@ -864,7 +856,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
if (error)
goto fail_gunlock;

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

Expand All @@ -877,7 +869,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
if (error)
goto fail_gunlock2;

inode = gfs2_inode_lookup(dir->i_sb, &inum, IF2DT(mode));
inode = gfs2_inode_lookup(dir->i_sb, inum.no_addr, IF2DT(mode));
if (IS_ERR(inode))
goto fail_gunlock2;

Expand Down Expand Up @@ -976,10 +968,8 @@ int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
*/

int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
struct gfs2_inode *ip)
const struct gfs2_inode *ip)
{
struct gfs2_inum_host inum;
unsigned int type;
int error;

if (IS_IMMUTABLE(&ip->i_inode) || IS_APPEND(&ip->i_inode))
Expand All @@ -997,18 +987,10 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
if (error)
return error;

error = gfs2_dir_search(&dip->i_inode, name, &inum, &type);
error = gfs2_dir_check(&dip->i_inode, name, ip);
if (error)
return error;

if (!gfs2_inum_equal(&inum, &ip->i_num))
return -ENOENT;

if (IF2DT(ip->i_inode.i_mode) != type) {
gfs2_consist_inode(dip);
return -EIO;
}

return 0;
}

Expand Down
Loading

0 comments on commit dbb7cae

Please sign in to comment.