Skip to content

Commit

Permalink
Merge tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/gfs2/linux-gfs2

Pull GFS2 updates from Bob Peterson:
 "We only have six patches ready for this merge window:

   - Arnd Bergmann contributed a patch that fixes an uninitialized
     variable warning.

   - The second patch avoids a kernel panic due to referencing an iopen
     glock that may not be held, in an error path.

   - The third patch fixes a rounding error that caused xfs_tests direct
     IO write "fsx" tests to fail on GFS2.

   - The fourth patch tidies up the code path when glocks are being
     reused to recreate a dinode that was recently deleted.

   - The fifth reverts an ages-old patch that should no longer be
     needed, and which interfered with the transition of dinodes from
     unlinked to free.

   - And lastly, a patch to eliminate a function parameter that's not
     needed"

* tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  GFS2: Eliminate parameter non_block on gfs2_inode_lookup
  GFS2: Don't filter out I_FREEING inodes anymore
  GFS2: Prevent delete work from occurring on glocks used for create
  GFS2: Fix direct IO write rounding error
  gfs2: avoid uninitialized variable warning
  GFS2: Check if iopen is held when deleting inode
  • Loading branch information
Linus Torvalds committed Mar 17, 2016
2 parents d77bed0 + 73b462d commit 1ca80a0
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 79 deletions.
2 changes: 1 addition & 1 deletion fs/gfs2/aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1082,7 +1082,7 @@ static ssize_t gfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
* the first place, mapping->nr_pages will always be zero.
*/
if (mapping->nrpages) {
loff_t lstart = offset & (PAGE_CACHE_SIZE - 1);
loff_t lstart = offset & ~(PAGE_CACHE_SIZE - 1);
loff_t len = iov_iter_count(iter);
loff_t end = PAGE_ALIGN(offset + len) - 1;

Expand Down
6 changes: 3 additions & 3 deletions fs/gfs2/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,7 @@ static int get_first_leaf(struct gfs2_inode *dip, u32 index,
int error;

error = get_leaf_nr(dip, index, &leaf_no);
if (!error)
if (!IS_ERR_VALUE(error))
error = get_leaf(dip, leaf_no, bh_out);

return error;
Expand Down Expand Up @@ -1014,7 +1014,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)

index = name->hash >> (32 - dip->i_depth);
error = get_leaf_nr(dip, index, &leaf_no);
if (error)
if (IS_ERR_VALUE(error))
return error;

/* Get the old leaf block */
Expand Down Expand Up @@ -1660,7 +1660,7 @@ struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name,
brelse(bh);
if (fail_on_exist)
return ERR_PTR(-EEXIST);
inode = gfs2_inode_lookup(dir->i_sb, dtype, addr, formal_ino, 0);
inode = gfs2_inode_lookup(dir->i_sb, dtype, addr, formal_ino);
if (!IS_ERR(inode))
GFS2_I(inode)->i_rahead = rahead;
return inode;
Expand Down
2 changes: 1 addition & 1 deletion fs/gfs2/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,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, 0);
inode = gfs2_ilookup(sb, inum->no_addr);
if (inode) {
if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
iput(inode);
Expand Down
10 changes: 9 additions & 1 deletion fs/gfs2/glock.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,17 +572,24 @@ static void delete_work_func(struct work_struct *work)
struct inode *inode;
u64 no_addr = gl->gl_name.ln_number;

/* If someone's using this glock to create a new dinode, the block must
have been freed by another node, then re-used, in which case our
iopen callback is too late after the fact. Ignore it. */
if (test_bit(GLF_INODE_CREATING, &gl->gl_flags))
goto out;

ip = gl->gl_object;
/* Note: Unsafe to dereference ip as we don't hold right refs/locks */

if (ip)
inode = gfs2_ilookup(sdp->sd_vfs, no_addr, 1);
inode = gfs2_ilookup(sdp->sd_vfs, no_addr);
else
inode = gfs2_lookup_by_inum(sdp, no_addr, NULL, GFS2_BLKST_UNLINKED);
if (inode && !IS_ERR(inode)) {
d_prune_aliases(inode);
iput(inode);
}
out:
gfs2_glock_put(gl);
}

Expand Down Expand Up @@ -1015,6 +1022,7 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
handle_callback(gl, LM_ST_UNLOCKED, 0, false);

list_del_init(&gh->gh_list);
clear_bit(HIF_HOLDER, &gh->gh_iflags);
if (find_first_holder(gl) == NULL) {
if (glops->go_unlock) {
GLOCK_BUG_ON(gl, test_and_set_bit(GLF_LOCK, &gl->gl_flags));
Expand Down
1 change: 1 addition & 0 deletions fs/gfs2/incore.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ enum {
GLF_LRU = 13,
GLF_OBJECT = 14, /* Used only for tracing */
GLF_BLOCKING = 15,
GLF_INODE_CREATING = 16, /* Inode creation occurring */
};

struct gfs2_glock {
Expand Down
71 changes: 12 additions & 59 deletions fs/gfs2/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,61 +37,9 @@
#include "super.h"
#include "glops.h"

struct gfs2_skip_data {
u64 no_addr;
int skipped;
int non_block;
};

static int iget_test(struct inode *inode, void *opaque)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_skip_data *data = opaque;

if (ip->i_no_addr == data->no_addr) {
if (data->non_block &&
inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) {
data->skipped = 1;
return 0;
}
return 1;
}
return 0;
}

static int iget_set(struct inode *inode, void *opaque)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_skip_data *data = opaque;

if (data->skipped)
return -ENOENT;
inode->i_ino = (unsigned long)(data->no_addr);
ip->i_no_addr = data->no_addr;
return 0;
}

struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr, int non_block)
struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr)
{
unsigned long hash = (unsigned long)no_addr;
struct gfs2_skip_data data;

data.no_addr = no_addr;
data.skipped = 0;
data.non_block = non_block;
return ilookup5(sb, hash, iget_test, &data);
}

