<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/">
  <channel rdf:about="http://blog.gmane.org/gmane.comp.file-systems.ocfs2.devel">
    <title>gmane.comp.file-systems.ocfs2.devel</title>
    <link>http://blog.gmane.org/gmane.comp.file-systems.ocfs2.devel</link>
    <description/>
    <syn:updatePeriod>hourly</syn:updatePeriod>
    <syn:updateFrequency>1</syn:updateFrequency>
    <syn:updateBase>1901-01-01T00:00+00:00</syn:updateBase>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7853"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7852"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7851"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7850"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7849"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7848"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7847"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7846"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7845"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7844"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7843"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7841"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7840"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7839"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7838"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7837"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7836"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7825"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7824"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7822"/>
      </rdf:Seq>
    </items>
    <image rdf:resource="http://gmane.org/img/gmane-25t.png"/>
    <textinput rdf:resource=""/>
  </channel>
  <image rdf:about="http://gmane.org/img/gmane-25t.png">
    <title>Gmane</title>
    <url>http://gmane.org/img/gmane-25t.png</url>
    <link>http://gmane.org</link>
  </image>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7853">
    <title>Re: [PATCH 2/3] ocfs2: implement discontiguouslocalalloc bitmap</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7853</link>
    <description>&lt;pre&gt;Please please don't hate me :( ... the changes takes care of old formats 
as well ...  I used the reserved space in the structure so that the code 
changes will be minimal and still compatible with old file system 
formats. I agree that we need to have some reserved space still 
available. So as discussed I'll redo the changes accordingly. Please 
ignore all the patches.

Thanks,
--Srini
&lt;/pre&gt;</description>
    <dc:creator>Srinivas Eeda</dc:creator>
    <dc:date>2012-05-08T02:10:32</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7852">
    <title>Re: ocfs2 discontiguous localalloc patches</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7852</link>
    <description>&lt;pre&gt;Hi Joel,

thanks a lot for the quick reply.

I have some stat_sysdir.sh snapshots at 
http://oss.oracle.com/~seeda/diag/stat_sysdir/ collected from a system. 
It has 4 snapshots collected when the file system usage is at 8%, 19%, 
21% and 52%.

In file stat_sysdir_52_percent_usage_slow_del.out, for the filesystem 
that has UUID: 3A6F54DF288C4AF2ABD1E00FC49BE7ED you could see that 
local_alloc:0000 bitmap total is 38 and is 0(disabled) for 
local_alloc:0001, and local_alloc:0002. for the filesystem that has uuid 
AC444DB162AE427C899BA89E076DD479, all localalloc appears to be disabled. 
Sorry I didn't collect /sys/kernel/debug/fs/&amp;lt;uuid&amp;gt;/fs_state. But, given 
the file system state, even if localalloc is not disabled localalloc 
need to be refilled every 40 clusters.

Thanks,
--Srini
&lt;/pre&gt;</description>
    <dc:creator>Srinivas Eeda</dc:creator>
    <dc:date>2012-05-08T01:26:58</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7851">
    <title>Re: [PATCH 3/3] ocfs2: modify reservation code to support discontigous localalloc</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7851</link>
    <description>&lt;pre&gt;
Hi Srini,
A patch like this should come before the feature patch.  Once
this code can treat the old single-range bitmap as a one-element
multiple-range bitmap, you can add the multiple-range change easily.


I don't see this function called anywhere.  And please don't use
needless abbreviations.  If you want to say ocfs2_resmap_set_extent(),
write it out.  I don't quite get the arguments, and since it isn't
called, I can't figure out how they are used.

Joel

&lt;/pre&gt;</description>
    <dc:creator>Joel Becker</dc:creator>
    <dc:date>2012-05-08T00:34:31</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7850">
    <title>Re: [PATCH 1/3] ocfs2: new structure to implment discontiguous local alloc bitmap</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7850</link>
    <description>&lt;pre&gt;
Another point.  Not only does this macro not handle
!DISCONTIG_LA filesystems (as described in my other email about this
patch), it should be a static inline function.  See eg: INODE_CACHE() in
fs/ocfs2/inode.h

Joel

&lt;/pre&gt;</description>
    <dc:creator>Joel Becker</dc:creator>
    <dc:date>2012-05-08T00:28:23</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7849">
    <title>Re: [PATCH 2/3] ocfs2: implement discontiguouslocalalloc bitmap</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7849</link>
    <description>&lt;pre&gt;
I noted that you moved local_alloc_inode into ocfs2_super in the
previous patch.  Lifting that into the super should be one distinct
patch.  It should add the field to ocfs2_super and change the function
signatures at the same time.  Munging it with other patches confuses the
issue.
 

This can't work for non-DISCONTIG_LA filesystems.  I looked, and
you call this regardless of the feature bits.  Old filesystems will
crash, because they have bitmap bits instead of la_rec_count.  This is
why I said you couldn't remove la_bitmap.


Again, no check for DISCONTIG_LA.  I'm going to stop mentioning
this.  Just assume that every place you want to touch la_rec_count, you
need to make sure you have a DISCONTIG_LA filesystem.


I lied.  You can't trust la_rec_count for non-DISCONTIG_LA
filesystems, so you can't have a naked check here.  Conversely,
la_bm_off is the valid check for those filesystems.  You need to
alternate based on the feature.


This is what I mean about osb-&amp;gt;local_alloc_inode.  There should
be a first patch that does these changes only.


I'm not sure about this.  Do you have a reason?


Here is the call that assumes a DISCONTIG_LA filesystem.


OH MY DOG NO.  NEVER EVER DO THIS.  You cannot update an old
filesystem on the fly!  What about other nodes that are running older
versions of the software?  They will crash or corrupt data!  The entire
point of feature bits is to make sure all nodes are speaking the same
code.

NAK NAK NAK

This explains why you trusted la_rec_count earlier.  But that is
broken.  When your patches are done, the code should use la_bm_off and
la_bitmap when !DISCONTIG_LA and then use la_rec_count, etc when
DISCONTIG_LA.  The only way to transition between them is a tunefs.ocfs2
operation that walks the filesystem, flushes the bitmap, and then
sets/clears la_rec_count appropriately depending on the direction..

Joel

&lt;/pre&gt;</description>
    <dc:creator>Joel Becker</dc:creator>
    <dc:date>2012-05-08T00:22:58</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7848">
    <title>Re: [PATCH 1/3] ocfs2: new structure to implment discontiguous local alloc bitmap</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7848</link>
    <description>&lt;pre&gt;
I really wish this could be an RO_COMPAT flag, but I think that
recovery on RO mounts will break with this.  Mark, please confirm, but I
think it has to be INCOMPAT.


You can't delete la_bitmap.  Any filesystem without DISCONTIG_LA
will be expecting the inline bitmap to start there.


You can't do this without checking for DISCONTIG_LA.  Again,
filesystems without DISCONTIG_LA will be starting at la_bitmap.

Joel


&lt;/pre&gt;</description>
    <dc:creator>Joel Becker</dc:creator>
    <dc:date>2012-05-08T00:05:33</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7847">
    <title>Re: ocfs2 discontiguous localalloc patches</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7847</link>
    <description>&lt;pre&gt;
Hi Srini.  Have you some performance numbers backing this?  That
is, I believe that the described filesystem turned off local alloc.  Do
you have proof that these patches, turning it back on, improved the
customer's performance?

Joel

&lt;/pre&gt;</description>
    <dc:creator>Joel Becker</dc:creator>
    <dc:date>2012-05-08T00:01:01</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7846">
    <title>ocfs2 discontiguous localalloc patches</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7846</link>
    <description>&lt;pre&gt;Hi all,

can you please review following 3 patches that implement discontiguous
localalloc bitmap support for ocfs2 file system. This feature helps
applications that significantly fragment the filesystem.

These fixes needs changes to ocfs2 tools as well. I am sending those patches
for review separately.

A write up on this feature is available at
http://oss.oracle.com/osswiki/OCFS2/DesignDocs/DiscontiguousLocalAlloc.html

Thanks,
--Srini
&lt;/pre&gt;</description>
    <dc:creator>Srinivas Eeda</dc:creator>
    <dc:date>2012-05-07T23:21:27</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7845">
    <title>[PATCH 2/3] ocfs2: implement discontiguous localallocbitmap</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7845</link>
    <description>&lt;pre&gt;This patch adds supporting functions and modifies localalloc code to implement
discontiguous localalloc bitmap.

Signed-off-by: Srinivas Eeda &amp;lt;srinivas.eeda&amp;lt; at &amp;gt;oracle.com&amp;gt;
---
 fs/ocfs2/localalloc.c |  523 ++++++++++++++++++++++++++++++++-----------------
 1 files changed, 342 insertions(+), 181 deletions(-)

diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
index 4190e53..f63381e 100644
--- a/fs/ocfs2/localalloc.c
+++ b/fs/ocfs2/localalloc.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -48,6 +48,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 
 #define OCFS2_LOCAL_ALLOC(dinode)(&amp;amp;((dinode)-&amp;gt;id2.i_lab))
 
+/* defines minimum contiguous required */
+#define OCFS2_LOCAL_ALLOC_MIN_BITS2
+
 #define OCFS2_LOCAL_ALLOC_REC_SZ(la)(le16_to_cpu(la-&amp;gt;la_rec_count) *\
  sizeof(struct ocfs2_local_alloc_rec))
 #define OCFS2_LOCAL_ALLOC_BITMAP(la)    ((char *)(&amp;amp;(la-&amp;gt;la_recs)) +\
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -58,7 +61,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 #define OCFS2_MAX_LOCAL_ALLOC_REC_LIMIT128
 
 
-static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc);
+static u32 ocfs2_local_alloc_count_bits(struct ocfs2_super *osb,
+struct ocfs2_dinode *alloc);
 
 static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
      struct ocfs2_dinode *alloc,
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -82,8 +86,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
 handle_t *handle,
 struct ocfs2_alloc_context *ac);
 
