Commit 71b86f56 authored by Steven Whitehouse's avatar Steven Whitehouse
Browse files

[GFS2] Further updates to dir and logging code



This reduces the size of the directory code by about 3k and gets
readdir() to use the functions which were introduced in the previous
directory code update.

Two memory allocations are merged into one. Eliminates zeroing of some
buffers which were never used before they were initialised by
other data.

There is still scope for further improvement in the directory code.

On the logging side, a hand created mutex has been replaced by a
standard Linux mutex in the log allocation code.

Signed-off-by: default avatarSteven Whitehouse <swhiteho@redhat.com>
parent 94aabbd9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/completion.h>
#include <linux/buffer_head.h>
#include <linux/gfs2_ondisk.h>
#include <linux/crc32.h>
#include <asm/semaphore.h>

#include "gfs2.h"
+161 −251
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@
#include <linux/buffer_head.h>
#include <linux/sort.h>
#include <linux/gfs2_ondisk.h>
#include <linux/crc32.h>
#include <asm/semaphore.h>

#include "gfs2.h"
@@ -344,7 +345,8 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf,
}

typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent,
			    const struct qstr *name);
			    const struct qstr *name,
			    void *opaque);

static inline int __gfs2_dirent_find(const struct gfs2_dirent *dent,
				     const struct qstr *name, int ret)
@@ -358,13 +360,15 @@ static inline int __gfs2_dirent_find(const struct gfs2_dirent *dent,
}

static int gfs2_dirent_find(const struct gfs2_dirent *dent,
			    const struct qstr *name)
			    const struct qstr *name,
			    void *opaque)
{
	return __gfs2_dirent_find(dent, name, 1);
}

static int gfs2_dirent_prev(const struct gfs2_dirent *dent,
			    const struct qstr *name)
			    const struct qstr *name,
			    void *opaque)
{
	return __gfs2_dirent_find(dent, name, 2);
}
@@ -374,7 +378,8 @@ static int gfs2_dirent_prev(const struct gfs2_dirent *dent,
 * name->len holds size of block.
 */
static int gfs2_dirent_last(const struct gfs2_dirent *dent,
			    const struct qstr *name)
			    const struct qstr *name,
			    void *opaque)
{
	const char *start = name->name;
	const char *end = (const char *)dent + be16_to_cpu(dent->de_rec_len);
@@ -384,17 +389,36 @@ static int gfs2_dirent_last(const struct gfs2_dirent *dent,
}

static int gfs2_dirent_find_space(const struct gfs2_dirent *dent,
				  const struct qstr *name)
				  const struct qstr *name,
				  void *opaque)
{
	unsigned required = GFS2_DIRENT_SIZE(name->len);
	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)
		actual = GFS2_DIRENT_SIZE(0);
	if ((totlen - actual) >= required)
		return 1;
	return 0;
}

struct dirent_gather {
	const struct gfs2_dirent **pdent;
	unsigned offset;
};

static int gfs2_dirent_gather(const struct gfs2_dirent *dent,
			      const struct qstr *name,
			      void *opaque)
{
	struct dirent_gather *g = opaque;
	if (dent->de_inum.no_addr) {
		g->pdent[g->offset++] = dent;
	}
	return 0;
}

