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
Pull GFS2 updates from Steven Whitehouse:
 "There are a few bug fixes for various, mostly very minor corner cases,
  plus some interesting new features.

  The new features include atomic_open whose main benefit will be the
  reduction in locking overhead in case of combined lookup/create and
  open operations, sorting the log buffer lists by block number to
  improve the efficiency of AIL writeback, and aggressively issuing
  revokes in gfs2_log_flush to reduce overhead when dropping glocks."

* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw:
  GFS2: Reserve journal space for quota change in do_grow
  GFS2: Fix fstrim boundary conditions
  GFS2: fix warning message
  GFS2: aggressively issue revokes in gfs2_log_flush
  GFS2: fix regression in dir_double_exhash
  GFS2: Add atomic_open support
  GFS2: Only do one directory search on create
  GFS2: fix error propagation in init_threads()
  GFS2: Remove no-op wrapper function
  GFS2: Cocci spatch "ptr_ret.spatch"
  GFS2: Eliminate gfs2_rg_lops
  GFS2: Sort buffer lists by inplace block number
  • Loading branch information
Linus Torvalds committed Jul 2, 2013
2 parents 9e239bb + a01aedf commit c4eb1b0
Show file tree
Hide file tree
Showing 17 changed files with 291 additions and 126 deletions.
11 changes: 9 additions & 2 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1612,6 +1612,10 @@ EXPORT_SYMBOL(d_obtain_alias);
* If a dentry was found and moved, then it is returned. Otherwise NULL
* is returned. This matches the expected return value of ->lookup.
*
* Cluster filesystems may call this function with a negative, hashed dentry.
* In that case, we know that the inode will be a regular file, and also this
* will only occur during atomic_open. So we need to check for the dentry
* being already hashed only in the final case.
*/
struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
{
Expand All @@ -1636,8 +1640,11 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
security_d_instantiate(dentry, inode);
d_rehash(dentry);
}
} else
d_add(dentry, inode);
} else {
d_instantiate(dentry, inode);
if (d_unhashed(dentry))
d_rehash(dentry);
}
return new;
}
EXPORT_SYMBOL(d_splice_alias);
Expand Down
4 changes: 3 additions & 1 deletion fs/gfs2/bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1232,7 +1232,9 @@ static int do_grow(struct inode *inode, u64 size)
unstuff = 1;
}

error = gfs2_trans_begin(sdp, RES_DINODE + RES_STATFS + RES_RG_BIT, 0);
error = gfs2_trans_begin(sdp, RES_DINODE + RES_STATFS + RES_RG_BIT +
(sdp->sd_args.ar_quota == GFS2_QUOTA_OFF ?
0 : RES_QUOTA), 0);
if (error)
goto do_grow_release;

Expand Down
26 changes: 15 additions & 11 deletions fs/gfs2/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1125,13 +1125,14 @@ static int dir_double_exhash(struct gfs2_inode *dip)
if (IS_ERR(hc))
return PTR_ERR(hc);

h = hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS | __GFP_NOWARN);
hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS | __GFP_NOWARN);
if (hc2 == NULL)
hc2 = __vmalloc(hsize_bytes * 2, GFP_NOFS, PAGE_KERNEL);

if (!hc2)
return -ENOMEM;

h = hc2;
error = gfs2_meta_inode_buffer(dip, &dibh);
if (error)
goto out_kfree;
Expand Down Expand Up @@ -1547,32 +1548,35 @@ int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,

/**
* gfs2_dir_search - Search a directory
* @dip: The GFS2 inode
* @filename:
* @inode:
* @dip: The GFS2 dir inode
* @name: The name we are looking up
* @fail_on_exist: Fail if the name exists rather than looking it up
*
* This routine searches a directory for a file or another directory.
* Assumes a glock is held on dip.
*
* Returns: errno
*/

struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name)
struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name,
bool fail_on_exist)
{
struct buffer_head *bh;
struct gfs2_dirent *dent;
struct inode *inode;
u64 addr, formal_ino;
u16 dtype;

dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
if (dent) {
if (IS_ERR(dent))
return ERR_CAST(dent);
inode = gfs2_inode_lookup(dir->i_sb,
be16_to_cpu(dent->de_type),
be64_to_cpu(dent->de_inum.no_addr),
be64_to_cpu(dent->de_inum.no_formal_ino), 0);
dtype = be16_to_cpu(dent->de_type);
addr = be64_to_cpu(dent->de_inum.no_addr);
formal_ino = be64_to_cpu(dent->de_inum.no_formal_ino);
brelse(bh);
return inode;
if (fail_on_exist)
return ERR_PTR(-EEXIST);
return gfs2_inode_lookup(dir->i_sb, dtype, addr, formal_ino, 0);
}
return ERR_PTR(-ENOENT);
}
Expand Down
3 changes: 2 additions & 1 deletion fs/gfs2/dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ struct gfs2_inode;
struct gfs2_inum;

extern struct inode *gfs2_dir_search(struct inode *dir,
const struct qstr *filename);
const struct qstr *filename,
bool fail_on_exist);
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,
Expand Down
69 changes: 46 additions & 23 deletions fs/gfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -531,51 +531,74 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
}

/**
* gfs2_open - open a file
* @inode: the inode to open
* @file: the struct file for this opening
* gfs2_open_common - This is common to open and atomic_open
* @inode: The inode being opened
* @file: The file being opened
*
* Returns: errno
* This maybe called under a glock or not depending upon how it has
* been called. We must always be called under a glock for regular
* files, however. For other file types, it does not matter whether
* we hold the glock or not.
*
* Returns: Error code or 0 for success
*/

static int gfs2_open(struct inode *inode, struct file *file)
int gfs2_open_common(struct inode *inode, struct file *file)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder i_gh;
struct gfs2_file *fp;
int error;
int ret;

fp = kzalloc(sizeof(struct gfs2_file), GFP_KERNEL);
if (S_ISREG(inode->i_mode)) {
ret = generic_file_open(inode, file);
if (ret)
return ret;
}

fp = kzalloc(sizeof(struct gfs2_file), GFP_NOFS);
if (!fp)
return -ENOMEM;

mutex_init(&fp->f_fl_mutex);

gfs2_assert_warn(GFS2_SB(inode), !file->private_data);
file->private_data = fp;
return 0;
}

/**
* gfs2_open - open a file
* @inode: the inode to open
* @file: the struct file for this opening
*
* After atomic_open, this function is only used for opening files
* which are already cached. We must still get the glock for regular
* files to ensure that we have the file size uptodate for the large
* file check which is in the common code. That is only an issue for
* regular files though.
*
* Returns: errno
*/

static int gfs2_open(struct inode *inode, struct file *file)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder i_gh;
int error;
bool need_unlock = false;

if (S_ISREG(ip->i_inode.i_mode)) {
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY,
&i_gh);
if (error)
goto fail;
return error;
need_unlock = true;
}

if (!(file->f_flags & O_LARGEFILE) &&
i_size_read(inode) > MAX_NON_LFS) {
error = -EOVERFLOW;
goto fail_gunlock;
}
error = gfs2_open_common(inode, file);

if (need_unlock)
gfs2_glock_dq_uninit(&i_gh);
}

return 0;

fail_gunlock:
gfs2_glock_dq_uninit(&i_gh);
fail:
file->private_data = NULL;
kfree(fp);
return error;
}

Expand Down
8 changes: 0 additions & 8 deletions fs/gfs2/glops.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
struct gfs2_bufdata *bd, *tmp;
struct buffer_head *bh;
const unsigned long b_state = (1UL << BH_Dirty)|(1UL << BH_Pinned)|(1UL << BH_Lock);
sector_t blocknr;

gfs2_log_lock(sdp);
spin_lock(&sdp->sd_ail_lock);
Expand All @@ -65,13 +64,6 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
continue;
gfs2_ail_error(gl, bh);
}
blocknr = bh->b_blocknr;
bh->b_private = NULL;
gfs2_remove_from_ail(bd); /* drops ref on bh */

bd->bd_bh = NULL;
bd->bd_blkno = blocknr;

gfs2_trans_add_revoke(sdp, bd);
}
GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count));
Expand Down
Loading

0 comments on commit c4eb1b0

Please sign in to comment.