Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw
Browse files Browse the repository at this point in the history
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw:
  GFS2: local functions should be static
  GFS2: We only need one ACL getting function
  GFS2: Fix multi-block allocation
  GFS2: decouple quota allocations from block allocations
  GFS2: split function rgblk_search
  GFS2: Fix up "off by one" in the previous patch
  GFS2: move toward a generic multi-block allocator
  GFS2: O_(D)SYNC support for fallocate
  GFS2: remove vestigial al_alloced
  GFS2: combine gfs2_alloc_block and gfs2_alloc_di
  GFS2: Add non-try locks back to get_local_rgrp
  GFS2: f_ra is always valid in dir readahead function
  GFS2: Fix very unlikley memory leak in ACL xattr code
  GFS2: More automated code analysis fixes
  GFS2: Add readahead to sequential directory traversal
  GFS2: Fix up REQ flags
  • Loading branch information
torvalds committed Jan 8, 2012
2 parents 29ad0de + 46cc1e5 commit 1619ed8
Show file tree
Hide file tree
Showing 19 changed files with 394 additions and 334 deletions.
14 changes: 5 additions & 9 deletions fs/gfs2/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ static const char *gfs2_acl_name(int type)
return NULL;
}

static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type)
struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct posix_acl *acl;
const char *name;
char *data;
Expand Down Expand Up @@ -67,11 +68,6 @@ static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type)
return acl;
}

struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
{
return gfs2_acl_get(GFS2_I(inode), type);
}

static int gfs2_set_mode(struct inode *inode, umode_t mode)
{
int error = 0;
Expand Down Expand Up @@ -125,7 +121,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode)
if (S_ISLNK(inode->i_mode))
return 0;

