/*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License v.2.
+ * of the GNU General Public License version 2.
*/
/*
-* Implements Extendible Hashing as described in:
-* "Extendible Hashing" by Fagin, et al in
-* __ACM Trans. on Database Systems__, Sept 1979.
-*
-*
-* Here's the layout of dirents which is essentially the same as that of ext2
-* within a single block. The field de_name_len is the number of bytes
-* actually required for the name (no null terminator). The field de_rec_len
-* is the number of bytes allocated to the dirent. The offset of the next
-* dirent in the block is (dirent + dirent->de_rec_len). When a dirent is
-* deleted, the preceding dirent inherits its allocated space, ie
-* prev->de_rec_len += deleted->de_rec_len. Since the next dirent is obtained
-* by adding de_rec_len to the current dirent, this essentially causes the
-* deleted dirent to get jumped over when iterating through all the dirents.
-*
-* When deleting the first dirent in a block, there is no previous dirent so
-* the field de_ino is set to zero to designate it as deleted. When allocating
-* a dirent, gfs2_dirent_alloc iterates through the dirents in a block. If the
-* first dirent has (de_ino == 0) and de_rec_len is large enough, this first
-* dirent is allocated. Otherwise it must go through all the 'used' dirents
-* searching for one in which the amount of total space minus the amount of
-* used space will provide enough space for the new dirent.
-*
-* There are two types of blocks in which dirents reside. In a stuffed dinode,
-* the dirents begin at offset sizeof(struct gfs2_dinode) from the beginning of
-* the block. In leaves, they begin at offset sizeof(struct gfs2_leaf) from the
-* beginning of the leaf block. The dirents reside in leaves when
-*
-* dip->i_di.di_flags & GFS2_DIF_EXHASH is true
-*
-* Otherwise, the dirents are "linear", within a single stuffed dinode block.
-*
-* When the dirents are in leaves, the actual contents of the directory file are
-* used as an array of 64-bit block pointers pointing to the leaf blocks. The
-* dirents are NOT in the directory file itself. There can be more than one block
-* pointer in the array that points to the same leaf. In fact, when a directory
-* is first converted from linear to exhash, all of the pointers point to the
-* same leaf.
-*
-* When a leaf is completely full, the size of the hash table can be
-* doubled unless it is already at the maximum size which is hard coded into
-* GFS2_DIR_MAX_DEPTH. After that, leaves are chained together in a linked list,
-* but never before the maximum hash table size has been reached.
-*/
+ * Implements Extendible Hashing as described in:
+ * "Extendible Hashing" by Fagin, et al in
+ * __ACM Trans. on Database Systems__, Sept 1979.
+ *
+ *
+ * Here's the layout of dirents which is essentially the same as that of ext2
+ * within a single block. The field de_name_len is the number of bytes
+ * actually required for the name (no null terminator). The field de_rec_len
+ * is the number of bytes allocated to the dirent. The offset of the next
+ * dirent in the block is (dirent + dirent->de_rec_len). When a dirent is
+ * deleted, the preceding dirent inherits its allocated space, ie
+ * prev->de_rec_len += deleted->de_rec_len. Since the next dirent is obtained
+ * by adding de_rec_len to the current dirent, this essentially causes the
+ * deleted dirent to get jumped over when iterating through all the dirents.
+ *
+ * When deleting the first dirent in a block, there is no previous dirent so
+ * the field de_ino is set to zero to designate it as deleted. When allocating
+ * a dirent, gfs2_dirent_alloc iterates through the dirents in a block. If the
+ * first dirent has (de_ino == 0) and de_rec_len is large enough, this first
+ * dirent is allocated. Otherwise it must go through all the 'used' dirents
+ * searching for one in which the amount of total space minus the amount of
+ * used space will provide enough space for the new dirent.
+ *
+ * There are two types of blocks in which dirents reside. In a stuffed dinode,
+ * the dirents begin at offset sizeof(struct gfs2_dinode) from the beginning of
+ * the block. In leaves, they begin at offset sizeof(struct gfs2_leaf) from the
+ * beginning of the leaf block. The dirents reside in leaves when
+ *
+ * dip->i_di.di_flags & GFS2_DIF_EXHASH is true
+ *
+ * Otherwise, the dirents are "linear", within a single stuffed dinode block.
+ *
+ * When the dirents are in leaves, the actual contents of the directory file are
+ * used as an array of 64-bit block pointers pointing to the leaf blocks. The
+ * dirents are NOT in the directory file itself. There can be more than one
+ * block pointer in the array that points to the same leaf. In fact, when a
+ * directory is first converted from linear to exhash, all of the pointers
+ * point to the same leaf.
+ *
+ * When a leaf is completely full, the size of the hash table can be
+ * doubled unless it is already at the maximum size which is hard coded into
+ * GFS2_DIR_MAX_DEPTH. After that, leaves are chained together in a linked list,
+ * but never before the maximum hash table size has been reached.
+ */
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include <linux/completion.h>
#include <linux/buffer_head.h>
#include <linux/sort.h>
#include <linux/gfs2_ondisk.h>
#include <linux/crc32.h>
-#include <asm/semaphore.h>
+#include <linux/vmalloc.h>
#include "gfs2.h"
#include "lm_interface.h"
#define IS_LEAF 1 /* Hashed (leaf) directory */
#define IS_DINODE 2 /* Linear (stuffed dinode block) directory */
-#if 1
-#define gfs2_disk_hash2offset(h) (((uint64_t)(h)) >> 1)
-#define gfs2_dir_offset2hash(p) ((uint32_t)(((uint64_t)(p)) << 1))
-#else
-#define gfs2_disk_hash2offset(h) (((uint64_t)(h)))
-#define gfs2_dir_offset2hash(p) ((uint32_t)(((uint64_t)(p))))
-#endif
+#define gfs2_disk_hash2offset(h) (((u64)(h)) >> 1)
+#define gfs2_dir_offset2hash(p) ((u32)(((u64)(p)) << 1))
typedef int (*leaf_call_t) (struct gfs2_inode *dip,
- uint32_t index, uint32_t len, uint64_t leaf_no,
+ u32 index, u32 len, u64 leaf_no,
void *data);
-int gfs2_dir_get_buffer(struct gfs2_inode *ip, uint64_t block, int new,
- struct buffer_head **bhp)
+
+int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
+ struct buffer_head **bhp)
{
struct buffer_head *bh;
- int error = 0;
-
- if (new) {
- bh = gfs2_meta_new(ip->i_gl, block);
- gfs2_trans_add_bh(ip->i_gl, bh, 1);
- gfs2_metatype_set(bh, GFS2_METATYPE_JD, GFS2_FORMAT_JD);
- gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
- } else {
- error = gfs2_meta_read(ip->i_gl, block, DIO_START | DIO_WAIT,
- &bh);
- if (error)
- return error;
- if (gfs2_metatype_check(ip->i_sbd, bh, GFS2_METATYPE_JD)) {
- brelse(bh);
- return -EIO;
- }
- }
+ bh = gfs2_meta_new(ip->i_gl, block);
+ gfs2_trans_add_bh(ip->i_gl, bh, 1);
+ gfs2_metatype_set(bh, GFS2_METATYPE_JD, GFS2_FORMAT_JD);
+ gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
*bhp = bh;
return 0;
}
+static int gfs2_dir_get_existing_buffer(struct gfs2_inode *ip, u64 block,
+ struct buffer_head **bhp)
+{
+ struct buffer_head *bh;
+ int error;
+ error = gfs2_meta_read(ip->i_gl, block, DIO_START | DIO_WAIT, &bh);
+ if (error)
+ return error;
+ if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh, GFS2_METATYPE_JD)) {
+ brelse(bh);
+ return -EIO;
+ }
+ *bhp = bh;
+ return 0;
+}
static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
unsigned int offset, unsigned int size)
* Returns: The number of bytes correctly written or error code
*/
static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
- uint64_t offset, unsigned int size)
+ u64 offset, unsigned int size)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct buffer_head *dibh;
- uint64_t lblock, dblock;
- uint32_t extlen = 0;
+ u64 lblock, dblock;
+ u32 extlen = 0;
unsigned int o;
int copied = 0;
int error = 0;
return -EINVAL;
if (gfs2_is_stuffed(ip)) {
- error = gfs2_unstuff_dinode(ip, NULL, NULL);
+ error = gfs2_unstuff_dinode(ip, NULL);
if (error)
return error;
}
if (!extlen) {
new = 1;
- error = gfs2_block_map(ip, lblock, &new, &dblock,
- &extlen);
+ error = gfs2_extent_map(&ip->i_inode, lblock, &new,
+ &dblock, &extlen);
if (error)
goto fail;
error = -EIO;
goto fail;
}
- error = gfs2_dir_get_buffer(ip, dblock,
- (amount == sdp->sd_jbsize) ?
- 1 : new, &bh);
+ if (amount == sdp->sd_jbsize || new)
+ error = gfs2_dir_get_new_buffer(ip, dblock, &bh);
+ else
+ error = gfs2_dir_get_existing_buffer(ip, dblock, &bh);
+
if (error)
goto fail;
if (error)
goto fail;
+ buf += amount;
copied += amount;
lblock++;
dblock++;
* Returns: The amount of data actually copied or the error
*/
static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf,
- uint64_t offset, unsigned int size)
+ u64 offset, unsigned int size)
{
- struct gfs2_sbd *sdp = ip->i_sbd;
- uint64_t lblock, dblock;
- uint32_t extlen = 0;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ u64 lblock, dblock;
+ u32 extlen = 0;
unsigned int o;
int copied = 0;
int error = 0;
if (!extlen) {
new = 0;
- error = gfs2_block_map(ip, lblock, &new, &dblock,
- &extlen);
+ error = gfs2_extent_map(&ip->i_inode, lblock, &new,
+ &dblock, &extlen);
if (error)
goto fail;
}
gfs2_meta_ra(ip->i_gl, dblock, extlen);
if (dblock) {
- error = gfs2_dir_get_buffer(ip, dblock, new, &bh);
+ if (new)
+ error = gfs2_dir_get_new_buffer(ip, dblock, &bh);
+ else
+ error = gfs2_dir_get_existing_buffer(ip, dblock, &bh);
if (error)
goto fail;
dblock++;
if (error)
goto fail;
+ buf += amount;
copied += amount;
lblock++;
}
consist_inode:
- gfs2_consist_inode(inode->u.generic_ip);
+ gfs2_consist_inode(GFS2_I(inode));
return ERR_PTR(-EIO);
}
struct gfs2_meta_header *h = (struct gfs2_meta_header *)bh->b_data;
if (be32_to_cpu(h->mh_type) == GFS2_METATYPE_LF) {
- if (gfs2_meta_check(dip->i_sbd, bh))
+ if (gfs2_meta_check(GFS2_SB(&dip->i_inode), bh))
return -EIO;
*dent = (struct gfs2_dirent *)(bh->b_data +
sizeof(struct gfs2_leaf));
return IS_LEAF;
} else {
- if (gfs2_metatype_check(dip->i_sbd, bh, GFS2_METATYPE_DI))
+ if (gfs2_metatype_check(GFS2_SB(&dip->i_inode), bh, GFS2_METATYPE_DI))
return -EIO;
*dent = (struct gfs2_dirent *)(bh->b_data +
sizeof(struct gfs2_dinode));
{
struct gfs2_dirent *tmp, *cur;
char *bh_end;
- uint16_t cur_rec_len;
+ u16 cur_rec_len;
cur = *dent;
bh_end = bh->b_data + bh->b_size;
static void dirent_del(struct gfs2_inode *dip, struct buffer_head *bh,
struct gfs2_dirent *prev, struct gfs2_dirent *cur)
{
- uint16_t cur_rec_len, prev_rec_len;
+ u16 cur_rec_len, prev_rec_len;
if (!cur->de_inum.no_addr) {
gfs2_consist_inode(dip);
* Takes a dent from which to grab space as an argument. Returns the
* newly created dent.
*/
-struct gfs2_dirent *gfs2_init_dirent(struct inode *inode,
- struct gfs2_dirent *dent,
- const struct qstr *name,
- struct buffer_head *bh)
+static struct gfs2_dirent *gfs2_init_dirent(struct inode *inode,
+ struct gfs2_dirent *dent,
+ const struct qstr *name,
+ struct buffer_head *bh)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_dirent *ndent;
unsigned offset = 0, totlen;
return gfs2_init_dirent(inode, dent, name, bh);
}
-static int get_leaf(struct gfs2_inode *dip, uint64_t leaf_no,
+static int get_leaf(struct gfs2_inode *dip, u64 leaf_no,
struct buffer_head **bhp)
{
int error;
error = gfs2_meta_read(dip->i_gl, leaf_no, DIO_START | DIO_WAIT, bhp);
- if (!error && gfs2_metatype_check(dip->i_sbd, *bhp, GFS2_METATYPE_LF))
+ if (!error && gfs2_metatype_check(GFS2_SB(&dip->i_inode), *bhp, GFS2_METATYPE_LF)) {
+ /* printk(KERN_INFO "block num=%llu\n", leaf_no); */
error = -EIO;
+ }
return error;
}
* Returns: 0 on success, error code otherwise
*/
-static int get_leaf_nr(struct gfs2_inode *dip, uint32_t index,
- uint64_t *leaf_out)
+static int get_leaf_nr(struct gfs2_inode *dip, u32 index,
+ u64 *leaf_out)
{
- uint64_t leaf_no;
+ u64 leaf_no;
int error;
error = gfs2_dir_read_data(dip, (char *)&leaf_no,
- index * sizeof(uint64_t),
- sizeof(uint64_t));
- if (error != sizeof(uint64_t))
+ index * sizeof(u64),
+ sizeof(u64));
+ if (error != sizeof(u64))
return (error < 0) ? error : -EIO;
*leaf_out = be64_to_cpu(leaf_no);
return 0;
}
-static int get_first_leaf(struct gfs2_inode *dip, uint32_t index,
+static int get_first_leaf(struct gfs2_inode *dip, u32 index,
struct buffer_head **bh_out)
{
- uint64_t leaf_no;
+ u64 leaf_no;
int error;
error = get_leaf_nr(dip, index, &leaf_no);
{
struct buffer_head *bh;
struct gfs2_dirent *dent;
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
int error;
if (ip->i_di.di_flags & GFS2_DIF_EXHASH) {
gfs2_consist_inode(ip);
return ERR_PTR(-EIO);
}
-
+
index = name->hash >> (32 - ip->i_di.di_depth);
error = get_first_leaf(ip, index, &bh);
if (error)
brelse(bh);
if (!ln)
break;
+
error = get_leaf(ip, ln, &bh);
} while(!error);
return error ? ERR_PTR(error) : NULL;
}
+
error = gfs2_meta_inode_buffer(ip, &bh);
if (error)
return ERR_PTR(error);
static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, u16 depth)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
u64 bn = gfs2_alloc_meta(ip);
struct buffer_head *bh = gfs2_meta_new(ip->i_gl, bn);
struct gfs2_leaf *leaf;
struct qstr name = { .name = "", .len = 0, .hash = 0 };
if (!bh)
return NULL;
+
gfs2_trans_add_bh(ip->i_gl, bh, 1);
gfs2_metatype_set(bh, GFS2_METATYPE_LF, GFS2_FORMAT_LF);
leaf = (struct gfs2_leaf *)bh->b_data;
static int dir_make_exhash(struct inode *inode)
{
- struct gfs2_inode *dip = inode->u.generic_ip;
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_inode *dip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
struct gfs2_dirent *dent;
struct qstr args;
struct buffer_head *bh, *dibh;
struct gfs2_leaf *leaf;
int y;
- uint32_t x;
- uint64_t *lp, bn;
+ u32 x;
+ u64 *lp, bn;
int error;
error = gfs2_meta_inode_buffer(dip, &dibh);
args.len = bh->b_size - sizeof(struct gfs2_dinode) +
sizeof(struct gfs2_leaf);
args.name = bh->b_data;
- dent = gfs2_dirent_scan(dip->i_vnode, bh->b_data, bh->b_size,
+ dent = gfs2_dirent_scan(&dip->i_inode, bh->b_data, bh->b_size,
gfs2_dirent_last, &args, NULL);
if (!dent) {
brelse(bh);
gfs2_trans_add_bh(dip->i_gl, dibh, 1);
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
- lp = (uint64_t *)(dibh->b_data + sizeof(struct gfs2_dinode));
+ lp = (u64 *)(dibh->b_data + sizeof(struct gfs2_dinode));
for (x = sdp->sd_hash_ptrs; x--; lp++)
*lp = cpu_to_be64(bn);
static int dir_split_leaf(struct inode *inode, const struct qstr *name)
{
- struct gfs2_inode *dip = inode->u.generic_ip;
+ struct gfs2_inode *dip = GFS2_I(inode);
struct buffer_head *nbh, *obh, *dibh;
struct gfs2_leaf *nleaf, *oleaf;
- struct gfs2_dirent *dent, *prev = NULL, *next = NULL, *new;
- uint32_t start, len, half_len, divider;
- uint64_t bn, *lp, leaf_no;
- uint32_t index;
+ struct gfs2_dirent *dent = NULL, *prev = NULL, *next = NULL, *new;
+ u32 start, len, half_len, divider;
+ u64 bn, *lp, leaf_no;
+ u32 index;
int x, moved = 0;
int error;
/* Change the pointers.
Don't bother distinguishing stuffed from non-stuffed.
This code is complicated enough already. */
- lp = kmalloc(half_len * sizeof(uint64_t), GFP_NOFS | __GFP_NOFAIL);
+ lp = kmalloc(half_len * sizeof(u64), GFP_NOFS | __GFP_NOFAIL);
/* Change the pointers */
for (x = 0; x < half_len; x++)
lp[x] = cpu_to_be64(bn);
- error = gfs2_dir_write_data(dip, (char *)lp, start * sizeof(uint64_t),
- half_len * sizeof(uint64_t));
- if (error != half_len * sizeof(uint64_t)) {
+ error = gfs2_dir_write_data(dip, (char *)lp, start * sizeof(u64),
+ half_len * sizeof(u64));
+ if (error != half_len * sizeof(u64)) {
if (error >= 0)
error = -EIO;
goto fail_lpfree;
oleaf->lf_depth = nleaf->lf_depth;
error = gfs2_meta_inode_buffer(dip, &dibh);
- if (!gfs2_assert_withdraw(dip->i_sbd, !error)) {
+ if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) {
dip->i_di.di_blocks++;
gfs2_dinode_out(&dip->i_di, dibh->b_data);
brelse(dibh);
static int dir_double_exhash(struct gfs2_inode *dip)
{
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct buffer_head *dibh;
- uint32_t hsize;
- uint64_t *buf;
- uint64_t *from, *to;
- uint64_t block;
+ u32 hsize;
+ u64 *buf;
+ u64 *from, *to;
+ u64 block;
int x;
int error = 0;
hsize = 1 << dip->i_di.di_depth;
- if (hsize * sizeof(uint64_t) != dip->i_di.di_size) {
+ if (hsize * sizeof(u64) != dip->i_di.di_size) {
gfs2_consist_inode(dip);
return -EIO;
}
}
from = buf;
- to = (uint64_t *)((char *)buf + sdp->sd_hash_bsize);
+ to = (u64 *)((char *)buf + sdp->sd_hash_bsize);
for (x = sdp->sd_hash_ptrs; x--; from++) {
*to++ = *from; /* No endianess worries */
return error;
- fail:
+fail:
kfree(buf);
-
return error;
}
static int compare_dents(const void *a, const void *b)
{
struct gfs2_dirent *dent_a, *dent_b;
- uint32_t hash_a, hash_b;
+ u32 hash_a, hash_b;
int ret = 0;
dent_a = *(struct gfs2_dirent **)a;
* Returns: errno, >0 on exception from filldir
*/
-static int do_filldir_main(struct gfs2_inode *dip, uint64_t *offset,
+static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
void *opaque, gfs2_filldir_t filldir,
- const struct gfs2_dirent **darr, uint32_t entries,
+ const struct gfs2_dirent **darr, u32 entries,
int *copied)
{
const struct gfs2_dirent *dent, *dent_next;
struct gfs2_inum inum;
- uint64_t off, off_next;
+ u64 off, off_next;
unsigned int x, y;
int run = 0;
int error = 0;
gfs2_filldir_t filldir, int *copied,
unsigned *depth, u64 leaf_no)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct buffer_head *bh;
struct gfs2_leaf *lf;
unsigned entries = 0;
return 0;
error = -ENOMEM;
- larr = kmalloc((leaves + entries) * sizeof(void*), GFP_KERNEL);
+ larr = vmalloc((leaves + entries) * sizeof(void*));
if (!larr)
goto out;
darr = (const struct gfs2_dirent **)(larr + leaves);
out_kfree:
for(i = 0; i < leaf; i++)
brelse(larr[i]);
- kfree(larr);
+ vfree(larr);
out:
return error;
}
* Returns: errno
*/
-static int dir_e_read(struct inode *inode, uint64_t *offset, void *opaque,
+static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
gfs2_filldir_t filldir)
{
- struct gfs2_inode *dip = inode->u.generic_ip;
- struct gfs2_sbd *sdp = dip->i_sbd;
- uint32_t hsize, len = 0;
- uint32_t ht_offset, lp_offset, ht_offset_cur = -1;
- uint32_t hash, index;
- uint64_t *lp;
+ struct gfs2_inode *dip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
+ u32 hsize, len = 0;
+ u32 ht_offset, lp_offset, ht_offset_cur = -1;
+ u32 hash, index;
+ u64 *lp;
int copied = 0;
int error = 0;
- unsigned depth;
+ unsigned depth = 0;
hsize = 1 << dip->i_di.di_depth;
- if (hsize * sizeof(uint64_t) != dip->i_di.di_size) {
+ if (hsize * sizeof(u64) != dip->i_di.di_size) {
gfs2_consist_inode(dip);
return -EIO;
}
if (ht_offset_cur != ht_offset) {
error = gfs2_dir_read_data(dip, (char *)lp,
- ht_offset * sizeof(uint64_t),
+ ht_offset * sizeof(u64),
sdp->sd_hash_bsize);
if (error != sdp->sd_hash_bsize) {
if (error >= 0)
return error;
}
-int gfs2_dir_read(struct inode *inode, uint64_t *offset, void *opaque,
+int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
gfs2_filldir_t filldir)
{
- struct gfs2_inode *dip = inode->u.generic_ip;
+ struct gfs2_inode *dip = GFS2_I(inode);
struct dirent_gather g;
const struct gfs2_dirent **darr, *dent;
struct buffer_head *dibh;
static int dir_new_leaf(struct inode *inode, const struct qstr *name)
{
struct buffer_head *bh, *obh;
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_leaf *leaf, *oleaf;
int error;
u32 index;
int gfs2_dir_add(struct inode *inode, const struct qstr *name,
const struct gfs2_inum *inum, unsigned type)
{
- struct gfs2_inode *ip = inode->u.generic_ip;
+ struct gfs2_inode *ip = GFS2_I(inode);
struct buffer_head *bh;
struct gfs2_dirent *dent;
struct gfs2_leaf *leaf;
/* Returns _either_ the entry (if its first in block) or the
previous entry otherwise */
- dent = gfs2_dirent_search(dip->i_vnode, name, gfs2_dirent_prev, &bh);
+ dent = gfs2_dirent_search(&dip->i_inode, name, gfs2_dirent_prev, &bh);
if (!dent) {
gfs2_consist_inode(dip);
return -EIO;
dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds();
gfs2_dinode_out(&dip->i_di, bh->b_data);
brelse(bh);
+ mark_inode_dirty(&dip->i_inode);
return error;
}
struct gfs2_dirent *dent;
int error;
- dent = gfs2_dirent_search(dip->i_vnode, filename, gfs2_dirent_find, &bh);
+ dent = gfs2_dirent_search(&dip->i_inode, filename, gfs2_dirent_find, &bh);
if (!dent) {
gfs2_consist_inode(dip);
return -EIO;
static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
{
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct buffer_head *bh;
struct gfs2_leaf *leaf;
- uint32_t hsize, len;
- uint32_t ht_offset, lp_offset, ht_offset_cur = -1;
- uint32_t index = 0;
- uint64_t *lp;
- uint64_t leaf_no;
+ u32 hsize, len;
+ u32 ht_offset, lp_offset, ht_offset_cur = -1;
+ u32 index = 0;
+ u64 *lp;
+ u64 leaf_no;
int error = 0;
hsize = 1 << dip->i_di.di_depth;
- if (hsize * sizeof(uint64_t) != dip->i_di.di_size) {
+ if (hsize * sizeof(u64) != dip->i_di.di_size) {
gfs2_consist_inode(dip);
return -EIO;
}
if (ht_offset_cur != ht_offset) {
error = gfs2_dir_read_data(dip, (char *)lp,
- ht_offset * sizeof(uint64_t),
+ ht_offset * sizeof(u64),
sdp->sd_hash_bsize);
if (error != sdp->sd_hash_bsize) {
if (error >= 0)
if (error)
goto out;
leaf = (struct gfs2_leaf *)bh->b_data;
- brelse(bh);
-
len = 1 << (dip->i_di.di_depth - be16_to_cpu(leaf->lf_depth));
+ brelse(bh);
error = lc(dip, index, len, leaf_no, data);
if (error)
error = -EIO;
}
- out:
+out:
kfree(lp);
return error;
* Returns: errno
*/
-static int leaf_dealloc(struct gfs2_inode *dip, uint32_t index, uint32_t len,
- uint64_t leaf_no, void *data)
+static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
+ u64 leaf_no, void *data)
{
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct gfs2_leaf *tmp_leaf;
struct gfs2_rgrp_list rlist;
struct buffer_head *bh, *dibh;
- uint64_t blk, nblk;
+ u64 blk, nblk;
unsigned int rg_blocks = 0, l_blocks = 0;
char *ht;
- unsigned int x, size = len * sizeof(uint64_t);
+ unsigned int x, size = len * sizeof(u64);
int error;
memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
dip->i_di.di_blocks--;
}
- error = gfs2_dir_write_data(dip, ht, index * sizeof(uint64_t), size);
+ error = gfs2_dir_write_data(dip, ht, index * sizeof(u64), size);
if (error != size) {
if (error >= 0)
error = -EIO;
gfs2_dinode_out(&dip->i_di, dibh->b_data);
brelse(dibh);
- out_end_trans:
+out_end_trans:
gfs2_trans_end(sdp);
-
- out_rg_gunlock:
+out_rg_gunlock:
gfs2_glock_dq_m(rlist.rl_rgrps, rlist.rl_ghs);
-
- out_rlist:
+out_rlist:
gfs2_rlist_free(&rlist);
gfs2_glock_dq_uninit(&dip->i_alloc.al_ri_gh);
-
- out_qs:
+out_qs:
gfs2_quota_unhold(dip);
-
- out:
+out:
gfs2_alloc_put(dip);
kfree(ht);
-
return error;
}
int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip)
{
- struct gfs2_sbd *sdp = dip->i_sbd;
+ struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct buffer_head *bh;
int error;