aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-02-15 05:15:18 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2006-02-15 05:15:18 -0500
commit61a30dcb5866eb7e92796b2988ddb4c94b9f78ac (patch)
treeaa27ef185437a813041aae3e9f0aa403a960db43
parent4dd651adbb4898d3200426c197b26c99d2209d8d (diff)
[GFS2] Fix for lock recursion problem for internal files
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>
-rw-r--r--fs/gfs2/ops_address.c17
-rw-r--r--fs/gfs2/ops_file.c14
-rw-r--r--fs/gfs2/ops_file.h2
3 files changed, 25 insertions, 8 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 74706f352780..39d03f3f2d54 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -28,6 +28,7 @@
28#include "quota.h" 28#include "quota.h"
29#include "trans.h" 29#include "trans.h"
30#include "rgrp.h" 30#include "rgrp.h"
31#include "ops_file.h"
31 32
32/** 33/**
33 * gfs2_get_block - Fills in a buffer head with details about a block 34 * gfs2_get_block - Fills in a buffer head with details about a block
@@ -267,10 +268,12 @@ static int gfs2_readpage(struct file *file, struct page *page)
267 268
268 atomic_inc(&sdp->sd_ops_address); 269 atomic_inc(&sdp->sd_ops_address);
269 270
270 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); 271 if (file != &gfs2_internal_file_sentinal) {
271 error = gfs2_glock_nq_m_atime(1, &gh); 272 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
272 if (error) 273 error = gfs2_glock_nq_m_atime(1, &gh);
273 goto out_unlock; 274 if (error)
275 goto out_unlock;
276 }
274 277
275 if (gfs2_is_stuffed(ip)) { 278 if (gfs2_is_stuffed(ip)) {
276 if (!page->index) { 279 if (!page->index) {
@@ -284,8 +287,10 @@ static int gfs2_readpage(struct file *file, struct page *page)
284 if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) 287 if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
285 error = -EIO; 288 error = -EIO;
286 289
287 gfs2_glock_dq_m(1, &gh); 290 if (file != &gfs2_internal_file_sentinal) {
288 gfs2_holder_uninit(&gh); 291 gfs2_glock_dq_m(1, &gh);
292 gfs2_holder_uninit(&gh);
293 }
289out: 294out:
290 return error; 295 return error;
291out_unlock: 296out_unlock:
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index bcde7a0b76f1..b86037832299 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -67,6 +67,16 @@ struct filldir_reg {
67 void *fdr_opaque; 67 void *fdr_opaque;
68}; 68};
69 69
70/*
71 * Most fields left uninitialised to catch anybody who tries to
72 * use them. f_flags set to prevent file_accessed() from touching
73 * any other part of this. Its use is purely as a flag so that we
74 * know (in readpage()) whether or not do to locking.
75 */
76struct file gfs2_internal_file_sentinal = {
77 .f_flags = O_NOATIME|O_RDONLY,
78};
79
70static int gfs2_read_actor(read_descriptor_t *desc, struct page *page, 80static int gfs2_read_actor(read_descriptor_t *desc, struct page *page,
71 unsigned long offset, unsigned long size) 81 unsigned long offset, unsigned long size)
72{ 82{
@@ -95,7 +105,9 @@ int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state,
95 desc.arg.buf = buf; 105 desc.arg.buf = buf;
96 desc.count = size; 106 desc.count = size;
97 desc.error = 0; 107 desc.error = 0;
98 do_generic_mapping_read(inode->i_mapping, ra_state, NULL, pos, &desc, gfs2_read_actor); 108 do_generic_mapping_read(inode->i_mapping, ra_state,
109 &gfs2_internal_file_sentinal, pos, &desc,
110 gfs2_read_actor);
99 return desc.written ? desc.written : desc.error; 111 return desc.written ? desc.written : desc.error;
100} 112}
101 113
diff --git a/fs/gfs2/ops_file.h b/fs/gfs2/ops_file.h
index 3c237bfc143d..192577b411f0 100644
--- a/fs/gfs2/ops_file.h
+++ b/fs/gfs2/ops_file.h
@@ -9,7 +9,7 @@
9 9
10#ifndef __OPS_FILE_DOT_H__ 10#ifndef __OPS_FILE_DOT_H__
11#define __OPS_FILE_DOT_H__ 11#define __OPS_FILE_DOT_H__
12 12extern struct file gfs2_internal_file_sentinal;
13extern int gfs2_internal_read(struct gfs2_inode *ip, 13extern int gfs2_internal_read(struct gfs2_inode *ip,
14 struct file_ra_state *ra_state, 14 struct file_ra_state *ra_state,
15 char *buf, loff_t *pos, unsigned size); 15 char *buf, loff_t *pos, unsigned size);