-static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
-  struct inode *local_alloc_inode);
+static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb);
 
 /*
  * ocfs2_la_default_mb() - determine a default size, in megabytes of
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -202,6 +205,74 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; unsigned int ocfs2_la_default_mb(struct ocfs2_super *osb)
 return la_mb;
 }
 
+static u32 ocfs2_local_bitmap_to_cluster(struct ocfs2_local_alloc *la, u32 bit)
+{
+u32 start, prev, offset;
+int rec;
+
+rec = start = prev = 0;
+for (rec = 0; rec &amp;lt; le16_to_cpu(la-&amp;gt;la_rec_count); rec++) {
+prev = start;
+start += le32_to_cpu(la-&amp;gt;la_recs[rec].la_clusters);
+if (bit &amp;lt; start)
+break;
+}
+offset = le32_to_cpu(la-&amp;gt;la_recs[rec].la_start) + (bit - prev);
+
+return offset;
+}
+
+/*
+ * This function is called before allocating a new chunk for the localalloc
+ * bitmap to make sure there is enough space in the bitmap for the new record
+ */
+static u32 ocfs2_local_alloc_adjust_bits_wanted(struct ocfs2_local_alloc *la,
+struct ocfs2_alloc_context *ac)
+{
+u32 required, available, cluster_cnt;
+
+if (ac-&amp;gt;ac_bits_given == ac-&amp;gt;ac_bits_wanted)
+return 0;
+
+/* total bits available in bitmap */
+available   = le16_to_cpu(la-&amp;gt;la_size) &amp;lt;&amp;lt; 3;
+cluster_cnt = ocfs2_local_alloc_cluster_count(la);
+
+/*
+ * Wanted shouldn't be greater than bitmap size and given should be
+ * equal to cluster count
+ */
+BUG_ON(ac-&amp;gt;ac_bits_given &amp;gt; ac-&amp;gt;ac_bits_wanted);
+BUG_ON(ac-&amp;gt;ac_bits_wanted &amp;gt; available);
+BUG_ON(ac-&amp;gt;ac_bits_given != cluster_cnt);
+
+/* reduce bits taken by each record structure */
+available -= (le16_to_cpu(la-&amp;gt;la_rec_count) *
+      OCFS2_LOCAL_ALLOC_BITS_PER_REC);
+
+/* reduce space reserved for bitmap for already allocated clusters */
+available -= cluster_cnt;
+
+/* if available bits are not enough to fit a new record return 0 */
+if (available &amp;lt; (OCFS2_LOCAL_ALLOC_BITS_PER_REC + 1))
+return 0;
+
+/* Adjust space that will be consumed by new record structure */
+available -= OCFS2_LOCAL_ALLOC_BITS_PER_REC;
+
+required = ac-&amp;gt;ac_bits_wanted - ac-&amp;gt;ac_bits_given;
+
+/*
+ * we can't allocate clusters more than the bits available. Adjust
+ * bits wanted
+ */
+if (required &amp;gt; available) {
+ac-&amp;gt;ac_bits_wanted = ac-&amp;gt;ac_bits_given + available;
+return available;
+} else
+return required;
+}
+
 void ocfs2_la_set_sizes(struct ocfs2_super *osb, int requested_mb)
 {
 struct super_block *sb = osb-&amp;gt;sb;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -239,12 +310,14 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void ocfs2_local_alloc_seen_free_bits(struct ocfs2_super *osb,
       unsigned int num_clusters)
 {
 spin_lock(&amp;amp;osb-&amp;gt;osb_lock);
-if (osb-&amp;gt;local_alloc_state == OCFS2_LA_DISABLED ||
-    osb-&amp;gt;local_alloc_state == OCFS2_LA_THROTTLED)
-if (num_clusters &amp;gt;= osb-&amp;gt;local_alloc_default_bits) {
-cancel_delayed_work(&amp;amp;osb-&amp;gt;la_enable_wq);
+if (osb-&amp;gt;local_alloc_state == OCFS2_LA_DISABLED) {
+cancel_delayed_work(&amp;amp;osb-&amp;gt;la_enable_wq);
+if (num_clusters &amp;gt;= osb-&amp;gt;local_alloc_bits)
+osb-&amp;gt;local_alloc_state = OCFS2_LA_THROTTLED;
+
+if (num_clusters &amp;gt;= osb-&amp;gt;local_alloc_default_bits)
 osb-&amp;gt;local_alloc_state = OCFS2_LA_ENABLED;
-}
+}
 spin_unlock(&amp;amp;osb-&amp;gt;osb_lock);
 }
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -280,7 +353,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ocfs2_alloc_should_use_local(struct ocfs2_super *osb, u64 bits)
  * a new block group. We want to be sure block group
  * allocations go through the local alloc, so allow an
  * allocation to take up to half the bitmap. */
-if (bits &amp;gt; (la_bits / 2))
+if ((la_bits &amp;gt; OCFS2_LOCAL_ALLOC_MIN_BITS) &amp;amp;&amp;amp; (bits &amp;gt; (la_bits / 2)))
 goto bail;
 
 ret = 1;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -348,21 +421,21 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ocfs2_load_local_alloc(struct ocfs2_super *osb)
 }
 
 /* do a little verification. */
-num_used = ocfs2_local_alloc_count_bits(alloc);
+num_used = ocfs2_local_alloc_count_bits(osb, alloc);
 
 /* hopefully the local alloc has always been recovered before
  * we load it. */
 if (num_used
     || alloc-&amp;gt;id1.bitmap1.i_used
     || alloc-&amp;gt;id1.bitmap1.i_total
-    || la-&amp;gt;la_bm_off)
+    || la-&amp;gt;la_rec_count)
 mlog(ML_ERROR, "Local alloc hasn't been recovered!\n"
-     "found = %u, set = %u, taken = %u, off = %u\n",
+     "found = %u, set = %u, taken = %u\n",
      num_used, le32_to_cpu(alloc-&amp;gt;id1.bitmap1.i_used),
-     le32_to_cpu(alloc-&amp;gt;id1.bitmap1.i_total),
-     OCFS2_LOCAL_ALLOC(alloc)-&amp;gt;la_bm_off);
+     le32_to_cpu(alloc-&amp;gt;id1.bitmap1.i_total));
 
-osb-&amp;gt;local_alloc_bh = alloc_bh;
+osb-&amp;gt;local_alloc_bh    = alloc_bh;
+osb-&amp;gt;local_alloc_inode = inode;
 osb-&amp;gt;local_alloc_state = OCFS2_LA_ENABLED;
 
 bail:
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -389,7 +462,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
 {
 int status;
 handle_t *handle;
-struct inode *local_alloc_inode = NULL;
 struct buffer_head *bh = NULL;
 struct buffer_head *main_bm_bh = NULL;
 struct inode *main_bm_inode = NULL;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -402,16 +474,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
 if (osb-&amp;gt;local_alloc_state == OCFS2_LA_UNUSED)
 goto out;
 
-local_alloc_inode =
-ocfs2_get_system_file_inode(osb,
-    LOCAL_ALLOC_SYSTEM_INODE,
-    osb-&amp;gt;slot_num);
-if (!local_alloc_inode) {
-status = -ENOENT;
-mlog_errno(status);
-goto out;
-}
-
 osb-&amp;gt;local_alloc_state = OCFS2_LA_DISABLED;
 
 ocfs2_resmap_uninit(&amp;amp;osb-&amp;gt;osb_la_resmap);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -451,13 +513,19 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
 }
 memcpy(alloc_copy, alloc, bh-&amp;gt;b_size);
 