/*
 * Other possible things to check:
 * - Inode located within filesystem size (and on valid block)
@@ -431,19 +455,12 @@ static int gfs2_check_dirent(struct gfs2_dirent *dent, unsigned int offset,
	return -EIO;
}

static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode,
					    void *buf,
					    unsigned int len, gfs2_dscan_t scan,
					    const struct qstr *name)
static int gfs2_dirent_offset(const void *buf)
{
	struct gfs2_meta_header *h = buf;
	struct gfs2_dirent *dent, *prev;
	unsigned offset;
	unsigned size;
	int ret = 0;
	const struct gfs2_meta_header *h = buf;
	int offset;

	BUG_ON(buf == NULL);
	BUG_ON(name == NULL);

	switch(be16_to_cpu(h->mh_type)) {
	case GFS2_METATYPE_LF:
@@ -455,14 +472,36 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode,
	default:
		goto wrong_type;
	}
	return offset;
wrong_type:
	printk(KERN_WARNING "gfs2_scan_dirent: wrong block type %u\n",
	       be16_to_cpu(h->mh_type));
	return -1;
}

static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode,
					    void *buf,
					    unsigned int len, gfs2_dscan_t scan,
					    const struct qstr *name,
					    void *opaque)
{
	struct gfs2_dirent *dent, *prev;
	unsigned offset;
	unsigned size;
	int ret = 0;

	ret = gfs2_dirent_offset(buf);
	if (ret < 0)
		goto consist_inode;

	offset = ret;
	prev = NULL;
	dent = (struct gfs2_dirent *)(buf + offset);
	size = be16_to_cpu(dent->de_rec_len);
	if (gfs2_check_dirent(dent, offset, size, len, 1))
		goto consist_inode;
	do {
		ret = scan(dent, name);
		ret = scan(dent, name, opaque);
		if (ret)
			break;
		offset += size;
@@ -487,9 +526,6 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode,
		return ERR_PTR(ret);
	}

wrong_type:
	printk(KERN_WARNING "gfs2_scan_dirent: %p wrong block type %u\n", scan,
	       be16_to_cpu(h->mh_type));
consist_inode:
	gfs2_consist_inode(inode->u.generic_ip);
	return ERR_PTR(-EIO);
@@ -651,7 +687,8 @@ static struct gfs2_dirent *gfs2_dirent_alloc(struct inode *inode,
					     const struct qstr *name)
{
	struct gfs2_dirent *dent;
	dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size, gfs2_dirent_find_space, name);
	dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size, 
				gfs2_dirent_find_space, name, NULL);
	if (!dent || IS_ERR(dent))
		return dent;
	return gfs2_init_dirent(inode, dent, name, bh);
@@ -734,7 +771,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
			return ERR_PTR(error);
		do {
			dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size,
						scan, name);
						scan, name, NULL);
			if (dent)
				goto got_dent;
			leaf = (struct gfs2_leaf *)bh->b_data;
@@ -751,7 +788,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
	error = gfs2_meta_inode_buffer(ip, &bh);
	if (error)
		return ERR_PTR(error);
	dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size, scan, name);
	dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size, scan, name, NULL);
got_dent:
	*pbh = bh;
	return dent;
@@ -764,6 +801,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
	struct buffer_head *bh = gfs2_meta_new(ip->i_gl, bn);
	struct gfs2_leaf *leaf;
	struct gfs2_dirent *dent;
	struct qstr name = { .name = "", .len = 0, .hash = 0 };
	if (!bh)
		return NULL;
	gfs2_trans_add_bh(ip->i_gl, bh, 1);
@@ -775,12 +813,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
	leaf->lf_next = cpu_to_be64(0);
	memset(leaf->lf_reserved, 0, sizeof(leaf->lf_reserved));
	dent = (struct gfs2_dirent *)(leaf+1);
	dent->de_inum.no_formal_ino = cpu_to_be64(0);
	dent->de_inum.no_addr = cpu_to_be64(0);
	dent->de_hash = cpu_to_be32(0);
	dent->de_rec_len = cpu_to_be16(bh->b_size - sizeof(struct gfs2_leaf));
	dent->de_name_len = cpu_to_be16(0);
	dent->de_type = cpu_to_be16(0);
	gfs2_qstr2dirent(&name, bh->b_size - sizeof(struct gfs2_leaf), dent);
	*pbh = bh;
	return leaf;
}
@@ -831,7 +864,7 @@ static int dir_make_exhash(struct inode *inode)
		   sizeof(struct gfs2_leaf);
	args.name = bh->b_data;
	dent = gfs2_dirent_scan(dip->i_vnode, bh->b_data, bh->b_size,
				gfs2_dirent_last, &args);
				gfs2_dirent_last, &args, NULL);
	if (!dent) {
		brelse(bh);
		brelse(dibh);
@@ -965,7 +998,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
			str.name = (char*)(dent+1);
			str.len = be16_to_cpu(dent->de_name_len);
			str.hash = be32_to_cpu(dent->de_hash);
			new = gfs2_dirent_alloc(dip->i_vnode, nbh, &str);
			new = gfs2_dirent_alloc(inode, nbh, &str);
			if (IS_ERR(new)) {
				error = PTR_ERR(new);
				break;
@@ -1154,10 +1187,10 @@ static int compare_dents(const void *a, const void *b)

static int do_filldir_main(struct gfs2_inode *dip, uint64_t *offset,
			   void *opaque, gfs2_filldir_t filldir,
			   struct gfs2_dirent **darr, uint32_t entries,
			   const struct gfs2_dirent **darr, uint32_t entries,
			   int *copied)
{
	struct gfs2_dirent *dent, *dent_next;
	const struct gfs2_dirent *dent, *dent_next;
	struct gfs2_inum inum;
	uint64_t off, off_next;
	unsigned int x, y;
@@ -1216,189 +1249,74 @@ static int do_filldir_main(struct gfs2_inode *dip, uint64_t *offset,
	return 0;
}

/**
 * do_filldir_single - Read directory entries out of a single block
 * @dip: The GFS2 inode
 * @offset: The offset in the file to read from
 * @opaque: opaque data to pass to filldir
 * @filldir: The function to pass entries to
 * @bh: the block
 * @entries: the number of entries in the block
 * @copied: pointer to int that's non-zero if a entry has been copied out
 *
 * Returns: errno, >0 on exception from filldir
 */