acl = gfs2_acl_get(dip, ACL_TYPE_DEFAULT);
acl = gfs2_get_acl(&dip->i_inode, ACL_TYPE_DEFAULT);
if (IS_ERR(acl))
return PTR_ERR(acl);
if (!acl) {
Expand Down Expand Up @@ -166,7 +162,7 @@ int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
unsigned int len;
int error;

acl = gfs2_acl_get(ip, ACL_TYPE_ACCESS);
acl = gfs2_get_acl(&ip->i_inode, ACL_TYPE_ACCESS);
if (IS_ERR(acl))
return PTR_ERR(acl);
if (!acl)
Expand Down Expand Up @@ -216,7 +212,7 @@ static int gfs2_xattr_system_get(struct dentry *dentry, const char *name,
if (type < 0)
return type;

acl = gfs2_acl_get(GFS2_I(inode), type);
acl = gfs2_get_acl(inode, type);
if (IS_ERR(acl))
return PTR_ERR(acl);
if (acl == NULL)
Expand Down
18 changes: 9 additions & 9 deletions fs/gfs2/aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
int alloc_required;
int error = 0;
struct gfs2_alloc *al = NULL;
struct gfs2_qadata *qa = NULL;
pgoff_t index = pos >> PAGE_CACHE_SHIFT;
unsigned from = pos & (PAGE_CACHE_SIZE - 1);
struct page *page;
Expand All @@ -639,8 +639,8 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks);

if (alloc_required) {
al = gfs2_alloc_get(ip);
if (!al) {
qa = gfs2_qadata_get(ip);
if (!qa) {
error = -ENOMEM;
goto out_unlock;
}
Expand All @@ -649,8 +649,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
if (error)
goto out_alloc_put;

al->al_requested = data_blocks + ind_blocks;
error = gfs2_inplace_reserve(ip);
error = gfs2_inplace_reserve(ip, data_blocks + ind_blocks);
if (error)
goto out_qunlock;
}
Expand Down Expand Up @@ -711,7 +710,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
out_qunlock:
gfs2_quota_unlock(ip);
out_alloc_put:
gfs2_alloc_put(ip);
gfs2_qadata_put(ip);
}
out_unlock:
if (&ip->i_inode == sdp->sd_rindex) {
Expand Down Expand Up @@ -848,7 +847,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
struct gfs2_sbd *sdp = GFS2_SB(inode);
struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
struct buffer_head *dibh;
struct gfs2_alloc *al = ip->i_alloc;
struct gfs2_qadata *qa = ip->i_qadata;
unsigned int from = pos & (PAGE_CACHE_SIZE - 1);
unsigned int to = from + len;
int ret;
Expand Down Expand Up @@ -880,10 +879,11 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
brelse(dibh);
failed:
gfs2_trans_end(sdp);
if (al) {
if (ip->i_res)
gfs2_inplace_release(ip);
if (qa) {
gfs2_quota_unlock(ip);
gfs2_alloc_put(ip);
gfs2_qadata_put(ip);
}
if (inode == sdp->sd_rindex) {
gfs2_glock_dq(&m_ip->i_gh);
Expand Down
26 changes: 11 additions & 15 deletions fs/gfs2/bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
and write it out to disk */

unsigned int n = 1;
error = gfs2_alloc_block(ip, &block, &n);
error = gfs2_alloc_blocks(ip, &block, &n, 0, NULL);
if (error)
goto out_brelse;
if (isdir) {
Expand Down Expand Up @@ -503,7 +503,7 @@ static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock,
do {
int error;
n = blks - alloced;
error = gfs2_alloc_block(ip, &bn, &n);
error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL);
if (error)
return error;
alloced += n;
Expand Down Expand Up @@ -743,9 +743,6 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
else if (ip->i_depth)
revokes = sdp->sd_inptrs;

if (error)
return error;

memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
bstart = 0;
blen = 0;
Expand Down Expand Up @@ -1044,7 +1041,7 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size)
lblock = (size - 1) >> sdp->sd_sb.sb_bsize_shift;

find_metapath(sdp, lblock, &mp, ip->i_height);
if (!gfs2_alloc_get(ip))
if (!gfs2_qadata_get(ip))
return -ENOMEM;

error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
Expand All @@ -1064,7 +1061,7 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size)
gfs2_quota_unhold(ip);

out:
gfs2_alloc_put(ip);
gfs2_qadata_put(ip);
return error;
}

Expand Down Expand Up @@ -1166,21 +1163,20 @@ static int do_grow(struct inode *inode, u64 size)
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
struct buffer_head *dibh;
struct gfs2_alloc *al = NULL;
struct gfs2_qadata *qa = NULL;
int error;

if (gfs2_is_stuffed(ip) &&
(size > (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)))) {
al = gfs2_alloc_get(ip);
if (al == NULL)
qa = gfs2_qadata_get(ip);
if (qa == NULL)
return -ENOMEM;

error = gfs2_quota_lock_check(ip);
if (error)
goto do_grow_alloc_put;

al->al_requested = 1;
error = gfs2_inplace_reserve(ip);
error = gfs2_inplace_reserve(ip, 1);
if (error)
goto do_grow_qunlock;
}
Expand All @@ -1189,7 +1185,7 @@ static int do_grow(struct inode *inode, u64 size)
if (error)
goto do_grow_release;

if (al) {
if (qa) {
error = gfs2_unstuff_dinode(ip, NULL);
if (error)
goto do_end_trans;
Expand All @@ -1208,12 +1204,12 @@ static int do_grow(struct inode *inode, u64 size)
do_end_trans:
gfs2_trans_end(sdp);
do_grow_release:
if (al) {
if (qa) {
gfs2_inplace_release(ip);
do_grow_qunlock:
gfs2_quota_unlock(ip);
do_grow_alloc_put:
gfs2_alloc_put(ip);
gfs2_qadata_put(ip);
}
return error;
}
Expand Down
64 changes: 58 additions & 6 deletions fs/gfs2/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@
#define IS_LEAF 1 /* Hashed (leaf) directory */
#define IS_DINODE 2 /* Linear (stuffed dinode block) directory */

#define MAX_RA_BLOCKS 32 /* max read-ahead blocks */

#define gfs2_disk_hash2offset(h) (((u64)(h)) >> 1)
#define gfs2_dir_offset2hash(p) ((u32)(((u64)(p)) << 1))

Expand Down Expand Up @@ -821,7 +823,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
struct gfs2_dirent *dent;
struct qstr name = { .name = "", .len = 0, .hash = 0 };

error = gfs2_alloc_block(ip, &bn, &n);
error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL);
if (error)
return NULL;
bh = gfs2_meta_new(ip->i_gl, bn);
Expand Down Expand Up @@ -1376,6 +1378,52 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
return error;
}

/**
* gfs2_dir_readahead - Issue read-ahead requests for leaf blocks.
*
* Note: we can't calculate each index like dir_e_read can because we don't
* have the leaf, and therefore we don't have the depth, and therefore we
* don't have the length. So we have to just read enough ahead to make up
* for the loss of information.
*/
static void gfs2_dir_readahead(struct inode *inode, unsigned hsize, u32 index,
struct file_ra_state *f_ra)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_glock *gl = ip->i_gl;
struct buffer_head *bh;
u64 blocknr = 0, last;
unsigned count;

/* First check if we've already read-ahead for the whole range. */
if (index + MAX_RA_BLOCKS < f_ra->start)
return;

f_ra->start = max((pgoff_t)index, f_ra->start);
for (count = 0; count < MAX_RA_BLOCKS; count++) {
if (f_ra->start >= hsize) /* if exceeded the hash table */
break;

last = blocknr;
blocknr = be64_to_cpu(ip->i_hash_cache[f_ra->start]);
f_ra->start++;
if (blocknr == last)
continue;

bh = gfs2_getbuf(gl, blocknr, 1);
if (trylock_buffer(bh)) {
if (buffer_uptodate(bh)) {
unlock_buffer(bh);
brelse(bh);
continue;
}
bh->b_end_io = end_buffer_read_sync;
submit_bh(READA | REQ_META, bh);
continue;
}
brelse(bh);
}
}

