[Cluster-devel] GFS2: Pre-pull patch posting (fixes)

2011-05-23 Thread Steven Whitehouse
Hi,

Here are a couple of small fixes which just missed the previous pull
request. Both fairly short and self-explanatory,

Steve.



[Cluster-devel] [PATCH 1/2] GFS2: Wipe directory hash table metadata when deallocating a directory

2011-05-23 Thread Steven Whitehouse
The deallocation code for directories in GFS2 is largely divided into
two parts. The first part deallocates any directory leaf blocks and
marks the directory as being a regular file when that is complete. The
second stage was identical to deallocating regular files.

Regular files have their data blocks in a different
address space to directories, and thus what would have been normal data
blocks in a regular file (the hash table in a GFS2 directory) were
deallocated correctly. However, a reference to these blocks was left in the
journal (assuming of course that some previous activity had resulted in
those blocks being in the journal or ail list).

This patch uses the i_depth as a test of whether the inode is an
exhash directory (we cannot test the inode type as that has already
been changed to a regular file at this stage in deallocation)

The original issue was reported by Chris Hertel as an issue he encountered
running bonnie++

Reported-by: Christopher R. Hertel c...@samba.org
Cc: Abhijith Das a...@redhat.com
Signed-off-by: Steven Whitehouse swhit...@redhat.com

diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 74add2d..e65493a 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -780,6 +780,8 @@ static int do_strip(struct gfs2_inode *ip, struct 
buffer_head *dibh,
metadata = (height != ip-i_height - 1);
if (metadata)
revokes = (height) ? sdp-sd_inptrs : sdp-sd_diptrs;
+   else if (ip-i_depth)
+   revokes = sdp-sd_inptrs;
 
if (ip != GFS2_I(sdp-sd_rindex))
error = gfs2_rindex_hold(sdp, ip-i_alloc-al_ri_gh);
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 7273ad3..9b780df 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1629,6 +1629,10 @@ void __gfs2_free_data(struct gfs2_inode *ip, u64 bstart, 
u32 blen)
gfs2_rgrp_out(rgd, rgd-rd_bits[0].bi_bh-b_data);
 
gfs2_trans_add_rg(rgd);
+
+   /* Directories keep their data in the metadata address space */
+   if (ip-i_depth)
+   gfs2_meta_wipe(ip, bstart, blen);
 }
 
 /**
-- 
1.7.4



[Cluster-devel] [PATCH 2/2] GFS2: Wait properly when flushing the ail list

2011-05-23 Thread Steven Whitehouse
The ail flush code has always relied upon log flushing to prevent
it from spinning needlessly. This fixes it to wait on the last
I/O request submitted (we don't need to wait for all of it)
instead of either spinning with io_schedule or sleeping.

As a result cpu usage of gfs2_logd is much reduced with certain
workloads.

Reported-by: Abhijith Das a...@redhat.com
Tested-by: Abhijith Das a...@redhat.com
Signed-off-by: Steven Whitehouse swhit...@redhat.com

diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index cec26c0..903115f 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -228,6 +228,27 @@ static int gfs2_ail1_empty(struct gfs2_sbd *sdp)
return ret;
 }
 
+static void gfs2_ail1_wait(struct gfs2_sbd *sdp)
+{
+   struct gfs2_ail *ai;
+   struct gfs2_bufdata *bd;
+   struct buffer_head *bh;
+
+   spin_lock(sdp-sd_ail_lock);
+   list_for_each_entry_reverse(ai, sdp-sd_ail1_list, ai_list) {
+   list_for_each_entry(bd, ai-ai_ail1_list, bd_ail_st_list) {
+   bh = bd-bd_bh;
+   if (!buffer_locked(bh))
+   continue;
+   get_bh(bh);
+   spin_unlock(sdp-sd_ail_lock);
+   wait_on_buffer(bh);
+   brelse(bh);
+   return;
+   }
+   }
+   spin_unlock(sdp-sd_ail_lock);
+}
 
 /**
  * gfs2_ail2_empty_one - Check whether or not a trans in the AIL has been 
synced
@@ -878,9 +899,9 @@ void gfs2_meta_syncfs(struct gfs2_sbd *sdp)
gfs2_log_flush(sdp, NULL);
for (;;) {
gfs2_ail1_start(sdp);
+   gfs2_ail1_wait(sdp);
if (gfs2_ail1_empty(sdp))
break;
-   msleep(10);
}
 }
 
@@ -920,12 +941,14 @@ int gfs2_logd(void *data)
 
if (gfs2_ail_flush_reqd(sdp)) {
gfs2_ail1_start(sdp);
-   io_schedule();
+   gfs2_ail1_wait(sdp);
gfs2_ail1_empty(sdp);
gfs2_log_flush(sdp, NULL);
}
 
-   wake_up(sdp-sd_log_waitq);
+   if (!gfs2_ail_flush_reqd(sdp))
+   wake_up(sdp-sd_log_waitq);
+
t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
if (freezing(current))
refrigerator();
-- 
1.7.4



[Cluster-devel] GFS2: Pull request (fixes)

2011-05-23 Thread Steven Whitehouse
Hi,

These two changes just missed out on the last pull request. Please
consider pulling the following two fixes,

Steve.


-
The following changes since commit c21fd1a8c68ce3f49b00caf10337169262cfb8ad:

  Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6 (2011-05-21 
00:13:03 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes.git master

Steven Whitehouse (2):
  GFS2: Wipe directory hash table metadata when deallocating a directory
  GFS2: Wait properly when flushing the ail list

 fs/gfs2/bmap.c |2 ++
 fs/gfs2/log.c  |   29 ++---
 fs/gfs2/rgrp.c |4 
 3 files changed, 32 insertions(+), 3 deletions(-)




[Cluster-devel] dlm_controld: clear waiting plocks for closed files

2011-05-23 Thread David Teigland
The new CLOSE flag is set in unlock operations that are
generated by the vfs removing locks that were not unlocked
by the process, when the process closes the file or exits.

The kernel does not take a reply for these unlock-close
operations.

plock requests can now be interrupted in the kernel when the
process is killed.  So the unlock-close also needs to clear
any waiting plocks that were abandoned by the killed process.

The corresponding kernel patch:
https://lkml.org/lkml/2011/5/23/237

Signed-off-by: David Teigland teigl...@redhat.com
---
 group/dlm_controld/plock.c |   28 
 1 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/group/dlm_controld/plock.c b/group/dlm_controld/plock.c
index f27001f..6d5dea8 100644
--- a/group/dlm_controld/plock.c
+++ b/group/dlm_controld/plock.c
@@ -631,6 +631,27 @@ static int unlock_internal(struct lockspace *ls, struct 
resource *r,
return rv;
 }
 
+static void clear_waiters(struct lockspace *ls, struct resource *r,
+ struct dlm_plock_info *in)
+{
+   struct lock_waiter *w, *safe;
+
+   list_for_each_entry_safe(w, safe, r-waiters, list) {
+   if (w-info.nodeid != in-nodeid || w-info.owner != in-owner)
+   continue;
+
+   list_del(w-list);
+
+   log_plock_error(ls, clear waiter %llx %llx-%llx %d/%u/%llx,
+   (unsigned long long)in-number,
+   (unsigned long long)in-start,
+   (unsigned long long)in-end,
+   in-nodeid, in-pid,
+   (unsigned long long)in-owner);
+   free(w);
+   }
+}
+
 static int add_waiter(struct lockspace *ls, struct resource *r,
  struct dlm_plock_info *in)
 
@@ -716,9 +737,16 @@ static void do_unlock(struct lockspace *ls, struct 
dlm_plock_info *in,
 
rv = unlock_internal(ls, r, in);
 
+   if (in-flags  DLM_PLOCK_FL_CLOSE) {
+   clear_waiters(ls, r, in);
+   /* no replies for unlock-close ops */
+   goto skip_result;
+   }
+
if (in-nodeid == our_nodeid)
write_result(ls, in, rv);
 
+ skip_result:
do_waiters(ls, r);
put_resource(r);
 }
-- 
1.7.1.1