static int do_filldir_single(struct gfs2_inode *dip, uint64_t *offset,
			     void *opaque, gfs2_filldir_t filldir,
			     struct buffer_head *bh, uint32_t entries,
			     int *copied)
static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
			      gfs2_filldir_t filldir, int *copied,
			      unsigned *depth, u64 leaf_no)
{
	struct gfs2_dirent **darr;
	struct gfs2_dirent *de;
	unsigned int e = 0;
	int error;

	if (!entries)
		return 0;

	darr = kcalloc(entries, sizeof(struct gfs2_dirent *), GFP_KERNEL);
	if (!darr)
		return -ENOMEM;
	struct gfs2_inode *ip = inode->u.generic_ip;
	struct buffer_head *bh;
	struct gfs2_leaf *lf;
	unsigned entries = 0;
	unsigned leaves = 0;
	const struct gfs2_dirent **darr, *dent;
	struct dirent_gather g;
	struct buffer_head **larr;
	int leaf = 0;
	int error, i;
	u64 lfn = leaf_no;

	dirent_first(dip, bh, &de);
	do {
		if (!de->de_inum.no_addr)
			continue;
		if (e >= entries) {
			gfs2_consist_inode(dip);
			error = -EIO;
			goto out;
		}
		darr[e++] = de;
	} while (dirent_next(dip, bh, &de) == 0);

	if (e != entries) {
		gfs2_consist_inode(dip);
		error = -EIO;
		goto out;
	}

	error = do_filldir_main(dip, offset, opaque, filldir, darr,
				entries, copied);

 out:
	kfree(darr);

	return error;
}

/**
 * do_filldir_multi - Read directory entries out of a linked leaf list
 * @dip: The GFS2 inode
 * @offset: The offset in the file to read from
 * @opaque: opaque data to pass to filldir
 * @filldir: The function to pass entries to
 * @bh: the first leaf in the list
 * @copied: pointer to int that's non-zero if a entry has been copied out
 *
 * Returns: errno, >0 on exception from filldir
 */

static int do_filldir_multi(struct gfs2_inode *dip, uint64_t *offset,
			    void *opaque, gfs2_filldir_t filldir,
			    struct buffer_head *bh, int *copied)
{
	struct buffer_head **larr = NULL;
	struct gfs2_dirent **darr;
	struct gfs2_leaf *leaf;
	struct buffer_head *tmp_bh;
	struct gfs2_dirent *de;
	unsigned int entries, e = 0;
	unsigned int leaves = 0, l = 0;
	unsigned int x;
	uint64_t ln;
	int error = 0;

