Revision: 5910
          http://jnode.svn.sourceforge.net/jnode/?rev=5910&view=rev
Author:   galatnm
Date:     2012-08-10 06:36:07 +0000 (Fri, 10 Aug 2012)
Log Message:
-----------
Add initial support for ext4 extents

Modified Paths:
--------------
    trunk/fs/src/fs/org/jnode/fs/ext2/INode.java

Added Paths:
-----------
    trunk/fs/src/fs/org/jnode/fs/ext2/Extent.java
    trunk/fs/src/fs/org/jnode/fs/ext2/ExtentHeader.java
    trunk/fs/src/fs/org/jnode/fs/ext2/ExtentIndex.java

Added: trunk/fs/src/fs/org/jnode/fs/ext2/Extent.java
===================================================================
--- trunk/fs/src/fs/org/jnode/fs/ext2/Extent.java                               
(rev 0)
+++ trunk/fs/src/fs/org/jnode/fs/ext2/Extent.java       2012-08-10 06:36:07 UTC 
(rev 5910)
@@ -0,0 +1,44 @@
+package org.jnode.fs.ext2;
+
+/**
+ * An ext4 extent object.
+ *
+ * @author Luke Quinane
+ */
+public class Extent {
+    /**
+     * The length of an extent.
+     */
+    public static final int EXTENT_LENGTH = 12;
+
+    /**
+     * The data for the extent.
+     */
+    private byte[] data;
+
+    /**
+     * Create an extent object.
+     *
+     * @param data the data for the extent.
+     */
+    public Extent(byte[] data) {
+        this.data = new byte[EXTENT_LENGTH];
+        System.arraycopy(data, 0, this.data, 0, EXTENT_LENGTH);
+    }
+
+    public long getBlockIndex() {
+        return Ext2Utils.get32(data, 0);
+    }
+
+    public int getBlockCount() {
+        return Ext2Utils.get16(data, 4);
+    }
+
+    public long getStartLow() {
+        return Ext2Utils.get32(data, 8);
+    }
+
+    public int getStartHigh() {
+        return Ext2Utils.get16(data, 6);
+    }
+}