static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr,
int non_block)
{
struct gfs2_skip_data data;
unsigned long hash = (unsigned long)no_addr;

data.no_addr = no_addr;
data.skipped = 0;
data.non_block = non_block;
return iget5_locked(sb, hash, iget_test, iget_set, &data);
return ilookup(sb, (unsigned long)no_addr);
}

/**
Expand Down Expand Up @@ -132,21 +80,21 @@ static void gfs2_set_iop(struct inode *inode)
* @sb: The super block
* @no_addr: The inode number
* @type: The type of the inode
* non_block: Can we block on inodes that are being freed?
*
* Returns: A VFS inode, or an error
*/

struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
u64 no_addr, u64 no_formal_ino, int non_block)
u64 no_addr, u64 no_formal_ino)
{
struct inode *inode;
struct gfs2_inode *ip;
struct gfs2_glock *io_gl = NULL;
int error;

inode = gfs2_iget(sb, no_addr, non_block);
inode = iget_locked(sb, (unsigned long)no_addr);
ip = GFS2_I(inode);
ip->i_no_addr = no_addr;

if (!inode)
return ERR_PTR(-ENOMEM);
Expand Down Expand Up @@ -221,7 +169,7 @@ struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr,
if (error)
goto fail;

inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0, 1);
inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0);
if (IS_ERR(inode))
goto fail;

Expand Down Expand Up @@ -592,7 +540,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
struct inode *inode = NULL;
struct gfs2_inode *dip = GFS2_I(dir), *ip;
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct gfs2_glock *io_gl;
struct gfs2_glock *io_gl = NULL;
int error, free_vfs_inode = 1;
u32 aflags = 0;
unsigned blocks = 1;
Expand Down Expand Up @@ -729,6 +677,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
if (error)
goto fail_gunlock2;

BUG_ON(test_and_set_bit(GLF_INODE_CREATING, &io_gl->gl_flags));

error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
if (error)
goto fail_gunlock2;
Expand Down Expand Up @@ -771,12 +721,15 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
}
gfs2_glock_dq_uninit(ghs);
gfs2_glock_dq_uninit(ghs + 1);
clear_bit(GLF_INODE_CREATING, &io_gl->gl_flags);
return error;

fail_gunlock3:
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
gfs2_glock_put(io_gl);
fail_gunlock2:
if (io_gl)
clear_bit(GLF_INODE_CREATING, &io_gl->gl_flags);
gfs2_glock_dq_uninit(ghs + 1);
fail_free_inode:
if (ip->i_gl)
Expand Down
5 changes: 2 additions & 3 deletions fs/gfs2/inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,11 @@ static inline int gfs2_check_internal_file_size(struct inode *inode,
}

extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type,
u64 no_addr, u64 no_formal_ino,
int non_block);
u64 no_addr, u64 no_formal_ino);
extern struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr,
u64 *no_formal_ino,
unsigned int blktype);
extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr, int nonblock);
extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr);

extern int gfs2_inode_refresh(struct gfs2_inode *ip);

Expand Down
2 changes: 1 addition & 1 deletion fs/gfs2/ops_fstype.c
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ static int gfs2_lookup_root(struct super_block *sb, struct dentry **dptr,
struct dentry *dentry;
struct inode *inode;

inode = gfs2_inode_lookup(sb, DT_DIR, no_addr, 0, 0);
inode = gfs2_inode_lookup(sb, DT_DIR, no_addr, 0);
if (IS_ERR(inode)) {
fs_err(sdp, "can't read in %s inode: %ld\n", name, PTR_ERR(inode));
return PTR_ERR(inode);
Expand Down
26 changes: 16 additions & 10 deletions fs/gfs2/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1551,12 +1551,16 @@ static void gfs2_evict_inode(struct inode *inode)
goto out_truncate;
}

ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
gfs2_glock_dq_wait(&ip->i_iopen_gh);
gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh);
error = gfs2_glock_nq(&ip->i_iopen_gh);
if (error)
goto out_truncate;
if (ip->i_iopen_gh.gh_gl &&
test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) {
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
gfs2_glock_dq_wait(&ip->i_iopen_gh);
gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE,
&ip->i_iopen_gh);
error = gfs2_glock_nq(&ip->i_iopen_gh);
if (error)
goto out_truncate;
}

/* Case 1 starts here */

Expand Down Expand Up @@ -1606,11 +1610,13 @@ static void gfs2_evict_inode(struct inode *inode)
if (gfs2_rs_active(&ip->i_res))
gfs2_rs_deltree(&ip->i_res);

if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) {
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
gfs2_glock_dq_wait(&ip->i_iopen_gh);
if (ip->i_iopen_gh.gh_gl) {
if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) {
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
gfs2_glock_dq_wait(&ip->i_iopen_gh);
}
gfs2_holder_uninit(&ip->i_iopen_gh);
}
gfs2_holder_uninit(&ip->i_iopen_gh);
gfs2_glock_dq_uninit(&gh);
if (error && error != GLR_TRYFAILED && error != -EROFS)
fs_warn(sdp, "gfs2_evict_inode: %d\n", error);
Expand Down

0 comments on commit 1ca80a0

Please sign in to comment.