- if (hsize * sizeof(uint64_t) != dip->i_di.di_size) {
- gfs2_consist_inode(dip);
- return -EIO;
- }
-
- hash = gfs2_dir_offset2hash(*offset);
- index = hash >> (32 - dip->i_di.di_depth);
-
- lp = kmalloc(sdp->sd_hash_bsize, GFP_KERNEL);
- if (!lp)
- return -ENOMEM;
-
- while (index < hsize) {
- lp_offset = index & (sdp->sd_hash_ptrs - 1);
- ht_offset = index - lp_offset;
-
- if (ht_offset_cur != ht_offset) {
- error = gfs2_jdata_read_mem(dip, (char *)lp,
- ht_offset * sizeof(uint64_t),
- sdp->sd_hash_bsize);
- if (error != sdp->sd_hash_bsize) {
- if (error >= 0)
- error = -EIO;
- goto out;
- }
- ht_offset_cur = ht_offset;
- }
-
- error = get_leaf(dip, be64_to_cpu(lp[lp_offset]), &bh);
- if (error)
- goto out;
-
- gfs2_leaf_in(&leaf, bh->b_data);
-
- if (leaf.lf_next)
- error = do_filldir_multi(dip, offset, opaque, filldir,
- bh, &copied);
- else
- error = do_filldir_single(dip, offset, opaque, filldir,
- bh, leaf.lf_entries, &copied);
-
- brelse(bh);
-
- if (error) {
- if (error > 0)
- error = 0;
- goto out;
- }
-
- len = 1 << (dip->i_di.di_depth - leaf.lf_depth);
- index = (index & ~(len - 1)) + len;
- }
-
- out:
- kfree(lp);
-
- return error;
-}
-
-static int dir_e_mvino(struct gfs2_inode *dip, struct qstr *filename,
- struct gfs2_inum *inum, unsigned int new_type)
-{
- struct buffer_head *bh, *dibh;
- struct gfs2_dirent *dent;
- int error;
-
- error = linked_leaf_search(dip, filename, &dent, NULL, &bh);
- if (error == -ENOENT) {
- gfs2_consist_inode(dip);
- return -EIO;
- }
- if (error)
- return error;
-
- gfs2_trans_add_bh(dip->i_gl, bh);
-
- gfs2_inum_out(inum, (char *)&dent->de_inum);
- dent->de_type = new_type;
-
- brelse(bh);
-
- error = gfs2_meta_inode_buffer(dip, &dibh);
- if (error)
- return error;
-
- dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds();
-
- gfs2_trans_add_bh(dip->i_gl, dibh);
- gfs2_dinode_out(&dip->i_di, dibh->b_data);
- brelse(dibh);
-
- return 0;
-}
-
-/**
- * dir_l_search - Search linear (stuffed dinode) dir for inode matching name
- * @dip: The GFS2 inode
- * @filename: Filename string
- * @inode: If non-NULL, function fills with formal inode # and block address
- * @type: If non-NULL, function fills with DT_... dinode type
- *
- * Returns:
- */
-
-static int dir_l_search(struct gfs2_inode *dip, struct qstr *filename,
- struct gfs2_inum *inum, unsigned int *type)
-{
- struct buffer_head *dibh;
- struct gfs2_dirent *dent;
- int error;
-
- if (!gfs2_is_stuffed(dip)) {
- gfs2_consist_inode(dip);
- return -EIO;
- }
-
- error = gfs2_meta_inode_buffer(dip, &dibh);
- if (error)
- return error;
-
- error = leaf_search(dip, dibh, filename, &dent, NULL);
- if (!error) {
- if (inum)
- gfs2_inum_in(inum, (char *)&dent->de_inum);
- if (type)
- *type = dent->de_type;
- }
-
- brelse(dibh);
-
- return error;
-}
-
-static int dir_l_add(struct gfs2_inode *dip, struct qstr *filename,
- struct gfs2_inum *inum, unsigned int type)
-{
- struct buffer_head *dibh;
- struct gfs2_dirent *dent;
- int error;
-
- if (!gfs2_is_stuffed(dip)) {
- gfs2_consist_inode(dip);
- return -EIO;
- }
-
- error = gfs2_meta_inode_buffer(dip, &dibh);
- if (error)
- return error;
-
- if (gfs2_dirent_alloc(dip, dibh, filename->len, &dent)) {
- brelse(dibh);
-
- error = dir_make_exhash(dip);
- if (!error)
- error = dir_e_add(dip, filename, inum, type);
-
- return error;
- }
-
- /* gfs2_dirent_alloc() pins */
-
- gfs2_inum_out(inum, (char *)&dent->de_inum);
- dent->de_hash = gfs2_disk_hash(filename->name, filename->len);
- dent->de_hash = cpu_to_be32(dent->de_hash);
- dent->de_type = type;
- memcpy((char *)(dent + 1), filename->name, filename->len);
-
- dip->i_di.di_entries++;
- dip->i_di.di_mtime = dip->i_di.di_ctime = get_seconds();
-
- gfs2_dinode_out(&dip->i_di, dibh->b_data);
- brelse(dibh);
-
- return 0;
-}
-
-static int dir_l_del(struct gfs2_inode *dip, struct qstr *filename)
-{
- struct buffer_head *dibh;
- struct gfs2_dirent *dent, *prev;
- int error;
-
- if (!gfs2_is_stuffed(dip)) {
- gfs2_consist_inode(dip);
- return -EIO;
- }
-
- error = gfs2_meta_inode_buffer(dip, &dibh);
- if (error)
- return error;
-
- error = leaf_search(dip, dibh, filename, &dent, &prev);
- if (error == -ENOENT) {