Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c1b8d94 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw: (32 commits)
  GFS2: Move all locking inside the inode creation function
  GFS2: Clean up symlink creation
  GFS2: Clean up mkdir
  GFS2: Use UUID field in generic superblock
  GFS2: Rename ops_inode.c to inode.c
  GFS2: Inode.c is empty now, remove it
  GFS2: Move final part of inode.c into super.c
  GFS2: Move most of the remaining inode.c into ops_inode.c
  GFS2: Move gfs2_refresh_inode() and friends into glops.c
  GFS2: Remove gfs2_dinode_print() function
  GFS2: When adding a new dir entry, inc link count if it is a subdir
  GFS2: Make gfs2_dir_del update link count when required
  GFS2: Don't use gfs2_change_nlink in link syscall
  GFS2: Don't use a try lock when promoting to a higher mode
  GFS2: Double check link count under glock
  GFS2: Improve bug trap code in ->releasepage()
  GFS2: Fix ail list traversal
  GFS2: make sure fallocate bytes is a multiple of blksize
  GFS2: Add an AIL writeback tracepoint
  GFS2: Make writeback more responsive to system conditions
  ...
parents 82aff107 f2741d98
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
ccflags-y := -I$(src)
obj-$(CONFIG_GFS2_FS) += gfs2.o
gfs2-y := acl.o bmap.o dir.o xattr.o glock.o \
	glops.o inode.o log.o lops.o main.o meta_io.o \
	glops.o log.o lops.o main.o meta_io.o \
	aops.o dentry.o export.o file.o \
	ops_fstype.o ops_inode.o quota.o \
	ops_fstype.o inode.o quota.o \
	recovery.o rgrp.o super.o sys.o trans.o util.o

gfs2-$(CONFIG_GFS2_FS_LOCKING_DLM) += lock_dlm.o
+6 −2
Original line number Diff line number Diff line
@@ -1076,8 +1076,8 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
		bd = bh->b_private;
		if (bd && bd->bd_ail)
			goto cannot_release;
		gfs2_assert_warn(sdp, !buffer_pinned(bh));
		gfs2_assert_warn(sdp, !buffer_dirty(bh));
		if (buffer_pinned(bh) || buffer_dirty(bh))
			goto not_possible;
		bh = bh->b_this_page;
	} while(bh != head);
	gfs2_log_unlock(sdp);
@@ -1107,6 +1107,10 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
	} while (bh != head);

	return try_to_free_buffers(page);

not_possible: /* Should never happen */
	WARN_ON(buffer_dirty(bh));
	WARN_ON(buffer_pinned(bh));
cannot_release:
	gfs2_log_unlock(sdp);
	return 0;
+88 −109
Original line number Diff line number Diff line
@@ -82,12 +82,9 @@
struct qstr gfs2_qdot __read_mostly;
struct qstr gfs2_qdotdot __read_mostly;

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);


