Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw
Browse files Browse the repository at this point in the history
* 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
  ...
  • Loading branch information
torvalds committed May 20, 2011
2 parents 82aff10 + f2741d9 commit 6c1b8d9
Show file tree
Hide file tree
Showing 25 changed files with 1,865 additions and 2,032 deletions.
4 changes: 2 additions & 2 deletions fs/gfs2/Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
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
Expand Down
8 changes: 6 additions & 2 deletions fs/gfs2/aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
197 changes: 88 additions & 109 deletions fs/gfs2/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1887,14 +1815,18 @@ 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) {
error = get_leaf(dip, blk, &bh);
if (error)
goto out_rlist;
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);
brelse(bh);
if (blk != leaf_no)
brelse(bh);

gfs2_rlist_add(sdp, &rlist, blk);
l_blocks++;
Expand All @@ -1918,13 +1850,18 @@ 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) {
error = get_leaf(dip, blk, &bh);
if (error)
goto out_end_trans;
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);
brelse(bh);
if (blk != leaf_no)
brelse(bh);

gfs2_free_meta(dip, blk, 1);
gfs2_add_inode_blocks(&dip->i_inode, -1);
Expand All @@ -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);

Expand Down Expand Up @@ -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;

error = gfs2_trans_begin(sdp, RES_DINODE, 0);
if (error)
return error;
while (index < hsize) {
lp_offset = index & (sdp->sd_hash_ptrs - 1);
ht_offset = index - lp_offset;

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);
brelse(bh);
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));

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;
}
Expand Down
4 changes: 2 additions & 2 deletions fs/gfs2/dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion fs/gfs2/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 6c1b8d9

Please sign in to comment.