	/*  Count leaves and entries  */

	leaf = (struct gfs2_leaf *)bh->b_data;
	entries = be16_to_cpu(leaf->lf_entries);
	ln = be64_to_cpu(leaf->lf_next);

	while (ln) {
		error = get_leaf(dip, ln, &tmp_bh);
		error = get_leaf(ip, lfn, &bh);
		if (error)
			return error;

		leaf = (struct gfs2_leaf *)tmp_bh->b_data;
		if (leaf->lf_entries) {
			entries += be16_to_cpu(leaf->lf_entries);
			goto out;
		lf = (struct gfs2_leaf *)bh->b_data;
		if (leaves == 0)
			*depth = be16_to_cpu(lf->lf_depth);
		entries += be16_to_cpu(lf->lf_entries);
		leaves++;
		}
		ln = be64_to_cpu(leaf->lf_next);

		brelse(tmp_bh);
	}
		lfn = be64_to_cpu(lf->lf_next);
		brelse(bh);
	} while(lfn);

	if (!entries)
		return 0;

	if (leaves) {
		larr = kcalloc(leaves, sizeof(struct buffer_head *),GFP_KERNEL);
	error = -ENOMEM;
	larr = kmalloc((leaves + entries) * sizeof(void*), GFP_KERNEL);
	if (!larr)
			return -ENOMEM;
	}

	darr = kcalloc(entries, sizeof(struct gfs2_dirent *), GFP_KERNEL);
	if (!darr) {
		kfree(larr);
		return -ENOMEM;
	}

	leaf = (struct gfs2_leaf *)bh->b_data;
	if (leaf->lf_entries) {
		dirent_first(dip, bh, &de);
		do {
			if (!de->de_inum.no_addr)
				continue;
			if (e >= entries) {
				gfs2_consist_inode(dip);
				error = -EIO;
				goto out;
			}
			darr[e++] = de;
		} while (dirent_next(dip, bh, &de) == 0);
	}
	ln = be64_to_cpu(leaf->lf_next);

	while (ln) {
		error = get_leaf(dip, ln, &tmp_bh);
		if (error)
		goto out;
	darr = (const struct gfs2_dirent **)(larr + leaves);
	g.pdent = darr;
	g.offset = 0;
	lfn = leaf_no;

		leaf = (struct gfs2_leaf *)tmp_bh->b_data;
		if (leaf->lf_entries) {
			dirent_first(dip, tmp_bh, &de);
	do {
				if (!de->de_inum.no_addr)
					continue;
				if (e >= entries) {
					gfs2_consist_inode(dip);
					error = -EIO;
					goto out;
		error = get_leaf(ip, lfn, &bh);
		if (error)
			goto out_kfree;
		lf = (struct gfs2_leaf *)bh->b_data;
		lfn = be64_to_cpu(lf->lf_next);
		if (lf->lf_entries) {
			dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size,
						gfs2_dirent_gather, NULL, &g);
			error = PTR_ERR(dent);
			if (IS_ERR(dent)) {
				goto out_kfree;
			}
				darr[e++] = de;
			} while (dirent_next(dip, tmp_bh, &de) == 0);

			larr[l++] = tmp_bh;

			ln = be64_to_cpu(leaf->lf_next);
			error = 0;
			larr[leaf++] = bh;
		} else {
			ln = be64_to_cpu(leaf->lf_next);
			brelse(tmp_bh);
		}
	}

	if (gfs2_assert_withdraw(dip->i_sbd, l == leaves)) {
		error = -EIO;
		goto out;
	}
	if (e != entries) {
		gfs2_consist_inode(dip);
		error = -EIO;
		goto out;
			brelse(bh);
		}
	} while(lfn);

	error = do_filldir_main(dip, offset, opaque, filldir, darr,
	error = do_filldir_main(ip, offset, opaque, filldir, darr,
				entries, copied);

 out:
	kfree(darr);
	for (x = 0; x < l; x++)
		brelse(larr[x]);
out_kfree:
	for(i = 0; i < leaf; i++)
		brelse(larr[i]);
	kfree(larr);

out:
	return error;
}