int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
			    struct buffer_head **bhp)
{
@@ -1600,7 +1597,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_inode *nip, unsigned type)
		 const struct gfs2_inode *nip)
{
	struct gfs2_inode *ip = GFS2_I(inode);
	struct buffer_head *bh;
@@ -1616,7 +1613,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
				return PTR_ERR(dent);
			dent = gfs2_init_dirent(inode, dent, name, bh);
			gfs2_inum_out(nip, dent);
			dent->de_type = cpu_to_be16(type);
			dent->de_type = cpu_to_be16(IF2DT(nip->i_inode.i_mode));
			if (ip->i_diskflags & GFS2_DIF_EXHASH) {
				leaf = (struct gfs2_leaf *)bh->b_data;
				be16_add_cpu(&leaf->lf_entries, 1);
@@ -1628,6 +1625,8 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
			gfs2_trans_add_bh(ip->i_gl, bh, 1);
			ip->i_entries++;
			ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
			if (S_ISDIR(nip->i_inode.i_mode))
				inc_nlink(&ip->i_inode);
			gfs2_dinode_out(ip, bh->b_data);
			brelse(bh);
			error = 0;
@@ -1672,8 +1671,9 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
 * Returns: 0 on success, error code on failure
 */

int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry)
{
	const struct qstr *name = &dentry->d_name;
	struct gfs2_dirent *dent, *prev = NULL;
	struct buffer_head *bh;
	int error;
@@ -1714,6 +1714,8 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
	gfs2_trans_add_bh(dip->i_gl, bh, 1);
	dip->i_entries--;
	dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME;
	if (S_ISDIR(dentry->d_inode->i_mode))
		drop_nlink(&dip->i_inode);
	gfs2_dinode_out(dip, bh->b_data);
	brelse(bh);
	mark_inode_dirty(&dip->i_inode);
@@ -1767,95 +1769,21 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
	return 0;
}

/**
 * foreach_leaf - call a function for each leaf in a directory
 * @dip: the directory
 * @lc: the function to call for each each
 * @data: private data to pass to it
 *
 * Returns: errno
 */

static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
{
	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
	struct buffer_head *bh;
	struct gfs2_leaf *leaf;
	u32 hsize, len;
	u32 ht_offset, lp_offset, ht_offset_cur = -1;
	u32 index = 0;
	__be64 *lp;
	u64 leaf_no;
	int error = 0;

	hsize = 1 << dip->i_depth;
	if (hsize * sizeof(u64) != i_size_read(&dip->i_inode)) {
		gfs2_consist_inode(dip);
		return -EIO;
	}

	lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS);
	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_dir_read_data(dip, (char *)lp,
						ht_offset * sizeof(__be64),
						sdp->sd_hash_bsize, 1);
			if (error != sdp->sd_hash_bsize) {
				if (error >= 0)
					error = -EIO;
				goto out;
			}
			ht_offset_cur = ht_offset;
		}

		leaf_no = be64_to_cpu(lp[lp_offset]);
		if (leaf_no) {
			error = get_leaf(dip, leaf_no, &bh);
			if (error)
				goto out;
			leaf = (struct gfs2_leaf *)bh->b_data;
			len = 1 << (dip->i_depth - be16_to_cpu(leaf->lf_depth));
			brelse(bh);

			error = lc(dip, index, len, leaf_no, data);
			if (error)
				goto out;

			index = (index & ~(len - 1)) + len;
		} else
			index++;
	}

	if (index != hsize) {
		gfs2_consist_inode(dip);
		error = -EIO;
	}

out:
	kfree(lp);

	return error;
}

/**
 * leaf_dealloc - Deallocate a directory leaf
 * @dip: the directory
 * @index: the hash table offset in the directory
 * @len: the number of pointers to this leaf
 * @leaf_no: the leaf number
 * @data: not used
 * @leaf_bh: buffer_head for the starting leaf
 * last_dealloc: 1 if this is the final dealloc for the leaf, else 0
 *
 * Returns: errno
 */