-status = ocfs2_journal_access_di(handle, INODE_CACHE(local_alloc_inode),
+status = ocfs2_journal_access_di(handle,
+ INODE_CACHE(osb-&amp;gt;local_alloc_inode),
  bh, OCFS2_JOURNAL_ACCESS_WRITE);
 if (status &amp;lt; 0) {
 mlog_errno(status);
 goto out_commit;
 }
 
+status = ocfs2_sync_local_to_main(osb, handle, alloc_copy,
+  main_bm_inode, main_bm_bh);
+if (status &amp;lt; 0)
+mlog_errno(status);
+
 ocfs2_clear_local_alloc(alloc);
 ocfs2_journal_dirty(handle, bh);
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -465,11 +533,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
 osb-&amp;gt;local_alloc_bh = NULL;
 osb-&amp;gt;local_alloc_state = OCFS2_LA_UNUSED;
 
-status = ocfs2_sync_local_to_main(osb, handle, alloc_copy,
-  main_bm_inode, main_bm_bh);
-if (status &amp;lt; 0)
-mlog_errno(status);
-
 out_commit:
 ocfs2_commit_trans(osb, handle);
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -483,9 +546,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; out_mutex:
 iput(main_bm_inode);
 
 out:
-if (local_alloc_inode)
-iput(local_alloc_inode);
-
 if (alloc_copy)
 kfree(alloc_copy);
 }
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -641,22 +701,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
 {
 int status;
 struct ocfs2_dinode *alloc;
-struct inode *local_alloc_inode;
 unsigned int free_bits;
 
 BUG_ON(!ac);
 
-local_alloc_inode =
-ocfs2_get_system_file_inode(osb,
-    LOCAL_ALLOC_SYSTEM_INODE,
-    osb-&amp;gt;slot_num);
-if (!local_alloc_inode) {
-status = -ENOENT;
-mlog_errno(status);
-goto bail;
-}
-
-mutex_lock(&amp;amp;local_alloc_inode-&amp;gt;i_mutex);
+mutex_lock(&amp;amp;osb-&amp;gt;local_alloc_inode-&amp;gt;i_mutex);
 
 /*
  * We must double check state and allocator bits because
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -675,12 +724,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
 
 #ifdef CONFIG_OCFS2_DEBUG_FS
 if (le32_to_cpu(alloc-&amp;gt;id1.bitmap1.i_used) !=
-    ocfs2_local_alloc_count_bits(alloc)) {
+    ocfs2_local_alloc_count_bits(osb, alloc)) {
 ocfs2_error(osb-&amp;gt;sb, "local alloc inode %llu says it has "
     "%u free bits, but a count shows %u",
     (unsigned long long)le64_to_cpu(alloc-&amp;gt;i_blkno),
     le32_to_cpu(alloc-&amp;gt;id1.bitmap1.i_used),
-    ocfs2_local_alloc_count_bits(alloc));
+    ocfs2_local_alloc_count_bits(osb, alloc));
 status = -EIO;
 goto bail;
 }
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -690,8 +739,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
 le32_to_cpu(alloc-&amp;gt;id1.bitmap1.i_used);
 if (bits_wanted &amp;gt; free_bits) {
 /* uhoh, window change time. */
-status =
-ocfs2_local_alloc_slide_window(osb, local_alloc_inode);
+status = ocfs2_local_alloc_slide_window(osb);
 if (status &amp;lt; 0) {
 if (status != -ENOSPC)
 mlog_errno(status);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -714,7 +762,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
 goto bail;
 }
 
-ac-&amp;gt;ac_inode = local_alloc_inode;
+ac-&amp;gt;ac_inode = osb-&amp;gt;local_alloc_inode;
 /* We should never use localalloc from another slot */
 ac-&amp;gt;ac_alloc_slot = osb-&amp;gt;slot_num;
 ac-&amp;gt;ac_which = OCFS2_AC_USE_LOCAL;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -722,9 +770,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
 ac-&amp;gt;ac_bh = osb-&amp;gt;local_alloc_bh;
 status = 0;
 bail:
-if (status &amp;lt; 0 &amp;amp;&amp;amp; local_alloc_inode) {
-mutex_unlock(&amp;amp;local_alloc_inode-&amp;gt;i_mutex);
-iput(local_alloc_inode);
+if (status &amp;lt; 0 &amp;amp;&amp;amp; osb-&amp;gt;local_alloc_inode) {
+mutex_unlock(&amp;amp;osb-&amp;gt;local_alloc_inode-&amp;gt;i_mutex);
 }
 
 trace_ocfs2_reserve_local_alloc_bits(
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -745,7 +792,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
 {
 int status, start;
 struct inode *local_alloc_inode;
-void *bitmap;
+u8 *bitmap;
 struct ocfs2_dinode *alloc;
 struct ocfs2_local_alloc *la;
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -764,8 +811,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
 goto bail;
 }
 
-bitmap = la-&amp;gt;la_bitmap;
-*bit_off = le32_to_cpu(la-&amp;gt;la_bm_off) + start;
+bitmap = OCFS2_LOCAL_ALLOC_BITMAP(la);
+*bit_off = ocfs2_local_bitmap_to_cluster(la, start);
 *num_bits = bits_wanted;
 
 status = ocfs2_journal_access_di(handle,
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -792,16 +839,29 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; bail:
 return status;
 }
 
-static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc)
+static u32 ocfs2_local_alloc_count_bits(struct ocfs2_super *osb,
+struct ocfs2_dinode *alloc)
 {
 int i;
-u8 *buffer;
+u8 *bitmap;
 u32 count = 0;
 struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc);
 
-buffer = la-&amp;gt;la_bitmap;
-for (i = 0; i &amp;lt; le16_to_cpu(la-&amp;gt;la_size); i++)
-count += hweight8(buffer[i]);
+/*
+ * if discontig is not enabled then lets update the first localalloc
+ * record with the current bitmap block info. We are doing this because
+ * old disk formats are not aware of the records.
+ */
+if (!ocfs2_supports_discontig_la(osb) &amp;amp;&amp;amp; la-&amp;gt;la_bm_off) {
+la-&amp;gt;la_rec_count = cpu_to_le16(1);
+la-&amp;gt;la_recs[0].la_start = la-&amp;gt;la_bm_off;
+la-&amp;gt;la_recs[0].la_clusters = alloc-&amp;gt;id1.bitmap1.i_total;
+}
+
+bitmap = OCFS2_LOCAL_ALLOC_BITMAP(la);
+for (i = 0; i &amp;lt; le32_to_cpu(alloc-&amp;gt;id1.bitmap1.i_total); i++)
+if (ocfs2_test_bit(i, bitmap))
+count++;
 
 trace_ocfs2_local_alloc_count_bits(count);
 return count;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -812,10 +872,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
      u32 *numbits,
      struct ocfs2_alloc_reservation *resv)
 {
-int numfound, bitoff, left, startoff, lastzero;
-int local_resv = 0;
+int numfound, bitoff, left, startoff;
+int i, local_resv = 0;
 struct ocfs2_alloc_reservation r;
-void *bitmap = NULL;
+struct ocfs2_local_alloc *la;
+u8 *bitmap = NULL;
 struct ocfs2_reservation_map *resmap = &amp;amp;osb-&amp;gt;osb_la_resmap;
 
 if (!alloc-&amp;gt;id1.bitmap1.i_total) {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -847,37 +908,44 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
  * Reservations are disabled. Handle this the old way.
  */
 
-bitmap = OCFS2_LOCAL_ALLOC(alloc)-&amp;gt;la_bitmap;
+la     = OCFS2_LOCAL_ALLOC(alloc);
+bitmap = OCFS2_LOCAL_ALLOC_BITMAP(la);
 
-numfound = bitoff = startoff = 0;
-lastzero = -1;
-left = le32_to_cpu(alloc-&amp;gt;id1.bitmap1.i_total);
-while ((bitoff = ocfs2_find_next_zero_bit(bitmap, left, startoff)) != -1) {
-if (bitoff == left) {
-/* mlog(0, "bitoff (%d) == left", bitoff); */
-break;
-}
-/* mlog(0, "Found a zero: bitoff = %d, startoff = %d, "
-   "numfound = %d\n", bitoff, startoff, numfound);*/
-
-/* Ok, we found a zero bit... is it contig. or do we
- * start over?*/
-if (bitoff == startoff) {
-/* we found a zero */
-numfound++;
-startoff++;
-} else {
-/* got a zero after some ones */
-numfound = 1;
-startoff = bitoff+1;
-}
-/* we got everything we needed */
-if (numfound == *numbits) {
-/* mlog(0, "Found it all!\n"); */
-break;
+left = numfound = bitoff = startoff = 0;
+for (i = 0; i &amp;lt; le16_to_cpu(la-&amp;gt;la_rec_count); i++) {
+
+numfound  = 0;
+startoff += left;
+left      = le32_to_cpu(la-&amp;gt;la_recs[i].la_clusters);
+
+while ((bitoff = ocfs2_find_next_zero_bit(bitmap, left,
+  startoff)) != -1) {
+if (bitoff == left) {
+/* mlog(0, "bitoff (%d) == left", bitoff); */
+break;
+}
+/* mlog(0, "Found a zero: bitoff = %d, startoff = %d, "
+ * "numfound = %d\n", bitoff, startoff, numfound);*/
+
+/* Ok, we found a zero bit... is it contig. or do we
+ * start over?*/
+if (bitoff == startoff) {
+/* we found a zero */
+numfound++;
+startoff++;
+} else {
+/* got a zero after some ones */
+numfound = 1;
+startoff = bitoff+1;
+}
+/* we got everything we needed */
+if (numfound == *numbits) {
+/* mlog(0, "Found it all!\n"); */
+goto out;
+}
 }
 }
-
+out:
 trace_ocfs2_local_alloc_find_clear_bits_search_bitmap(bitoff, numfound);
 
 if (numfound == *numbits)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -900,12 +968,18 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc)
 {
 struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc);
 int i;
+u8 *bitmap;
 
 alloc-&amp;gt;id1.bitmap1.i_total = 0;
 alloc-&amp;gt;id1.bitmap1.i_used = 0;
+la-&amp;gt;la_rec_count = 0;
 la-&amp;gt;la_bm_off = 0;
+
+/* We reset the rec count so following will clear records as well */
+bitmap = OCFS2_LOCAL_ALLOC_BITMAP(la);
+bitmap += sizeof(struct ocfs2_local_alloc);
 for(i = 0; i &amp;lt; le16_to_cpu(la-&amp;gt;la_size); i++)
-la-&amp;gt;la_bitmap[i] = 0;
+bitmap[i] = 0;
 }
 
 #if 0
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -933,17 +1007,64 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void ocfs2_verify_zero_bits(unsigned long *bitmap,
  * assumes you've already locked the main bitmap -- the bitmap inode
  * passed is used for caching.
  */
+static int ocfs2_sync_local_rec_to_main(struct ocfs2_super *osb,
+handle_t *handle,
+struct ocfs2_dinode *alloc,
+struct inode *main_bm_inode,
+struct buffer_head *main_bm_bh,
+u8 *bitmap, u64 la_start_blk,
+int start, int left)
+{
+int bit_off = 0, status = 0, prev, count;
+u64 blkno;
+
+prev = start;
+count = 0;
+while ((bit_off = ocfs2_find_next_zero_bit(bitmap, left,
+   start)) != -1) {
+if ((bit_off &amp;lt; left) &amp;amp;&amp;amp; (bit_off == start)) {
+count++;
+start++;
+continue;
+}
+if (count) {
+blkno = la_start_blk +
+ocfs2_clusters_to_blocks(osb-&amp;gt;sb,
+ (start - prev) - count);
+mlog(0, "\nfreeing %u bits starting at local "
+     "alloc bit %u (la_start_blk = %llu, "
+     "blkno = %llu)\n",
+     count, ((start - prev) - count),
+     (unsigned long long)la_start_blk,
+     (unsigned long long)blkno);
+status = ocfs2_release_clusters(handle, main_bm_inode,
+main_bm_bh, blkno,
+count);
+if (status &amp;lt; 0) {
+mlog_errno(status);
+goto bail;
+}
+}
+if (bit_off &amp;gt;= left)
+break;
+count = 1;
+start = bit_off + 1;
+}
+bail:
+return status;
+}
+
 static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
     handle_t *handle,
     struct ocfs2_dinode *alloc,
     struct inode *main_bm_inode,
     struct buffer_head *main_bm_bh)
 {
-int status = 0;
-int bit_off, left, count, start;
+int i, status = 0;
+int total, start, rec_cnt, credits;
+u32 clusters;
 u64 la_start_blk;
-u64 blkno;
-void *bitmap;
+u8 *bitmap;
 struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc);
 
 trace_ocfs2_sync_local_to_main(
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -954,49 +1075,58 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
 goto bail;
 }
 
+/* if all bits are used nothing to sync, just return */
 if (le32_to_cpu(alloc-&amp;gt;id1.bitmap1.i_used) ==
     le32_to_cpu(alloc-&amp;gt;id1.bitmap1.i_total)) {
 goto bail;
 }
 
-la_start_blk = ocfs2_clusters_to_blocks(osb-&amp;gt;sb,
-le32_to_cpu(la-&amp;gt;la_bm_off));
-bitmap = la-&amp;gt;la_bitmap;
-start = count = bit_off = 0;
-left = le32_to_cpu(alloc-&amp;gt;id1.bitmap1.i_total);
+bitmap  = OCFS2_LOCAL_ALLOC_BITMAP(la);
+rec_cnt = le16_to_cpu(la-&amp;gt;la_rec_count) - 1;
 
-while ((bit_off = ocfs2_find_next_zero_bit(bitmap, left, start))
-       != -1) {
-if ((bit_off &amp;lt; left) &amp;amp;&amp;amp; (bit_off == start)) {
-count++;
-start++;
-continue;
-}
-if (count) {
-blkno = la_start_blk +
-ocfs2_clusters_to_blocks(osb-&amp;gt;sb,
- start - count);
+for (i = rec_cnt; i &amp;gt;= 0 ; i--) {
+la_start_blk = ocfs2_clusters_to_blocks(osb-&amp;gt;sb,
+le32_to_cpu(la-&amp;gt;la_recs[i].la_start));
 
-trace_ocfs2_sync_local_to_main_free(
-     count, start - count,
-     (unsigned long long)la_start_blk,
-     (unsigned long long)blkno);
+total    = le32_to_cpu(alloc-&amp;gt;id1.bitmap1.i_total);
+clusters = le32_to_cpu(la-&amp;gt;la_recs[i].la_clusters);
+start    = total - clusters;
 
-status = ocfs2_release_clusters(handle,
-main_bm_inode,
-main_bm_bh, blkno,
-count);
+status = ocfs2_sync_local_rec_to_main(osb, handle, alloc,
+      main_bm_inode,
+      main_bm_bh, bitmap,
+      la_start_blk, start,
+      total);
+if (status &amp;lt; 0) {
+mlog_errno(status);
+goto bail;
+}
+la-&amp;gt;la_bm_off              = 0;
+la-&amp;gt;la_recs[i].la_start    = 0;
+la-&amp;gt;la_recs[i].la_clusters = 0;
+le16_add_cpu(&amp;amp;la-&amp;gt;la_rec_count, -1);
+le32_add_cpu(&amp;amp;alloc-&amp;gt;id1.bitmap1.i_total, -clusters);
+
+ocfs2_journal_dirty(handle, osb-&amp;gt;local_alloc_bh);
+
+/* if we need more credits extend the transaction */
+credits = OCFS2_WINDOW_MOVE_CREDITS - handle-&amp;gt;h_buffer_credits;
+if (credits &amp;gt; 0) {
+status = ocfs2_extend_trans(handle, credits);
+if (status &amp;lt; 0) {
+mlog_errno(status);
+goto bail;
+}
+status = ocfs2_journal_access_di(handle,
+ INODE_CACHE(osb-&amp;gt;local_alloc_inode),
+ osb-&amp;gt;local_alloc_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
 if (status &amp;lt; 0) {
 mlog_errno(status);
 goto bail;
 }
 }
-if (bit_off &amp;gt;= left)
-break;
-count = 1;
-start = bit_off + 1;
 }
-
 bail:
 if (status)
 mlog_errno(status);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1046,9 +1176,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int ocfs2_recalc_la_window(struct ocfs2_super *osb,
  * We ran out of contiguous space in the primary
  * bitmap. Drastically reduce the number of bits used
  * by local alloc until we have to disable it.
+ * In general we will be seeing atleast few contiguous free
+ * bits. It should be ok to keep local alloc enabled even
+ * in extreme case where max available contiguous free bit is 1
  */
 bits = osb-&amp;gt;local_alloc_bits &amp;gt;&amp;gt; 1;
-if (bits &amp;gt; ocfs2_megabytes_to_clusters(osb-&amp;gt;sb, 1)) {
+if (bits) {
 /*
  * By setting state to THROTTLED, we'll keep
  * the number of local alloc bits used down
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1096,8 +1229,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,
 goto bail;
 }
 
+osb-&amp;gt;local_alloc_bits = osb-&amp;gt;local_alloc_default_bits;
 retry_enospc:
-(*ac)-&amp;gt;ac_bits_wanted = osb-&amp;gt;local_alloc_default_bits;
+(*ac)-&amp;gt;ac_bits_wanted = osb-&amp;gt;local_alloc_bits;
 status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac);
 if (status == -ENOSPC) {
 if (ocfs2_recalc_la_window(osb, OCFS2_LA_EVENT_ENOSPC) ==
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1137,9 +1271,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
 struct ocfs2_alloc_context *ac)
 {
 int status = 0;
-u32 cluster_off, cluster_count;
+u32 wanted, cluster_off, cluster_count;
 struct ocfs2_dinode *alloc = NULL;
 struct ocfs2_local_alloc *la;
+u8 *bitmap;
+int i, rec_cnt, credits;
 
 alloc = (struct ocfs2_dinode *) osb-&amp;gt;local_alloc_bh-&amp;gt;b_data;
 la = OCFS2_LOCAL_ALLOC(alloc);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1156,72 +1292,97 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
 /* we used the generic suballoc reserve function, but we set
  * everything up nicely, so there's no reason why we can't use
  * the more specific cluster api to claim bits. */
-status = ocfs2_claim_clusters(handle, ac, osb-&amp;gt;local_alloc_bits,
-      &amp;amp;cluster_off, &amp;amp;cluster_count);
-if (status == -ENOSPC) {
-retry_enospc:
-/*
- * Note: We could also try syncing the journal here to
- * allow use of any free bits which the current
- * transaction can't give us access to. --Mark
- */
-if (ocfs2_recalc_la_window(osb, OCFS2_LA_EVENT_FRAGMENTED) ==
-    OCFS2_LA_DISABLED)
-goto bail;
-
-ac-&amp;gt;ac_bits_wanted = osb-&amp;gt;local_alloc_default_bits;
-status = ocfs2_claim_clusters(handle, ac,
-      osb-&amp;gt;local_alloc_bits,
-      &amp;amp;cluster_off,
+rec_cnt = 0;
+wanted = osb-&amp;gt;local_alloc_bits;
+while (1) {
+status = ocfs2_claim_clusters(handle, ac, wanted, &amp;amp;cluster_off,
       &amp;amp;cluster_count);
-if (status == -ENOSPC)
-goto retry_enospc;
-/*
- * We only shrunk the *minimum* number of in our
- * request - it's entirely possible that the allocator
- * might give us more than we asked for.
- */
-if (status == 0) {
-spin_lock(&amp;amp;osb-&amp;gt;osb_lock);
-osb-&amp;gt;local_alloc_bits = cluster_count;
-spin_unlock(&amp;amp;osb-&amp;gt;osb_lock);
+if (status == -ENOSPC) {
+/* reduce window size and retry */
+if (ocfs2_recalc_la_window(osb,
+   OCFS2_LA_EVENT_FRAGMENTED) == OCFS2_LA_DISABLED)
+break;
+wanted = osb-&amp;gt;local_alloc_bits;
+continue;
+} else if (status &amp;lt; 0)
+break;
+
+BUG_ON(ac-&amp;gt;ac_bits_given &amp;gt; ac-&amp;gt;ac_bits_wanted);
+
+/* found a window */
+la-&amp;gt;la_recs[rec_cnt].la_start    = cpu_to_le32(cluster_off);
+la-&amp;gt;la_recs[rec_cnt].la_clusters = cpu_to_le32(cluster_count);
+rec_cnt++;
+la-&amp;gt;la_rec_count = cpu_to_le16(rec_cnt);
+le32_add_cpu(&amp;amp;alloc-&amp;gt;id1.bitmap1.i_total, cluster_count);
+
+ocfs2_journal_dirty(handle, osb-&amp;gt;local_alloc_bh);
+
+if (!ocfs2_supports_discontig_la(osb)) {
+la-&amp;gt;la_bm_off = cpu_to_le32(cluster_off);
+break;
+}
+
+/* exit if we can't fit another record */
+wanted = ocfs2_local_alloc_adjust_bits_wanted(la, ac);
+if (!wanted)
+break;
+
+if (wanted &amp;gt; osb-&amp;gt;local_alloc_bits)
+wanted = osb-&amp;gt;local_alloc_bits;
+
+/* if we need more credits extend the transaction */
+if (rec_cnt &amp;gt;= OCFS2_MAX_LOCAL_ALLOC_REC_LIMIT)
+break;
+
+credits = OCFS2_WINDOW_MOVE_CREDITS - handle-&amp;gt;h_buffer_credits;
+if (credits &amp;gt; 0) {
+status = ocfs2_extend_trans(handle, credits);
+if (status &amp;lt; 0) {
+mlog_errno(status);
+goto bail;
+}
+status = ocfs2_journal_access_di(handle,
+ INODE_CACHE(osb-&amp;gt;local_alloc_inode),
+ osb-&amp;gt;local_alloc_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+if (status &amp;lt; 0) {
+mlog_errno(status);
+goto bail;
+}
 }
 }
-if (status &amp;lt; 0) {
-if (status != -ENOSPC)
-mlog_errno(status);
+if (!rec_cnt)
 goto bail;
-}
 
+osb-&amp;gt;local_alloc_state = OCFS2_LA_ENABLED;
+spin_lock(&amp;amp;osb-&amp;gt;osb_lock);
+if (cluster_count &amp;gt; osb-&amp;gt;local_alloc_bits)
+osb-&amp;gt;local_alloc_bits = cluster_count;
+spin_unlock(&amp;amp;osb-&amp;gt;osb_lock);
 osb-&amp;gt;la_last_gd = ac-&amp;gt;ac_last_group;
 
-la-&amp;gt;la_bm_off = cpu_to_le32(cluster_off);
-alloc-&amp;gt;id1.bitmap1.i_total = cpu_to_le32(cluster_count);
-/* just in case... In the future when we find space ourselves,
- * we don't have to get all contiguous -- but we'll have to
- * set all previously used bits in bitmap and update
- * la_bits_set before setting the bits in the main bitmap. */
-alloc-&amp;gt;id1.bitmap1.i_used = 0;
-memset(OCFS2_LOCAL_ALLOC(alloc)-&amp;gt;la_bitmap, 0,
-       le16_to_cpu(la-&amp;gt;la_size));
-
-ocfs2_resmap_restart(&amp;amp;osb-&amp;gt;osb_la_resmap, cluster_count,
-     OCFS2_LOCAL_ALLOC(alloc)-&amp;gt;la_bitmap);
+bitmap = OCFS2_LOCAL_ALLOC_BITMAP(la);
+ocfs2_resmap_restart(&amp;amp;osb-&amp;gt;osb_la_resmap, rec_cnt,
+     alloc-&amp;gt;id1.bitmap1.i_total, bitmap);
+for (i = 0; i &amp;lt; rec_cnt; i++)
+ocfs2_resmap_set_ext(&amp;amp;osb-&amp;gt;osb_la_resmap, i,
+     le32_to_cpu(la-&amp;gt;la_recs[i].la_clusters));
 
-trace_ocfs2_local_alloc_new_window_result(
-OCFS2_LOCAL_ALLOC(alloc)-&amp;gt;la_bm_off,
+trace_ocfs2_local_alloc_new_window_result
+(OCFS2_LOCAL_ALLOC(alloc)-&amp;gt;la_recs[0].la_start,
 le32_to_cpu(alloc-&amp;gt;id1.bitmap1.i_total));
 
 bail:
-if (status)
+if ((status &amp;lt; 0) &amp;amp;&amp;amp; (status != -ENOSPC))
 mlog_errno(status);
+
 return status;
 }
 
 /* Note that we do *NOT* lock the local alloc inode here as
  * it's been locked already for us. */
-static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
-  struct inode *local_alloc_inode)
+static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb)
 {
 int status = 0;
 struct buffer_head *main_bm_bh = NULL;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1268,7 +1429,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
 memcpy(alloc_copy, alloc, osb-&amp;gt;local_alloc_bh-&amp;gt;b_size);
 
 status = ocfs2_journal_access_di(handle,
- INODE_CACHE(local_alloc_inode),
+ INODE_CACHE(osb-&amp;gt;local_alloc_inode),
  osb-&amp;gt;local_alloc_bh,
  OCFS2_JOURNAL_ACCESS_WRITE);
 if (status &amp;lt; 0) {
&lt;/pre&gt;</description>
    <dc:creator>Srinivas Eeda</dc:creator>
    <dc:date>2012-05-07T23:21:29</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7844">
    <title>[PATCH 1/3] ocfs2: new structure to implmentdiscontiguous local alloc bitmap</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7844</link>
    <description>&lt;pre&gt;Current local alloc handles single contiguous free chunk of clusters. This
patch enhances local alloc to handle discontigous free chunks. It adds a new
ocfs2_local_alloc_rec structure which tracks single contiguous free chunk. An
array of these sit in the bitmap itself and track discontiguous chunks. In
best case there is only one record and increases as the filesystem gets
fragmented. Number of records at a time are limited depending on the size
of the bitmap and the max limit is defined by OCFS2_MAX_LOCAL_ALLOC_RECS.

Signed-off-by: Srinivas Eeda &amp;lt;srinivas.eeda&amp;lt; at &amp;gt;oracle.com&amp;gt;
---
 fs/ocfs2/localalloc.c |   10 ++++++++++
 fs/ocfs2/ocfs2.h      |    8 ++++++++
 fs/ocfs2/ocfs2_fs.h   |   48 ++++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 60 insertions(+), 6 deletions(-)

diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
index 210c352..4190e53 100644
--- a/fs/ocfs2/localalloc.c
+++ b/fs/ocfs2/localalloc.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -48,6 +48,16 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 
 #define OCFS2_LOCAL_ALLOC(dinode)(&amp;amp;((dinode)-&amp;gt;id2.i_lab))
 
+#define OCFS2_LOCAL_ALLOC_REC_SZ(la)(le16_to_cpu(la-&amp;gt;la_rec_count) *\
+ sizeof(struct ocfs2_local_alloc_rec))
+#define OCFS2_LOCAL_ALLOC_BITMAP(la)    ((char *)(&amp;amp;(la-&amp;gt;la_recs)) +\
+ OCFS2_LOCAL_ALLOC_REC_SZ(la))
+#define OCFS2_LOCAL_ALLOC_BITS_PER_REC (sizeof(struct ocfs2_local_alloc_rec)*8)
+
+/* Maximum number of local alloc records */
+#define OCFS2_MAX_LOCAL_ALLOC_REC_LIMIT128
+
+
 static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc);
 
 static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index d355e6e..d4c36d2 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -367,6 +367,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct ocfs2_super
  * by osb_lock */
 
 struct buffer_head *local_alloc_bh;
+struct inode   *local_alloc_inode;
 
 u64 la_last_gd;
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -522,6 +523,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static inline int ocfs2_supports_discontig_bg(struct ocfs2_super *osb)
 return 0;
 }
 
+static inline int ocfs2_supports_discontig_la(struct ocfs2_super *osb)
+{
+if (osb-&amp;gt;s_feature_incompat &amp;amp; OCFS2_FEATURE_INCOMPAT_DISCONTIG_LA)
+return 1;
+return 0;
+}
+
 static inline unsigned int ocfs2_link_max(struct ocfs2_super *osb)
 {
 if (ocfs2_supports_indexed_dirs(osb))
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index 938387a..6a0fe02 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -102,7 +102,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
  | OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS \
  | OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE \
  | OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG\
- | OCFS2_FEATURE_INCOMPAT_CLUSTERINFO)
+ | OCFS2_FEATURE_INCOMPAT_CLUSTERINFO \
+ | OCFS2_FEATURE_INCOMPAT_DISCONTIG_LA)
 #define OCFS2_FEATURE_RO_COMPAT_SUPP(OCFS2_FEATURE_RO_COMPAT_UNWRITTEN \
  | OCFS2_FEATURE_RO_COMPAT_USRQUOTA \
  | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -177,6 +178,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
  */
 #define OCFS2_FEATURE_INCOMPAT_CLUSTERINFO0x4000
 
+/* Discontiguous local alloc */
+#define OCFS2_FEATURE_INCOMPAT_DISCONTIG_LA0x8000
+
 /*
  * backup superblock flag is used to indicate that this volume
  * has backup superblocks.
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -664,14 +668,19 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct ocfs2_super_block {
  * Local allocation bitmap for OCFS2 slots
  * Note that it exists inside an ocfs2_dinode, so all offsets are
  * relative to the start of ocfs2_dinode.id2.
+ * Each ocfs2_local_alloc_rec tracks one contigous chunk of clusters.
  */
+struct ocfs2_local_alloc_rec {
+__le32 la_start;/* 1st cluster in this extent */
+__le32 la_clusters;/* Number of contiguous clusters */
+};
+
 struct ocfs2_local_alloc
 {
 /*00*/__le32 la_bm_off;/* Starting bit offset in main bitmap */
 __le16 la_size;/* Size of included bitmap, in bytes */
-__le16 la_reserved1;
-__le64 la_reserved2;
-/*10*/__u8   la_bitmap[0];
+__le16 la_rec_count;/* Number of discontiguous records */
+struct ocfs2_local_alloc_rec la_recs[0]; /* Localalloc records */
 };
 
 /*
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1380,11 +1389,24 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static inline u16 ocfs2_local_alloc_size(struct super_block *sb)
 u16 size;
 
 size = sb-&amp;gt;s_blocksize -
-offsetof(struct ocfs2_dinode, id2.i_lab.la_bitmap);
+offsetof(struct ocfs2_dinode, id2.i_lab.la_recs);
+size -= sizeof(struct ocfs2_local_alloc_rec);
 
 return size;
 }
 
+/* effectively this is also the bitmap size */
+static inline u32 ocfs2_local_alloc_cluster_count(struct ocfs2_local_alloc *la)
+{
+u32 i, clusters;
+
+clusters = 0;
+for (i = 0; i &amp;lt; le16_to_cpu(la-&amp;gt;la_rec_count); i++)
+clusters +=  le32_to_cpu(la-&amp;gt;la_recs[i].la_clusters);
+
+return clusters;
+}
+
 static inline int ocfs2_group_bitmap_size(struct super_block *sb,
   int suballocator,
   u32 feature_incompat)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1528,11 +1550,25 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static inline int ocfs2_local_alloc_size(int blocksize)
 int size;
 
 size = blocksize -
-offsetof(struct ocfs2_dinode, id2.i_lab.la_bitmap);
+offsetof(struct ocfs2_dinode, id2.i_lab.la_recs);
+size -= sizeof(struct ocfs2_local_alloc_rec);
 
 return size;
 }
 
+/* effectively this is also the bitmap size */
+static inline uint32_t
+ocfs2_local_alloc_cluster_count(struct ocfs2_local_alloc *la)
+{
+uint32_t i, clusters;
+
+clusters = 0;
+for (i = 0; i &amp;lt; le16_to_cpu(la-&amp;gt;la_rec_count); i++)
+clusters +=  le32_to_cpu(la-&amp;gt;la_recs[i].la_clusters);
+
+return clusters;
+}
+
 static inline int ocfs2_group_bitmap_size(int blocksize,
   int suballocator,
   uint32_t feature_incompat)
&lt;/pre&gt;</description>
    <dc:creator>Srinivas Eeda</dc:creator>
    <dc:date>2012-05-07T23:21:28</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7843">
    <title>[PATCH 3/3] ocfs2: modify reservation code to supportdiscontigous localalloc</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7843</link>
    <description>&lt;pre&gt;Currently reservation code assumes a bitmap given to it is all one contigous
chunk. This patch enhances it to handle a discontigous chunks. It adds new
fields m_bitmap_ext_cnt and m_bitmap_ext_arr. m_bitmap_ext_arr tracks the sizes
of each contigous free bits and m_bitmap_ext_cnt trackes number of
m_bitmap_ext_arr.

Signed-off-by: Srinivas Eeda &amp;lt;srinivas.eeda&amp;lt; at &amp;gt;oracle.com&amp;gt;
---
 fs/ocfs2/reservations.c |   41 ++++++++++++++++++++++++++++++++++-------
 fs/ocfs2/reservations.h |    7 ++++++-
 2 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/fs/ocfs2/reservations.c b/fs/ocfs2/reservations.c
index 41ffd36..fea93d7 100644
--- a/fs/ocfs2/reservations.c
+++ b/fs/ocfs2/reservations.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -291,7 +291,15 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void ocfs2_resmap_clear_all_resv(struct ocfs2_reservation_map *resmap)
 }
 }
 
-void ocfs2_resmap_restart(struct ocfs2_reservation_map *resmap,
+void ocfs2_resmap_set_ext(struct ocfs2_reservation_map *resmap, int arr, u32 sz)
+{
+if (ocfs2_resmap_disabled(resmap))
+return;
+
+resmap-&amp;gt;m_bitmap_ext_arr[arr] = sz;
+}
+
+void ocfs2_resmap_restart(struct ocfs2_reservation_map *resmap, u32 ext_cnt,
   unsigned int clen, char *disk_bitmap)
 {
 if (ocfs2_resmap_disabled(resmap))
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -300,9 +308,21 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void ocfs2_resmap_restart(struct ocfs2_reservation_map *resmap,
 spin_lock(&amp;amp;resv_lock);
 
 ocfs2_resmap_clear_all_resv(resmap);
+
+/* free existing extent array */
+if (resmap-&amp;gt;m_bitmap_ext_arr)
+kfree(resmap-&amp;gt;m_bitmap_ext_arr);
+
 resmap-&amp;gt;m_bitmap_len = clen;
 resmap-&amp;gt;m_disk_bitmap = disk_bitmap;
 
+resmap-&amp;gt;m_bitmap_ext_cnt = ext_cnt;
+resmap-&amp;gt;m_bitmap_ext_arr = kmalloc((sizeof(u32) * ext_cnt), GFP_NOFS);
+if (!resmap-&amp;gt;m_bitmap_ext_arr) {
+mlog_errno(-ENOMEM);
+resmap-&amp;gt;m_osb-&amp;gt;osb_resv_level = 0;
+}
+
 spin_unlock(&amp;amp;resv_lock);
 }
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -419,20 +439,26 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int ocfs2_resmap_find_free_bits(struct ocfs2_reservation_map *resmap,
        unsigned int *rlen)
 {
 void *bitmap = resmap-&amp;gt;m_disk_bitmap;
-unsigned int best_start, best_len = 0;
+unsigned int best_start, len, ext, best_len = 0;
 int offset, start, found;
 
 trace_ocfs2_resmap_find_free_bits_begin(search_start, search_len,
 wanted, resmap-&amp;gt;m_bitmap_len);
 
-found = best_start = best_len = 0;
-
+found = best_start = best_len = ext = 0;
 start = search_start;
+len = resmap-&amp;gt;m_bitmap_ext_arr[ext++];
 while ((offset = ocfs2_find_next_zero_bit(bitmap, resmap-&amp;gt;m_bitmap_len,
- start)) != -1) {
+  start)) != -1) {
 /* Search reached end of the region */
 if (offset &amp;gt;= (search_start + search_len))
-break;
+goto out;
+
+if (offset &amp;gt;= len) {
+len += resmap-&amp;gt;m_bitmap_ext_arr[ext];
+found = 1;
+start = offset + 1;
+}
 
 if (offset == start) {
 /* we found a zero */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -450,9 +476,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int ocfs2_resmap_find_free_bits(struct ocfs2_reservation_map *resmap,
 }
 
 if (found &amp;gt;= wanted)
-break;
+goto out;
 }
 
+out:
 if (best_len == 0)
 return 0;
 
diff --git a/fs/ocfs2/reservations.h b/fs/ocfs2/reservations.h
index 42c2b80..bb5e94f 100644
--- a/fs/ocfs2/reservations.h
+++ b/fs/ocfs2/reservations.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -56,6 +56,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct ocfs2_reservation_map {
 u32m_bitmap_len;/* Number of valid
  * bits available */
 
+u32m_bitmap_ext_cnt;
+u32*m_bitmap_ext_arr;
 struct list_headm_lru;/* LRU of reservations
  * structures. */
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -94,6 +96,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void ocfs2_resv_discard(struct ocfs2_reservation_map *resmap,
 int ocfs2_resmap_init(struct ocfs2_super *osb,
       struct ocfs2_reservation_map *resmap);
 
+void ocfs2_resmap_set_ext(struct ocfs2_reservation_map *resmap, int arr,
+  u32 sz);
+
 /**
  * ocfs2_resmap_restart() - "restart" a reservation bitmap
  * &amp;lt; at &amp;gt;resmap: reservations bitmap
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -107,7 +112,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ocfs2_resmap_init(struct ocfs2_super *osb,
  * reservations. A future version will recalculate existing
  * reservations based on the new bitmap.
  */
-void ocfs2_resmap_restart(struct ocfs2_reservation_map *resmap,
+void ocfs2_resmap_restart(struct ocfs2_reservation_map *resmap, u32 ext_cnt,
   unsigned int clen, char *disk_bitmap);
 
 /**
&lt;/pre&gt;</description>
    <dc:creator>Srinivas Eeda</dc:creator>
    <dc:date>2012-05-07T23:21:30</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7841">
    <title>Ocfs2 + Quota!</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7841</link>
    <description>&lt;pre&gt;Hello Guys
This is awsome you want guys do more stable OCFS2 but mayby someone repair 
problem with ocfs2 + quota deadlock?
Because is amazing unstable i report bug 4 month ago on ocfs2-users/ 
ocfs2-devel mailing list and Oracle Bugzilla and everyone confirm problem 
but noone repair.. :(
http://oss.oracle.com/bugzilla/show_bug.cgi?id=1339
and:
http://oss.oracle.com/pipermail/ocfs2-users/2012-January/005637.html


Thanks.
&lt;/pre&gt;</description>
    <dc:creator>Marek Królikowski</dc:creator>
    <dc:date>2012-04-17T21:13:44</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7840">
    <title>Re: Ocfs2/move_extents: move/defrag extents within acertain range.</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7840</link>
    <description>&lt;pre&gt;Gar...  I somehow missed that this warning was really old.  Sorry
for that.  I will fix my scripts to avoid this.

regards,
dan carpenter

_______________________________________________
Ocfs2-devel mailing list
Ocfs2-devel&amp;lt; at &amp;gt;oss.oracle.com
http://oss.oracle.com/mailman/listinfo/ocfs2-devel&lt;/pre&gt;</description>
    <dc:creator>Dan Carpenter</dc:creator>
    <dc:date>2012-02-15T20:40:56</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7839">
    <title>Re: [patch] ocfs2: cleanup error handling ino2hb_alloc_hb_set()</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7839</link>
    <description>&lt;pre&gt;
It's a static checker thing.  It's either an unneeded NULL check or
a check on the wrong variable depending on how you look at it.
Recently, I've been sending a lot of patches to remove unneeded NULL
checks for static checkers.  I try to fix the mistakes that are
harmless so that the real bugs aren't drowned out in noise.

regards,
dan carpenter

_______________________________________________
Ocfs2-devel mailing list
Ocfs2-devel&amp;lt; at &amp;gt;oss.oracle.com
http://oss.oracle.com/mailman/listinfo/ocfs2-devel&lt;/pre&gt;</description>
    <dc:creator>Dan Carpenter</dc:creator>
    <dc:date>2012-02-13T20:29:24</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7838">
    <title>Re: Ocfs2/move_extents: move/defrag extents within acertain range.</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7838</link>
    <description>&lt;pre&gt;Hello Tristan Ye,

This is a semi-automatic email about new static checker warnings.

The patch 53069d4e7695: "Ocfs2/move_extents: move/defrag extents 
within a certain range." from May 25, 2011, leads to the following 
Smatch complaint:

fs/ocfs2/move_extents.c:980 ocfs2_move_extents()
 warn: variable dereferenced before check 'inode' (see line 978)

fs/ocfs2/move_extents.c
   977struct buffer_head *di_bh = NULL;
   978struct ocfs2_super *osb = OCFS2_SB(inode-&amp;gt;i_sb);
                                                   ^^^^^^^^^^^
Dereference.

   979
   980if (!inode)
                    ^^^^^^
Check.

   981return -ENOENT;
   982

regards,
dan carpenter
&lt;/pre&gt;</description>
    <dc:creator>Dan Carpenter</dc:creator>
    <dc:date>2012-02-15T20:31:51</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7837">
    <title>[patch] ocfs2: cleanup error handling ino2hb_alloc_hb_set()</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7837</link>
    <description>&lt;pre&gt;If "ret" is NULL, then "hs" is also NULL, so there is no need to free
it.  config_group_init_type_name() can't fail if the name ("heartbeat"
in this case) is less than CONFIGFS_ITEM_NAME_LEN (20) characters long
so we can just remove this error handling code.

Signed-off-by: Dan Carpenter &amp;lt;dan.carpenter&amp;lt; at &amp;gt;oracle.com&amp;gt;

diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index f3f2d95..0bca51b 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2306,20 +2306,14 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct config_item_type o2hb_heartbeat_group_type = {
 struct config_group *o2hb_alloc_hb_set(void)
 {
 struct o2hb_heartbeat_group *hs = NULL;
-struct config_group *ret = NULL;
 
 hs = kzalloc(sizeof(struct o2hb_heartbeat_group), GFP_KERNEL);
 if (hs == NULL)
-goto out;
+return NULL;
 
 config_group_init_type_name(&amp;amp;hs-&amp;gt;hs_group, "heartbeat",
     &amp;amp;o2hb_heartbeat_group_type);
-
-ret = &amp;amp;hs-&amp;gt;hs_group;
-out:
-if (ret == NULL)
-kfree(hs);
-return ret;
+return &amp;amp;hs-&amp;gt;hs_group;
 }
 
 void o2hb_free_hb_set(struct config_group *group)
&lt;/pre&gt;</description>
    <dc:creator>Dan Carpenter</dc:creator>
    <dc:date>2012-02-13T13:50:47</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7836">
    <title>Re: [patch] ocfs2: cleanup error handling ino2hb_alloc_hb_set()</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7836</link>
    <description>&lt;pre&gt;
The error handling isn't correct because checking "&amp;amp;hs-&amp;gt;hs_group"
for NULL doesn't work.  "hs" and "&amp;amp;hs-&amp;gt;hs_group" are the same
address and we checked "hs" already.  If we wanted to check for
allocation errors, then we would need to change the check to:

        if (!hs-&amp;gt;hs_group.cg_item.ci_name)
kfree(hs);

But that's not how the function is supposed to be used.  The example
code in Documentation/filesystems/configfs/configfs_example_explicit.c
doesn't have error handling.

regards,
dan carpenter

_______________________________________________
Ocfs2-devel mailing list
Ocfs2-devel&amp;lt; at &amp;gt;oss.oracle.com
http://oss.oracle.com/mailman/listinfo/ocfs2-devel&lt;/pre&gt;</description>
    <dc:creator>Dan Carpenter</dc:creator>
    <dc:date>2012-02-13T20:08:35</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7825">
    <title>[PATCH 09/27] fs: Push mnt_want_write() outside ofi_mutex</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7825</link>
    <description>&lt;pre&gt;Currently, mnt_want_write() is sometimes called with i_mutex held and sometimes
without it. This isn't really a problem because mnt_want_write() is a
non-blocking operation (essentially has a trylock semantics) but when the
function starts to handle also frozen filesystems, it will get a full lock
semantics and thus proper lock ordering has to be established. So move
all mnt_want_write() calls outside of i_mutex.

One non-trivial case needing conversion is kern_path_create() /
user_path_create() which didn't include mnt_want_write() but now needs to
because it acquires i_mutex.  Because there are virtual file systems which
don't bother with freeze / remount-ro protection we actually provide both
versions of the function - one which calls mnt_want_write() and one which does
not.

CC: ocfs2-devel&amp;lt; at &amp;gt;oss.oracle.com
CC: Mark Fasheh &amp;lt;mfasheh&amp;lt; at &amp;gt;suse.com&amp;gt;
CC: Joel Becker &amp;lt;jlbec&amp;lt; at &amp;gt;evilplan.org&amp;gt;
CC: "David S. Miller" &amp;lt;davem&amp;lt; at &amp;gt;davemloft.net&amp;gt;
BugLink: https://bugs.launchpad.net/bugs/897421
Tested-by: Kamal Mostafa &amp;lt;kamal&amp;lt; at &amp;gt;canonical.com&amp;gt;
Tested-by: Peter M. Petrakis &amp;lt;peter.petrakis&amp;lt; at &amp;gt;canonical.com&amp;gt;
Tested-by: Dann Frazier &amp;lt;dann.frazier&amp;lt; at &amp;gt;canonical.com&amp;gt;
Tested-by: Massimo Morana &amp;lt;massimo.morana&amp;lt; at &amp;gt;canonical.com&amp;gt;
Signed-off-by: Jan Kara &amp;lt;jack&amp;lt; at &amp;gt;suse.cz&amp;gt;
---
 fs/namei.c              |  115 +++++++++++++++++++++++++++--------------------
 fs/ocfs2/refcounttree.c |   10 +---
 include/linux/namei.h   |    2 +
 net/unix/af_unix.c      |   13 ++----
 4 files changed, 74 insertions(+), 66 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 0062dd1..5417fa1 100644
--- a/fs/namei.c
+++ b/fs/namei.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2460,7 +2460,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
 return file;
 }
 
-struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path, int is_dir)
+static struct dentry *do_kern_path_create(int dfd, const char *pathname,
+  struct path *path, int is_dir,
+  int freeze_protect)
 {
 struct dentry *dentry = ERR_PTR(-EEXIST);
 struct nameidata nd;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2478,6 +2480,14 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path
 nd.flags |= LOOKUP_CREATE | LOOKUP_EXCL;
 nd.intent.open.flags = O_EXCL;
 
+if (freeze_protect) {
+error = mnt_want_write(nd.path.mnt);
+if (error) {
+dentry = ERR_PTR(error);
+goto out;
+}
+}
+
 /*
  * Do the final lookup.
  */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2506,24 +2516,49 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; eexist:
 dentry = ERR_PTR(-EEXIST);
 fail:
 mutex_unlock(&amp;amp;nd.path.dentry-&amp;gt;d_inode-&amp;gt;i_mutex);
+if (freeze_protect)
+mnt_drop_write(nd.path.mnt);
 out:
 path_put(&amp;amp;nd.path);
 return dentry;
 }
+
+struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path, int is_dir)
+{
+return do_kern_path_create(dfd, pathname, path, is_dir, 0);
+}
 EXPORT_SYMBOL(kern_path_create);
 
+struct dentry *kern_path_create_thawed(int dfd, const char *pathname, struct path *path, int is_dir)
+{
+return do_kern_path_create(dfd, pathname, path, is_dir, 1);
+}
+EXPORT_SYMBOL(kern_path_create_thawed);
+
 struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, int is_dir)
 {
 char *tmp = getname(pathname);
 struct dentry *res;
 if (IS_ERR(tmp))
 return ERR_CAST(tmp);
-res = kern_path_create(dfd, tmp, path, is_dir);
+res = do_kern_path_create(dfd, tmp, path, is_dir, 0);
 putname(tmp);
 return res;
 }
 EXPORT_SYMBOL(user_path_create);
 
+struct dentry *user_path_create_thawed(int dfd, const char __user *pathname, struct path *path, int is_dir)
+{
+char *tmp = getname(pathname);
+struct dentry *res;
+if (IS_ERR(tmp))
+return ERR_CAST(tmp);
+res = do_kern_path_create(dfd, tmp, path, is_dir, 1);
+putname(tmp);
+return res;
+}
+EXPORT_SYMBOL(user_path_create_thawed);
+
 int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
 {
 int error = may_create(dir, dentry);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2579,7 +2614,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
 if (S_ISDIR(mode))
 return -EPERM;
 
-dentry = user_path_create(dfd, filename, &amp;amp;path, 0);
+dentry = user_path_create_thawed(dfd, filename, &amp;amp;path, 0);
 if (IS_ERR(dentry))
 return PTR_ERR(dentry);
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2588,12 +2623,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
 error = may_mknod(mode);
 if (error)
 goto out_dput;
-error = mnt_want_write(path.mnt);
-if (error)
-goto out_dput;
 error = security_path_mknod(&amp;amp;path, dentry, mode, dev);
 if (error)
-goto out_drop_write;
+goto out_dput;
 switch (mode &amp;amp; S_IFMT) {
 case 0: case S_IFREG:
 error = vfs_create(path.dentry-&amp;gt;d_inode,dentry,mode,NULL);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2606,11 +2638,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
 error = vfs_mknod(path.dentry-&amp;gt;d_inode,dentry,mode,0);
 break;
 }
-out_drop_write:
-mnt_drop_write(path.mnt);
 out_dput:
 dput(dentry);
 mutex_unlock(&amp;amp;path.dentry-&amp;gt;d_inode-&amp;gt;i_mutex);
+mnt_drop_write(path.mnt);
 path_put(&amp;amp;path);
 
 return error;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2652,24 +2683,20 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
 struct path path;
 int error;
 
-dentry = user_path_create(dfd, pathname, &amp;amp;path, 1);
+dentry = user_path_create_thawed(dfd, pathname, &amp;amp;path, 1);
 if (IS_ERR(dentry))
 return PTR_ERR(dentry);
 
 if (!IS_POSIXACL(path.dentry-&amp;gt;d_inode))
 mode &amp;amp;= ~current_umask();
-error = mnt_want_write(path.mnt);
-if (error)
-goto out_dput;
 error = security_path_mkdir(&amp;amp;path, dentry, mode);
 if (error)
-goto out_drop_write;
+goto out_dput;
 error = vfs_mkdir(path.dentry-&amp;gt;d_inode, dentry, mode);
-out_drop_write:
-mnt_drop_write(path.mnt);
 out_dput:
 dput(dentry);
 mutex_unlock(&amp;amp;path.dentry-&amp;gt;d_inode-&amp;gt;i_mutex);
+mnt_drop_write(path.mnt);
 path_put(&amp;amp;path);
 return error;
 }
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2764,6 +2791,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static long do_rmdir(int dfd, const char __user *pathname)
 }
 
 nd.flags &amp;amp;= ~LOOKUP_PARENT;
+error = mnt_want_write(nd.path.mnt);
+if (error)
+goto exit1;
 
 mutex_lock_nested(&amp;amp;nd.path.dentry-&amp;gt;d_inode-&amp;gt;i_mutex, I_MUTEX_PARENT);
 dentry = lookup_hash(&amp;amp;nd);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2774,19 +2804,15 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static long do_rmdir(int dfd, const char __user *pathname)
 error = -ENOENT;
 goto exit3;
 }
-error = mnt_want_write(nd.path.mnt);
-if (error)
-goto exit3;
 error = security_path_rmdir(&amp;amp;nd.path, dentry);
 if (error)
-goto exit4;
+goto exit3;
 error = vfs_rmdir(nd.path.dentry-&amp;gt;d_inode, dentry);
-exit4:
-mnt_drop_write(nd.path.mnt);
 exit3:
 dput(dentry);
 exit2:
 mutex_unlock(&amp;amp;nd.path.dentry-&amp;gt;d_inode-&amp;gt;i_mutex);
+mnt_drop_write(nd.path.mnt);
 exit1:
 path_put(&amp;amp;nd.path);
 putname(name);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2853,6 +2879,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static long do_unlinkat(int dfd, const char __user *pathname)
 goto exit1;
 
 nd.flags &amp;amp;= ~LOOKUP_PARENT;
+error = mnt_want_write(nd.path.mnt);
+if (error)
+goto exit1;
 
 mutex_lock_nested(&amp;amp;nd.path.dentry-&amp;gt;d_inode-&amp;gt;i_mutex, I_MUTEX_PARENT);
 dentry = lookup_hash(&amp;amp;nd);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2865,21 +2894,17 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static long do_unlinkat(int dfd, const char __user *pathname)
 if (!inode)
 goto slashes;
 ihold(inode);
-error = mnt_want_write(nd.path.mnt);
-if (error)
-goto exit2;
 error = security_path_unlink(&amp;amp;nd.path, dentry);
 if (error)
-goto exit3;
+goto exit2;
 error = vfs_unlink(nd.path.dentry-&amp;gt;d_inode, dentry);
-exit3:
-mnt_drop_write(nd.path.mnt);
-exit2:
+exit2:
 dput(dentry);
 }
 mutex_unlock(&amp;amp;nd.path.dentry-&amp;gt;d_inode-&amp;gt;i_mutex);
 if (inode)
 iput(inode);/* truncate the inode here */
+mnt_drop_write(nd.path.mnt);
 exit1:
 path_put(&amp;amp;nd.path);
 putname(name);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2939,23 +2964,19 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
 if (IS_ERR(from))
 return PTR_ERR(from);
 
-dentry = user_path_create(newdfd, newname, &amp;amp;path, 0);
+dentry = user_path_create_thawed(newdfd, newname, &amp;amp;path, 0);
 error = PTR_ERR(dentry);
 if (IS_ERR(dentry))
 goto out_putname;
 
-error = mnt_want_write(path.mnt);
-if (error)
-goto out_dput;
 error = security_path_symlink(&amp;amp;path, dentry, from);
 if (error)
-goto out_drop_write;
+goto out_dput;
 error = vfs_symlink(path.dentry-&amp;gt;d_inode, dentry, from);
-out_drop_write:
-mnt_drop_write(path.mnt);
 out_dput:
 dput(dentry);
 mutex_unlock(&amp;amp;path.dentry-&amp;gt;d_inode-&amp;gt;i_mutex);
+mnt_drop_write(path.mnt);
 path_put(&amp;amp;path);
 out_putname:
 putname(from);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3048,7 +3069,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
 if (error)
 return error;
 
-new_dentry = user_path_create(newdfd, newname, &amp;amp;new_path, 0);
+new_dentry = user_path_create_thawed(newdfd, newname, &amp;amp;new_path, 0);
 error = PTR_ERR(new_dentry);
 if (IS_ERR(new_dentry))
 goto out;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3056,18 +3077,14 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
 error = -EXDEV;
 if (old_path.mnt != new_path.mnt)
 goto out_dput;
-error = mnt_want_write(new_path.mnt);
-if (error)
-goto out_dput;
 error = security_path_link(old_path.dentry, &amp;amp;new_path, new_dentry);
 if (error)
-goto out_drop_write;
+goto out_dput;
 error = vfs_link(old_path.dentry, new_path.dentry-&amp;gt;d_inode, new_dentry);
-out_drop_write:
-mnt_drop_write(new_path.mnt);
 out_dput:
 dput(new_dentry);
 mutex_unlock(&amp;amp;new_path.dentry-&amp;gt;d_inode-&amp;gt;i_mutex);
+mnt_drop_write(new_path.mnt);
 path_put(&amp;amp;new_path);
 out:
 path_put(&amp;amp;old_path);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3264,6 +3281,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
 if (newnd.last_type != LAST_NORM)
 goto exit2;
 
+error = mnt_want_write(oldnd.path.mnt);
+if (error)
+goto exit2;
+
 oldnd.flags &amp;amp;= ~LOOKUP_PARENT;
 newnd.flags &amp;amp;= ~LOOKUP_PARENT;
 newnd.flags |= LOOKUP_RENAME_TARGET;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3299,23 +3320,19 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
 if (new_dentry == trap)
 goto exit5;
 
-error = mnt_want_write(oldnd.path.mnt);
-if (error)
-goto exit5;
 error = security_path_rename(&amp;amp;oldnd.path, old_dentry,
      &amp;amp;newnd.path, new_dentry);
 if (error)
-goto exit6;
+goto exit5;
 error = vfs_rename(old_dir-&amp;gt;d_inode, old_dentry,
    new_dir-&amp;gt;d_inode, new_dentry);
-exit6:
-mnt_drop_write(oldnd.path.mnt);
 exit5:
 dput(new_dentry);
 exit4:
 dput(old_dentry);
 exit3:
 unlock_rename(new_dir, old_dir);
+mnt_drop_write(oldnd.path.mnt);
 exit2:
 path_put(&amp;amp;newnd.path);
 putname(to);
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index cf78233..a99b8e2 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -4453,7 +4453,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ocfs2_reflink_ioctl(struct inode *inode,
 return error;
 }
 
-new_dentry = user_path_create(AT_FDCWD, newname, &amp;amp;new_path, 0);
+new_dentry = user_path_create_thawed(AT_FDCWD, newname, &amp;amp;new_path, 0);
 error = PTR_ERR(new_dentry);
 if (IS_ERR(new_dentry)) {
 mlog_errno(error);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -4466,19 +4466,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ocfs2_reflink_ioctl(struct inode *inode,
 goto out_dput;
 }
 
-error = mnt_want_write(new_path.mnt);
-if (error) {
-mlog_errno(error);
-goto out_dput;
-}
-
 error = ocfs2_vfs_reflink(old_path.dentry,
   new_path.dentry-&amp;gt;d_inode,
   new_dentry, preserve);
-mnt_drop_write(new_path.mnt);
 out_dput:
 dput(new_dentry);
 mutex_unlock(&amp;amp;new_path.dentry-&amp;gt;d_inode-&amp;gt;i_mutex);
+mnt_drop_write(new_path.mnt);
 path_put(&amp;amp;new_path);
 out:
 path_put(&amp;amp;old_path);
diff --git a/include/linux/namei.h b/include/linux/namei.h
index ffc0213..432f6bb 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -77,7 +77,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; extern int user_path_at_empty(int, const char __user *, unsigned, struct path *,
 extern int kern_path(const char *, unsigned, struct path *);
 
 extern struct dentry *kern_path_create(int, const char *, struct path *, int);
+extern struct dentry *kern_path_create_thawed(int, const char *, struct path *, int);
 extern struct dentry *user_path_create(int, const char __user *, struct path *, int);
+extern struct dentry *user_path_create_thawed(int, const char __user *, struct path *, int);
 extern int kern_path_parent(const char *, struct nameidata *);
 extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
    const char *, unsigned int, struct path *);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index d510353..c532632 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -865,7 +865,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
  * Get the parent directory, calculate the hash for last
  * component.
  */
-dentry = kern_path_create(AT_FDCWD, sun_path, &amp;amp;path, 0);
+dentry = kern_path_create_thawed(AT_FDCWD, sun_path, &amp;amp;path, 0);
 err = PTR_ERR(dentry);
 if (IS_ERR(dentry))
 goto out_mknod_parent;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -875,19 +875,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
  */
 mode = S_IFSOCK |
        (SOCK_INODE(sock)-&amp;gt;i_mode &amp;amp; ~current_umask());
-err = mnt_want_write(path.mnt);
-if (err)
-goto out_mknod_dput;
 err = security_path_mknod(&amp;amp;path, dentry, mode, 0);
 if (err)
-goto out_mknod_drop_write;
-err = vfs_mknod(path.dentry-&amp;gt;d_inode, dentry, mode, 0);
-out_mknod_drop_write:
-mnt_drop_write(path.mnt);
-if (err)
 goto out_mknod_dput;
+err = vfs_mknod(path.dentry-&amp;gt;d_inode, dentry, mode, 0);
 mutex_unlock(&amp;amp;path.dentry-&amp;gt;d_inode-&amp;gt;i_mutex);
 dput(path.dentry);
+mnt_drop_write(path.mnt);
 path.dentry = dentry;
 
 addr-&amp;gt;hash = UNIX_HASH_SIZE;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -924,6 +918,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; out:
 out_mknod_dput:
 dput(dentry);
 mutex_unlock(&amp;amp;path.dentry-&amp;gt;d_inode-&amp;gt;i_mutex);
+mnt_drop_write(path.mnt);
 path_put(&amp;amp;path);
 out_mknod_parent:
 if (err == -EEXIST)
&lt;/pre&gt;</description>
    <dc:creator>Jan Kara</dc:creator>
    <dc:date>2012-04-16T16:13:47</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7824">
    <title>[PATCH 19/27] ocfs2: Convert to new freezing mechanism</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7824</link>
    <description>&lt;pre&gt;Protect ocfs2_page_mkwrite() and ocfs2_file_aio_write() using the new
freeze protection. We also protect several ioctl entry points which
were missing the protection.

CC: Mark Fasheh &amp;lt;mfasheh&amp;lt; at &amp;gt;suse.com&amp;gt;
CC: Joel Becker &amp;lt;jlbec&amp;lt; at &amp;gt;evilplan.org&amp;gt;
CC: ocfs2-devel&amp;lt; at &amp;gt;oss.oracle.com
Signed-off-by: Jan Kara &amp;lt;jack&amp;lt; at &amp;gt;suse.cz&amp;gt;
---
 fs/ocfs2/file.c  |   11 +++++++++--
 fs/ocfs2/ioctl.c |   14 ++++++++++++--
 fs/ocfs2/mmap.c  |    2 ++
 3 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 061591a..9b1e3d4 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1971,6 +1971,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ocfs2_change_file_space(struct file *file, unsigned int cmd,
 {
 struct inode *inode = file-&amp;gt;f_path.dentry-&amp;gt;d_inode;
 struct ocfs2_super *osb = OCFS2_SB(inode-&amp;gt;i_sb);
+int ret;
 
 if ((cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) &amp;amp;&amp;amp;
     !ocfs2_writes_unwritten_extents(osb))
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1985,7 +1986,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int ocfs2_change_file_space(struct file *file, unsigned int cmd,
 if (!(file-&amp;gt;f_mode &amp;amp; FMODE_WRITE))
 return -EBADF;
 
-return __ocfs2_change_file_space(file, inode, file-&amp;gt;f_pos, cmd, sr, 0);
+ret = mnt_want_write_file(file);
+if (ret)
+return ret;
+ret = __ocfs2_change_file_space(file, inode, file-&amp;gt;f_pos, cmd, sr, 0);
+mnt_drop_write_file(file);
+return ret;
 }
 
 static long ocfs2_fallocate(struct file *file, int mode, loff_t offset,
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2261,7 +2267,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
 if (iocb-&amp;gt;ki_left == 0)
 return 0;
 
-vfs_check_frozen(inode-&amp;gt;i_sb, SB_FREEZE_WRITE);
+sb_start_write(inode-&amp;gt;i_sb);
 
 appending = file-&amp;gt;f_flags &amp;amp; O_APPEND ? 1 : 0;
 direct_io = file-&amp;gt;f_flags &amp;amp; O_DIRECT ? 1 : 0;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2434,6 +2440,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; out_sems:
 ocfs2_iocb_clear_sem_locked(iocb);
 
 mutex_unlock(&amp;amp;inode-&amp;gt;i_mutex);
+sb_end_write(inode-&amp;gt;i_sb);
 
 if (written)
 ret = written;
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
index a1a1bfd..d9c352b 100644
--- a/fs/ocfs2/ioctl.c
+++ b/fs/ocfs2/ioctl.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -926,7 +926,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 if (get_user(new_clusters, (int __user *)arg))
 return -EFAULT;
 
-return ocfs2_group_extend(inode, new_clusters);
+status = mnt_want_write_file(filp);
+if (status)
+return status;
+status = ocfs2_group_extend(inode, new_clusters);
+mnt_drop_write_file(filp);
+return status;
 case OCFS2_IOC_GROUP_ADD:
 case OCFS2_IOC_GROUP_ADD64:
 if (!capable(CAP_SYS_RESOURCE))
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -935,7 +940,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 if (copy_from_user(&amp;amp;input, (int __user *) arg, sizeof(input)))
 return -EFAULT;
 
-return ocfs2_group_add(inode, &amp;amp;input);
+status = mnt_want_write_file(filp);
+if (status)
+return status;
+status = ocfs2_group_add(inode, &amp;amp;input);
+mnt_drop_write_file(filp);
+return status;
 case OCFS2_IOC_REFLINK:
 if (copy_from_user(&amp;amp;args, (struct reflink_arguments *)arg,
    sizeof(args)))
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c
index 9cd4108..d150372 100644
--- a/fs/ocfs2/mmap.c
+++ b/fs/ocfs2/mmap.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -136,6 +136,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 sigset_t oldset;
 int ret;
 
+sb_start_pagefault(inode-&amp;gt;i_sb);
 ocfs2_block_signals(&amp;amp;oldset);
 
 /*
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -165,6 +166,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 
 out:
 ocfs2_unblock_signals(&amp;amp;oldset);
+sb_end_pagefault(inode-&amp;gt;i_sb);
 return ret;
 }
 
&lt;/pre&gt;</description>
    <dc:creator>Jan Kara</dc:creator>
    <dc:date>2012-04-16T16:13:57</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7822">
    <title>Re: Maybe a null point bug in__ocfs2_change_file_space.</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7822</link>
    <description>&lt;pre&gt;Hi Limin,
Thanks for the report and the patch is already there. Please search the
archive with the subject "ocfs2: Fix oops in fallocate()".

Thanks
Tao
On 04/13/2012 03:58 PM, Chang Limin wrote:

_______________________________________________
Ocfs2-devel mailing list
Ocfs2-devel&amp;lt; at &amp;gt;oss.oracle.com
http://oss.oracle.com/mailman/listinfo/ocfs2-devel&lt;/pre&gt;</description>
    <dc:creator>Tao Ma</dc:creator>
    <dc:date>2012-04-13T09:26:52</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7821">
    <title>Maybe a null point bug in __ocfs2_change_file_space.</title>
    <link>http://permalink.gmane.org/gmane.comp.file-systems.ocfs2.devel/7821</link>
    <description>&lt;pre&gt;Hi,
 Version linux-3.3
In function
static long ocfs2_fallocate(struct file *file, int mode, loff_t offset,
                        loff_t len)
{
…
return __ocfs2_change_file_space(NULL, inode, offset, cmd, &amp;amp;sr,           // file is NULL
                                        change_size);
}

In function
static int __ocfs2_change_file_space(struct file *file, struct inode *inode,
                                  loff_t f_pos, unsigned int cmd,
                                  struct ocfs2_space_resv *sr,
                                  int change_size)
{
if (file-&amp;gt;f_flags &amp;amp; O_SYNC)                                                                                   // access file-&amp;gt;f_flags result null pointer
           handle-&amp;gt;h_sync = 1;
}

Changlimin

-------------------------------------------------------------------------------------------------------------------------------------
本邮件及其附件含有杭州华三通信技术有限公司的保密信息，仅限于发送给上面地址中列出
的个人或群组。禁止任何其他人以任何形式使用（包括但不限于全部或部分地泄露、复制、
或散发）本邮件中的信息。如果您错收了本邮件，请您立即电话或邮件通知发件人并删除本
邮件！
This e-mail and its attachments contain confidential information from H3C, which is
intended only for the person or entity whose address is listed above. Any use of the
information contained herein in any way (including, but not limited to, total or partial
disclosure, reproduction, or dissemination) by persons other than the intended
recipient(s) is prohibited. If you receive this e-mail in error, please notify the sender
by phone or email immediately and delete it!
_______________________________________________
Ocfs2-devel mailing list
Ocfs2-devel&amp;lt; at &amp;gt;oss.oracle.com
http://oss.oracle.com/mailman/listinfo/ocfs2-devel&lt;/pre&gt;</description>
    <dc:creator>Chang Limin</dc:creator>
    <dc:date>2012-04-13T03:32:57</dc:date>
  </item>
  <textinput rdf:about="http://search.gmane.org/?group=$group=gmane.comp.file-systems.ocfs2.devel">
    <title>Search Engine</title>
    <description>Search the mailing list at Gmane</description>
    <name>query</name>
    <link>http://search.gmane.org/?group=$group=gmane.comp.file-systems.ocfs2.devel</link>
  </textinput>
</rdf:RDF>

