Skip to content

Commit

Permalink
[GFS2] Fix for lock recursion problem for internal files
Browse files Browse the repository at this point in the history
Two internal files which are read through the gfs2_internal_read()
routine were already locked when the routine was called and this
do not need locking at the redapages level.

This patch introduces a struct file which is used as a sentinal
so that readpage will only perform locking in the case that the
struct file passed to it is _not_ equal to this sentinal.

Since the comments in the generic kernel code indicate that the
struct file will never be used for anything other than passing
straight through to readpage(), this should be ok.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
  • Loading branch information
Steven Whitehouse committed Feb 15, 2006
1 parent 4dd651a commit 61a30dc
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 8 deletions.
17 changes: 11 additions & 6 deletions fs/gfs2/ops_address.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "quota.h"
#include "trans.h"
#include "rgrp.h"
#include "ops_file.h"

/**
* gfs2_get_block - Fills in a buffer head with details about a block
Expand Down Expand Up @@ -267,10 +268,12 @@ static int gfs2_readpage(struct file *file, struct page *page)

atomic_inc(&sdp->sd_ops_address);

gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
error = gfs2_glock_nq_m_atime(1, &gh);
if (error)
goto out_unlock;
if (file != &gfs2_internal_file_sentinal) {
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
error = gfs2_glock_nq_m_atime(1, &gh);
if (error)
goto out_unlock;
}

if (gfs2_is_stuffed(ip)) {
if (!page->index) {
Expand All @@ -284,8 +287,10 @@ static int gfs2_readpage(struct file *file, struct page *page)
if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
error = -EIO;

gfs2_glock_dq_m(1, &gh);
gfs2_holder_uninit(&gh);
if (file != &gfs2_internal_file_sentinal) {
gfs2_glock_dq_m(1, &gh);
gfs2_holder_uninit(&gh);
}
out:
return error;
out_unlock:
Expand Down
14 changes: 13 additions & 1 deletion fs/gfs2/ops_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ struct filldir_reg {
void *fdr_opaque;
};

/*
* Most fields left uninitialised to catch anybody who tries to
* use them. f_flags set to prevent file_accessed() from touching
* any other part of this. Its use is purely as a flag so that we
* know (in readpage()) whether or not do to locking.
*/
struct file gfs2_internal_file_sentinal = {
.f_flags = O_NOATIME|O_RDONLY,
};

static int gfs2_read_actor(read_descriptor_t *desc, struct page *page,
unsigned long offset, unsigned long size)
{
Expand Down Expand Up @@ -95,7 +105,9 @@ int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state,
desc.arg.buf = buf;
desc.count = size;
desc.error = 0;
do_generic_mapping_read(inode->i_mapping, ra_state, NULL, pos, &desc, gfs2_read_actor);
do_generic_mapping_read(inode->i_mapping, ra_state,
&gfs2_internal_file_sentinal, pos, &desc,
gfs2_read_actor);
return desc.written ? desc.written : desc.error;
}

Expand Down
2 changes: 1 addition & 1 deletion fs/gfs2/ops_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#ifndef __OPS_FILE_DOT_H__
#define __OPS_FILE_DOT_H__

extern struct file gfs2_internal_file_sentinal;
extern int gfs2_internal_read(struct gfs2_inode *ip,
struct file_ra_state *ra_state,
char *buf, loff_t *pos, unsigned size);
Expand Down

0 comments on commit 61a30dc

Please sign in to comment.