/**
* dir_e_read - Reads the entries from a directory into a filldir buffer
Expand All @@ -1388,7 +1436,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
*/

static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
filldir_t filldir)
filldir_t filldir, struct file_ra_state *f_ra)
{
struct gfs2_inode *dip = GFS2_I(inode);
u32 hsize, len = 0;
Expand All @@ -1402,10 +1450,14 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
hash = gfs2_dir_offset2hash(*offset);
index = hash >> (32 - dip->i_depth);

if (dip->i_hash_cache == NULL)
f_ra->start = 0;
lp = gfs2_dir_get_hash_table(dip);
if (IS_ERR(lp))
return PTR_ERR(lp);

gfs2_dir_readahead(inode, hsize, index, f_ra);

while (index < hsize) {
error = gfs2_dir_read_leaf(inode, offset, opaque, filldir,
&copied, &depth,
Expand All @@ -1423,7 +1475,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
}

int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
filldir_t filldir)
filldir_t filldir, struct file_ra_state *f_ra)
{
struct gfs2_inode *dip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
Expand All @@ -1437,7 +1489,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
return 0;

if (dip->i_diskflags & GFS2_DIF_EXHASH)
return dir_e_read(inode, offset, opaque, filldir);
return dir_e_read(inode, offset, opaque, filldir, f_ra);

if (!gfs2_is_stuffed(dip)) {
gfs2_consist_inode(dip);
Expand Down Expand Up @@ -1798,7 +1850,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
if (!ht)
return -ENOMEM;

if (!gfs2_alloc_get(dip)) {
if (!gfs2_qadata_get(dip)) {
error = -ENOMEM;
goto out;
}
Expand Down Expand Up @@ -1887,7 +1939,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
gfs2_rlist_free(&rlist);
gfs2_quota_unhold(dip);
out_put:
gfs2_alloc_put(dip);
gfs2_qadata_put(dip);
out:
kfree(ht);
return error;
Expand Down
2 changes: 1 addition & 1 deletion fs/gfs2/dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ extern int gfs2_dir_add(struct inode *inode, 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);
filldir_t filldir, struct file_ra_state *f_ra);
extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
const struct gfs2_inode *nip, unsigned int new_type);

Expand Down
3 changes: 2 additions & 1 deletion fs/gfs2/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ static int gfs2_get_name(struct dentry *parent, char *name,
struct gfs2_holder gh;
u64 offset = 0;
int error;
struct file_ra_state f_ra = { .start = 0 };

if (!dir)
return -EINVAL;
Expand All @@ -118,7 +119,7 @@ static int gfs2_get_name(struct dentry *parent, char *name,
if (error)
return error;

error = gfs2_dir_read(dir, &offset, &gnfd, get_name_filldir);
error = gfs2_dir_read(dir, &offset, &gnfd, get_name_filldir, &f_ra);

gfs2_glock_dq_uninit(&gh);

Expand Down
Loading

0 comments on commit 1619ed8

Please sign in to comment.