@@ -1412,18 +1330,18 @@ static int do_filldir_multi(struct gfs2_inode *dip, uint64_t *offset,
 * Returns: errno
 */

static int dir_e_read(struct gfs2_inode *dip, uint64_t *offset, void *opaque,
static int dir_e_read(struct inode *inode, uint64_t *offset, void *opaque,
		      gfs2_filldir_t filldir)
{
	struct gfs2_inode *dip = inode->u.generic_ip;
	struct gfs2_sbd *sdp = dip->i_sbd;
	struct buffer_head *bh;
	struct gfs2_leaf *leaf;
	uint32_t hsize, len;
	uint32_t hsize, len = 0;
	uint32_t ht_offset, lp_offset, ht_offset_cur = -1;
	uint32_t hash, index;
	uint64_t *lp;
	int copied = 0;
	int error = 0;
	unsigned depth;

	hsize = 1 << dip->i_di.di_depth;
	if (hsize * sizeof(uint64_t) != dip->i_di.di_size) {
@@ -1454,61 +1372,66 @@ static int dir_e_read(struct gfs2_inode *dip, uint64_t *offset, void *opaque,
			ht_offset_cur = ht_offset;
		}

		error = get_leaf(dip, be64_to_cpu(lp[lp_offset]), &bh);
		error = gfs2_dir_read_leaf(inode, offset, opaque, filldir,
					   &copied, &depth,
					   be64_to_cpu(lp[lp_offset]));
		if (error)
			goto out;

		leaf = (struct gfs2_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, 
						  be16_to_cpu(leaf->lf_entries),
						  &copied);

		brelse(bh);

		if (error) {
			if (error > 0)
				error = 0;
			goto out;
		}
			break;

		len = 1 << (dip->i_di.di_depth - be16_to_cpu(leaf->lf_depth));
		len = 1 << (dip->i_di.di_depth - depth);
		index = (index & ~(len - 1)) + len;
	}

out:
	kfree(lp);

	if (error > 0)
		error = 0;
	return error;
}

static int dir_l_read(struct gfs2_inode *dip, uint64_t *offset, void *opaque,
int gfs2_dir_read(struct inode *inode, uint64_t *offset, void *opaque,
		  gfs2_filldir_t filldir)
{
	struct gfs2_inode *dip = inode->u.generic_ip;
	struct dirent_gather g;
	const struct gfs2_dirent **darr, *dent;
	struct buffer_head *dibh;
	int copied = 0;
	int error;

	if (!dip->i_di.di_entries)
		return 0;

	if (dip->i_di.di_flags & GFS2_DIF_EXHASH)
		return dir_e_read(inode, offset, opaque, filldir);

	if (!gfs2_is_stuffed(dip)) {
		gfs2_consist_inode(dip);
		return -EIO;
	}

	if (!dip->i_di.di_entries)
		return 0;

	error = gfs2_meta_inode_buffer(dip, &dibh);
	if (error)
		return error;

	error = do_filldir_single(dip, offset,
				  opaque, filldir,
				  dibh, dip->i_di.di_entries,
				  &copied);
	error = -ENOMEM;
	darr = kmalloc(dip->i_di.di_entries * sizeof(struct gfs2_dirent *),
		       GFP_KERNEL);
	if (darr) {
		g.pdent = darr;
		g.offset = 0;
		dent = gfs2_dirent_scan(inode, dibh->b_data, dibh->b_size,
					gfs2_dirent_gather, NULL, &g);
		if (IS_ERR(dent)) {
			error = PTR_ERR(dent);
			goto out;
		}
		error = do_filldir_main(dip, offset, opaque, filldir, darr,
					dip->i_di.di_entries, &copied);
out:
		kfree(darr);
	}

	if (error > 0)
		error = 0;

@@ -1694,7 +1617,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
		return PTR_ERR(dent);
	}
	/* If not first in block, adjust pointers accordingly */
	if (gfs2_dirent_find(dent, name) == 0) {
	if (gfs2_dirent_find(dent, name, NULL) == 0) {
		prev = dent;
		dent = (struct gfs2_dirent *)((char *)dent + be16_to_cpu(prev->de_rec_len));
	}
@@ -1724,19 +1647,6 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
	return error;
}

int gfs2_dir_read(struct gfs2_inode *dip, uint64_t *offset, void *opaque,
		  gfs2_filldir_t filldir)
{
	int error;

	if (dip->i_di.di_flags & GFS2_DIF_EXHASH)
		error = dir_e_read(dip, offset, opaque, filldir);
	else
		error = dir_l_read(dip, offset, opaque, filldir);

	return error;
}

/**
 * gfs2_dir_mvino - Change inode number of directory entry
 * @dip: The GFS2 inode
+14 −1
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ int gfs2_dir_search(struct inode *dir, const struct qstr *filename,
int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
		 const struct gfs2_inum *inum, unsigned int type);
int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
int gfs2_dir_read(struct gfs2_inode *dip, uint64_t * offset, void *opaque,
int gfs2_dir_read(struct inode *inode, uint64_t * offset, void *opaque,
		  gfs2_filldir_t filldir);
int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
		   struct gfs2_inum *new_inum, unsigned int new_type);
@@ -44,6 +44,19 @@ int gfs2_diradd_alloc_required(struct inode *dir,
int gfs2_dir_get_buffer(struct gfs2_inode *ip, uint64_t block, int new,
                        struct buffer_head **bhp);

static inline uint32_t gfs2_disk_hash(const char *data, int len)
{
        return crc32_le(0xFFFFFFFF, data, len) ^ 0xFFFFFFFF;
}


static inline void gfs2_str2qstr(struct qstr *name, const char *fname)
{
	name->name = fname;
	name->len = strlen(fname);
	name->hash = gfs2_disk_hash(name->name, name->len);
}

/* N.B. This probably ought to take inum & type as args as well */
static inline void gfs2_qstr2dirent(const struct qstr *name, u16 reclen, struct gfs2_dirent *dent)
{
+1 −2
Original line number Diff line number Diff line
@@ -634,8 +634,7 @@ struct gfs2_sbd {
	struct list_head sd_log_le_databuf;

	unsigned int sd_log_blks_free;
	struct list_head sd_log_blks_list;
	wait_queue_head_t sd_log_blks_wait;
	struct mutex sd_log_reserve_mutex;

	uint64_t sd_log_sequence;
	unsigned int sd_log_head;
+4 −10
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/posix_acl.h>
#include <linux/sort.h>
#include <linux/gfs2_ondisk.h>
#include <linux/crc32.h>
#include <asm/semaphore.h>

#include "gfs2.h"
@@ -701,9 +702,7 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff)
struct inode *gfs2_lookup_simple(struct inode *dip, const char *name)
{
	struct qstr qstr;
	qstr.name = name;
	qstr.len = strlen(name);
	qstr.hash = gfs2_disk_hash(qstr.name, qstr.len);
	gfs2_str2qstr(&qstr, name);
	return gfs2_lookupi(dip, &qstr, 1, NULL);
}

@@ -1389,9 +1388,7 @@ int gfs2_rmdiri(struct gfs2_inode *dip, struct qstr *name,
	if (error)
		return error;

	dotname.len = 1;
	dotname.name = ".";
	dotname.hash = gfs2_disk_hash(dotname.name, dotname.len);
	gfs2_str2qstr(&dotname, ".");
	error = gfs2_dir_del(ip, &dotname);
	if (error)
		return error;
@@ -1487,10 +1484,7 @@ int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
	struct qstr dotdot;
	int error = 0;

	memset(&dotdot, 0, sizeof(struct qstr));
	dotdot.name = "..";
	dotdot.len = 2;
	dotdot.hash = gfs2_disk_hash(dotdot.name, dotdot.len);
	gfs2_str2qstr(&dotdot, "..");

	igrab(dir);

Loading