#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, u32 index, u32 len,
+typedef int (*leaf_call_t) (struct gfs2_inode *dip, u32 index, u32 len,
u64 leaf_no, void *data);
typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent,
const struct qstr *name, void *opaque);
struct buffer_head *bh;
int error;
- error = gfs2_meta_read(ip->i_gl, block, DIO_START | DIO_WAIT, &bh);
+ error = gfs2_meta_read(ip->i_gl, block, DIO_WAIT, &bh);
if (error)
return error;
if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh, GFS2_METATYPE_JD)) {
static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
unsigned int offset, unsigned int size)
-
{
struct buffer_head *dibh;
int error;
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();
- gfs2_dinode_out(&ip->i_di, dibh->b_data);
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
while (copied < size) {
unsigned int amount;
struct buffer_head *bh;
- int new;
+ int new = 0;
amount = size - copied;
if (amount > sdp->sd_sb.sb_bsize - o)
gfs2_trans_add_bh(ip->i_gl, bh, 1);
memcpy(bh->b_data + o, buf, amount);
brelse(bh);
- if (error)
- goto fail;
buf += amount;
copied += amount;
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 = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
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;
}
static int gfs2_dir_read_stuffed(struct gfs2_inode *ip, char *buf,
- unsigned int offset, unsigned int size)
+ u64 offset, unsigned int size)
{
struct buffer_head *dibh;
int error;
*
* Returns: The amount of data actually copied or the error
*/
-static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf,
- u64 offset, unsigned int size)
+static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf, u64 offset,
+ unsigned int size, unsigned ra)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
u64 lblock, dblock;
return 0;
if (gfs2_is_stuffed(ip))
- return gfs2_dir_read_stuffed(ip, buf, (unsigned int)offset,
- size);
+ return gfs2_dir_read_stuffed(ip, buf, offset, size);
if (gfs2_assert_warn(sdp, gfs2_is_jdata(ip)))
return -EINVAL;
new = 0;
error = gfs2_extent_map(&ip->i_inode, lblock, &new,
&dblock, &extlen);
- if (error)
+ if (error || !dblock)
goto fail;
- }
-
- if (extlen > 1)
- gfs2_meta_ra(ip->i_gl, dblock, extlen);
-
- if (dblock) {
- if (new)
- error = gfs2_dir_get_new_buffer(ip, dblock, &bh);
- else
- error = gfs2_dir_get_existing_buffer(ip, dblock, &bh);
+ BUG_ON(extlen < 1);
+ if (!ra)
+ extlen = 1;
+ bh = gfs2_meta_ra(ip->i_gl, dblock, extlen);
+ } else {
+ error = gfs2_meta_read(ip->i_gl, dblock, DIO_WAIT, &bh);
if (error)
goto fail;
- dblock++;
- extlen--;
- } else
- bh = NULL;
-
+ }
+ error = gfs2_metatype_check(sdp, bh, GFS2_METATYPE_JD);
+ if (error) {
+ brelse(bh);
+ goto fail;
+ }
+ dblock++;
+ extlen--;
memcpy(buf, bh->b_data + o, amount);
brelse(bh);
- if (error)
- goto fail;
-
buf += amount;
copied += amount;
lblock++;
-
o = sizeof(struct gfs2_meta_header);
}
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)
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;
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;
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;
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;
}
{
u16 cur_rec_len, prev_rec_len;
- if (!cur->de_inum.no_addr) {
+ if (gfs2_dirent_sentinel(cur)) {
gfs2_consist_inode(dip);
return;
}
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;
}
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);
const struct qstr *name)
{
struct gfs2_dirent *dent;
- dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size,
+ dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size,
gfs2_dirent_find_space, name, NULL);
if (!dent || IS_ERR(dent))
return dent;
{
int error;
- error = gfs2_meta_read(dip->i_gl, leaf_no, DIO_START | DIO_WAIT, bhp);
+ error = gfs2_meta_read(dip->i_gl, leaf_no, DIO_WAIT, bhp);
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;
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));
+ index * sizeof(__be64),
+ sizeof(__be64), 0);
if (error != sizeof(u64))
return (error < 0) ? error : -EIO;
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);
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;
leaf->lf_depth = cpu_to_be16(depth);
leaf->lf_entries = 0;
- leaf->lf_dirent_format = cpu_to_be16(GFS2_FORMAT_DE);
+ leaf->lf_dirent_format = cpu_to_be32(GFS2_FORMAT_DE);
leaf->lf_next = 0;
memset(leaf->lf_reserved, 0, sizeof(leaf->lf_reserved));
dent = (struct gfs2_dirent *)(leaf+1);
struct gfs2_leaf *leaf;
int y;
u32 x;
- u64 *lp, bn;
+ __be64 *lp;
+ u64 bn;
int error;
error = gfs2_meta_inode_buffer(dip, &dibh);
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);
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;
- 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;
- gfs2_dinode_out(&dip->i_di, dibh->b_data);
+ gfs2_dinode_out(dip, dibh->b_data);
brelse(dibh);
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;
/* 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);
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);
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_set_inode_blocks(&dip->i_inode);
+ gfs2_dinode_out(dip, dibh->b_data);
brelse(dibh);
}
for (block = dip->i_di.di_size >> sdp->sd_hash_bsize_shift; block--;) {
error = gfs2_dir_read_data(dip, (char *)buf,
block * sdp->sd_hash_bsize,
- sdp->sd_hash_bsize);
+ sdp->sd_hash_bsize, 1);
if (error != sdp->sd_hash_bsize) {
if (error >= 0)
error = -EIO;
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);
}
*/
static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
- void *opaque, gfs2_filldir_t filldir,
+ void *opaque, filldir_t filldir,
const struct gfs2_dirent **darr, u32 entries,
int *copied)
{
const struct gfs2_dirent *dent, *dent_next;
- struct gfs2_inum inum;
u64 off, off_next;
unsigned int x, y;
int run = 0;
*offset = off;
}
- gfs2_inum_in(&inum, (char *)&dent->de_inum);
-
error = filldir(opaque, (const char *)(dent + 1),
be16_to_cpu(dent->de_name_len),
- off, &inum,
+ off, be64_to_cpu(dent->de_inum.no_addr),
be16_to_cpu(dent->de_type));
if (error)
return 1;
}
static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
- gfs2_filldir_t filldir, int *copied,
- unsigned *depth, u64 leaf_no)
+ filldir_t filldir, int *copied, unsigned *depth,
+ u64 leaf_no)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct buffer_head *bh;
*/
static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
- gfs2_filldir_t filldir)
+ filldir_t filldir)
{
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;
+ __be64 *lp;
int copied = 0;
int error = 0;
unsigned depth = 0;
if (ht_offset_cur != ht_offset) {
error = gfs2_dir_read_data(dip, (char *)lp,
- ht_offset * sizeof(u64),
- sdp->sd_hash_bsize);
+ ht_offset * sizeof(__be64),
+ sdp->sd_hash_bsize, 1);
if (error != sdp->sd_hash_bsize) {
if (error >= 0)
error = -EIO;
}
int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
- gfs2_filldir_t filldir)
+ filldir_t filldir)
{
struct gfs2_inode *dip = GFS2_I(inode);
struct dirent_gather g;
*/
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;
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_set_inode_blocks(&ip->i_inode);
+ gfs2_dinode_out(ip, bh->b_data);
brelse(bh);
return 0;
}
*/
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;
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();
- gfs2_dinode_out(&ip->i_di, bh->b_data);
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ gfs2_dinode_out(ip, bh->b_data);
brelse(bh);
error = 0;
break;
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();
- gfs2_dinode_out(&dip->i_di, bh->b_data);
+ dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ gfs2_dinode_out(dip, bh->b_data);
brelse(bh);
mark_inode_dirty(&dip->i_inode);
*/
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;
gfs2_trans_add_bh(dip->i_gl, bh, 1);
}
- dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds();
- gfs2_dinode_out(&dip->i_di, bh->b_data);
+ dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ gfs2_dinode_out(dip, bh->b_data);
brelse(bh);
return 0;
}
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;
if (ht_offset_cur != ht_offset) {
error = gfs2_dir_read_data(dip, (char *)lp,
- ht_offset * sizeof(u64),
- sdp->sd_hash_bsize);
+ ht_offset * sizeof(__be64),
+ sdp->sd_hash_bsize, 1);
if (error != sdp->sd_hash_bsize) {
if (error >= 0)
error = -EIO;
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);
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: