]> err.no Git - linux-2.6/commitdiff
[GFS2] Fix for lock recursion problem for internal files
authorSteven Whitehouse <swhiteho@redhat.com>
Wed, 15 Feb 2006 10:15:18 +0000 (10:15 +0000)
committerSteven Whitehouse <swhiteho@redhat.com>
Wed, 15 Feb 2006 10:15:18 +0000 (10:15 +0000)
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>
fs/gfs2/ops_address.c
fs/gfs2/ops_file.c
fs/gfs2/ops_file.h

index 74706f3527800a07f262b9e691c5c417949dadb5..39d03f3f2d541008f96799676a3095ee24342118 100644 (file)
@@ -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
@@ -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) {
@@ -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:
index bcde7a0b76f125dcee19079cd75517ead40b70eb..b86037832299834bf96a679617c36ddca2b873c8 100644 (file)
@@ -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)
 {
@@ -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;
 }
 
index 3c237bfc143da3fe370005ff6d3b9012b855dfda..192577b411f0ada74022a72e357c9c847b7f71a4 100644 (file)
@@ -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);