Added: trunk/fs/src/fs/org/jnode/fs/ext2/ExtentHeader.java
===================================================================
--- trunk/fs/src/fs/org/jnode/fs/ext2/ExtentHeader.java                         
(rev 0)
+++ trunk/fs/src/fs/org/jnode/fs/ext2/ExtentHeader.java 2012-08-10 06:36:07 UTC 
(rev 5910)
@@ -0,0 +1,134 @@
+package org.jnode.fs.ext2;
+
+import java.io.IOException;
+
+/**
+ * An ext4 extent header.
+ *
+ * @author Luke Quinane
+ */
+public class ExtentHeader {
+    /**
+     * The length of an extent header.
+     */
+    public static final int EXTENT_HEADER_LENGTH = 12;
+
+    /**
+     * The magic number for an extent header.
+     */
+    public static final int MAGIC = 0xf30a;
+
+    /**
+     * The data for the header.
+     */
+    private byte[] data;
+
+    /**
+     * The cache copy of the index entries.
+     */
+    private ExtentIndex[] indexEntries;
+
+    /**
+     * The cache copy of the extent entries.
+     */
+    private Extent[] extentEntries;
+
+    /**
+     * Create an extent header object.
+     */
+    public ExtentHeader(byte[] data) throws IOException {
+        this.data = new byte[data.length];
+        System.arraycopy(data, 0, this.data, 0, data.length);
+
+        if (getMagic() != ExtentHeader.MAGIC) {
+            throw new IOException("Extent had the wrong magic: " + getMagic());
+        }
+    }
+
+    public int getMagic() {
+        return Ext2Utils.get16(data, 0);
+    }
+
+    public int getEntryCount() {
+        return Ext2Utils.get16(data, 2);
+    }
+
+    public int getMaximumEntryCount() {
+        return Ext2Utils.get16(data, 4);
+    }
+
+    public int getDepth() {
+        return Ext2Utils.get16(data, 6);
+    }
+
+    public ExtentIndex[] getIndexEntries() {
+        if (getDepth() == 0) {
+            throw new IllegalStateException("Trying to read index entries from 
a leaf.");
+        }
+
+        if (indexEntries == null) {
+            indexEntries = new ExtentIndex[getEntryCount()];
+            int offset = EXTENT_HEADER_LENGTH;
+
+            for (int i = 0; i < getEntryCount(); i++) {
+                byte[] indexBuffer = new byte[ExtentIndex.EXTENT_INDEX_LENGTH];
+                System.arraycopy(data, offset, indexBuffer, 0, 
indexBuffer.length);
+
+                indexEntries[i] = new ExtentIndex(indexBuffer);
+                offset += ExtentIndex.EXTENT_INDEX_LENGTH;
+            }
+        }
+
+        return indexEntries;
+    }
+
+    public Extent[] getExtentEntries() {
+        if (getDepth() != 0) {
+            throw new IllegalStateException("Trying to read extent entries 
from a non-leaf.");
+        }
+
+        if (extentEntries == null) {
+            extentEntries = new Extent[getEntryCount()];
+            int offset = EXTENT_HEADER_LENGTH;
+
+            for (int i = 0; i < getEntryCount(); i++) {
+                byte[] indexBuffer = new byte[Extent.EXTENT_LENGTH];
+                System.arraycopy(data, offset, indexBuffer, 0, 
indexBuffer.length);
+
+                extentEntries[i] = new Extent(indexBuffer);
+                offset += Extent.EXTENT_LENGTH;
+            }
+        }
+
+        return extentEntries;
+    }
+
+    public long getBlockNumber(long index) {
+        if (getDepth() > 0) {
+            ExtentIndex[] indexes = getIndexEntries();
+
+            throw new UnsupportedOperationException();
+        }
+        else {
+            Extent[] extents = getExtentEntries();
+
+            int lowIndex = 0;
+            int highIndex = extents.length - 1;
+            Extent extent = null;
+
+            while (lowIndex <= highIndex) {
+                int middle = lowIndex + (highIndex - lowIndex) / 2;
+                extent = extents[middle];
+
+                if (index < extent.getBlockIndex()) {
+                    highIndex = middle - 1;
+                }
+                else {
+                    lowIndex = middle + 1;
+                }
+            }
+
+            return extent.getStartLow();
+        }
+    }
+}

Added: trunk/fs/src/fs/org/jnode/fs/ext2/ExtentIndex.java
===================================================================
--- trunk/fs/src/fs/org/jnode/fs/ext2/ExtentIndex.java                          
(rev 0)
+++ trunk/fs/src/fs/org/jnode/fs/ext2/ExtentIndex.java  2012-08-10 06:36:07 UTC 
(rev 5910)
@@ -0,0 +1,40 @@
+package org.jnode.fs.ext2;
+
+/**
+ * An ext4 extent index.
+ *
+ * @author Luke Quinane
+ */
+public class ExtentIndex {
+    /**
+     * The length of an extent index.
+     */
+    public static final int EXTENT_INDEX_LENGTH = 12;
+
+    /**
+     * The data for the index.
+     */
+    private byte[] data;
+
+    /**
+     * Create an extent index object.
+     *
+     * @param data the data for the index.
+     */
+    public ExtentIndex(byte[] data) {
+        this.data = new byte[EXTENT_INDEX_LENGTH];
+        System.arraycopy(data, 0, this.data, 0, EXTENT_INDEX_LENGTH);
+    }
+
+    public long getBlockIndex() {
+        return Ext2Utils.get32(data, 0);
+    }
+
+    public long getLeafLow() {
+        return Ext2Utils.get32(data, 4);
+    }
+
+    public int getLeafHigh() {
+        return Ext2Utils.get16(data, 8);
+    }
+}

Modified: trunk/fs/src/fs/org/jnode/fs/ext2/INode.java
===================================================================
--- trunk/fs/src/fs/org/jnode/fs/ext2/INode.java        2012-08-10 06:32:22 UTC 
(rev 5909)
+++ trunk/fs/src/fs/org/jnode/fs/ext2/INode.java        2012-08-10 06:36:07 UTC 
(rev 5910)
@@ -22,7 +22,6 @@
 
 import java.io.IOException;
 import java.util.Arrays;
-
 import org.apache.log4j.Level;
 import org.apache.log4j.Logger;
 import org.jnode.fs.FileSystemException;
@@ -60,6 +59,11 @@
     private Ext2FileSystem fs;
 
     /**
+     * The cached extent header.
+     */
+    private ExtentHeader extentHeader;
+
+    /**
      * Create an INode object from an existing inode on the disk.
      * 
      * @param fs
@@ -280,6 +284,36 @@
      * @throws IOException
      */
     private long getDataBlockNr(long i) throws IOException {
+        if ((getFlags() & Ext2Constants.EXT4_INODE_EXTENTS_FLAG) != 0) {
+            if (extentHeader == null) {
+                byte[] headerBuffer = new byte[64];
+                System.arraycopy(data, 40, headerBuffer, 0, 
headerBuffer.length);
+
+                extentHeader = new ExtentHeader(headerBuffer);
+            }
+
+            return extentHeader.getBlockNumber(i);
+        }
+        else {
+            return getDataBlockNrIndirect(i);
+        }
+    }
+
+    /**
+     * Return the number of the block in the filesystem that stores the ith
+     * block of the inode (i is a sequential index from the beginning of the
+     * file) using an indirect (ext2 / ext3) lookup.
+     *
+     * [Naming convention used: in the code, a <code>...BlockNr</code> always
+     * means an absolute block nr (of the filesystem), while a
+     * <code>...BlockIndex</code> means an index relative to the beginning of
+     * a block]
+     *
+     * @param i
+     * @return the block number
+     * @throws IOException
+     */
+     private long getDataBlockNrIndirect(long i) throws IOException {
         final long blockCount = getAllocatedBlockCount();
         final int indirectCount = getIndirectCount();
         if (i > blockCount - 1) {
@@ -910,6 +944,10 @@
 
     public void setDirty(boolean b) {
         dirty = b;
+
+        if (dirty) {
+            extentHeader = null;
+        }
     }
 
     public synchronized boolean isLocked() {

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Jnode-svn-commits mailing list
Jnode-svn-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jnode-svn-commits

Reply via email to