static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
			u64 leaf_no, void *data)
			u64 leaf_no, struct buffer_head *leaf_bh,
			int last_dealloc)
{
	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
	struct gfs2_leaf *tmp_leaf;
@@ -1887,13 +1815,17 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
		goto out_qs;

	/*  Count the number of leaves  */
	bh = leaf_bh;

	for (blk = leaf_no; blk; blk = nblk) {
		if (blk != leaf_no) {
			error = get_leaf(dip, blk, &bh);
			if (error)
				goto out_rlist;
		}
		tmp_leaf = (struct gfs2_leaf *)bh->b_data;
		nblk = be64_to_cpu(tmp_leaf->lf_next);
		if (blk != leaf_no)
			brelse(bh);

		gfs2_rlist_add(sdp, &rlist, blk);
@@ -1918,12 +1850,17 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
	if (error)
		goto out_rg_gunlock;

	bh = leaf_bh;

	for (blk = leaf_no; blk; blk = nblk) {
		if (blk != leaf_no) {
			error = get_leaf(dip, blk, &bh);
			if (error)
				goto out_end_trans;
		}
		tmp_leaf = (struct gfs2_leaf *)bh->b_data;
		nblk = be64_to_cpu(tmp_leaf->lf_next);
		if (blk != leaf_no)
			brelse(bh);

		gfs2_free_meta(dip, blk, 1);
@@ -1942,6 +1879,10 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
		goto out_end_trans;

	gfs2_trans_add_bh(dip->i_gl, dibh, 1);
	/* On the last dealloc, make this a regular file in case we crash.
	   (We don't want to free these blocks a second time.)  */
	if (last_dealloc)
		dip->i_inode.i_mode = S_IFREG;
	gfs2_dinode_out(dip, dibh->b_data);
	brelse(dibh);

@@ -1975,29 +1916,67 @@ int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip)
{
	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
	struct buffer_head *bh;
	int error;
	struct gfs2_leaf *leaf;
	u32 hsize, len;
	u32 ht_offset, lp_offset, ht_offset_cur = -1;
	u32 index = 0, next_index;
	__be64 *lp;
	u64 leaf_no;
	int error = 0, last;

	/* Dealloc on-disk leaves to FREEMETA state */
	error = foreach_leaf(dip, leaf_dealloc, NULL);
	if (error)
		return error;
	hsize = 1 << dip->i_depth;
	if (hsize * sizeof(u64) != i_size_read(&dip->i_inode)) {
		gfs2_consist_inode(dip);
		return -EIO;
	}

	/* Make this a regular file in case we crash.
	   (We don't want to free these blocks a second time.)  */
	lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS);
	if (!lp)
		return -ENOMEM;

	while (index < hsize) {
		lp_offset = index & (sdp->sd_hash_ptrs - 1);
		ht_offset = index - lp_offset;

	error = gfs2_trans_begin(sdp, RES_DINODE, 0);
		if (ht_offset_cur != ht_offset) {
			error = gfs2_dir_read_data(dip, (char *)lp,
						ht_offset * sizeof(__be64),
						sdp->sd_hash_bsize, 1);
			if (error != sdp->sd_hash_bsize) {
				if (error >= 0)
					error = -EIO;
				goto out;
			}
			ht_offset_cur = ht_offset;
		}

		leaf_no = be64_to_cpu(lp[lp_offset]);
		if (leaf_no) {
			error = get_leaf(dip, leaf_no, &bh);
			if (error)
		return error;
				goto out;
			leaf = (struct gfs2_leaf *)bh->b_data;
			len = 1 << (dip->i_depth - be16_to_cpu(leaf->lf_depth));

	error = gfs2_meta_inode_buffer(dip, &bh);
	if (!error) {
		gfs2_trans_add_bh(dip->i_gl, bh, 1);
		((struct gfs2_dinode *)bh->b_data)->di_mode =
						cpu_to_be32(S_IFREG);
			next_index = (index & ~(len - 1)) + len;
			last = ((next_index >= hsize) ? 1 : 0);
			error = leaf_dealloc(dip, index, len, leaf_no, bh,
					     last);
			brelse(bh);
			if (error)
				goto out;
			index = next_index;
		} else
			index++;
	}

	gfs2_trans_end(sdp);
	if (index != hsize) {
		gfs2_consist_inode(dip);
		error = -EIO;
	}

out:
	kfree(lp);

	return error;
}
+2 −2
Original line number Diff line number Diff line
@@ -22,8 +22,8 @@ extern struct inode *gfs2_dir_search(struct inode *dir,
extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
			  const struct gfs2_inode *ip);
extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
			const struct gfs2_inode *ip, unsigned int type);
extern int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
			const struct gfs2_inode *ip);
extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry);
extern int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
			 filldir_t filldir);
extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
+1 −1
Original line number Diff line number Diff line
@@ -139,7 +139,7 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb,
	struct gfs2_sbd *sdp = sb->s_fs_info;
	struct inode *inode;

	inode = gfs2_ilookup(sb, inum->no_addr);
	inode = gfs2_ilookup(sb, inum->no_addr, 0);
	if (inode) {
		if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
			iput(inode);
Loading