public void read(long fileOffset, byte[] dest, int off, int len) throws IOException {   synchronized(((Ext2FileSystem)getFileSystem()).getInodeCache()) {   rereadInode();      iNode.incLocked(); }    synchronized(iNode) { try{ if(len+off>getLength()) throw new IOException("Can't read past the file!"); long blockSize = iNode.getExt2FileSystem().getBlockSize(); long bytesRead=0; while( bytesRead < len ) { long blockNr = (fileOffset+bytesRead) / blockSize; long blockOffset = (fileOffset+bytesRead) % blockSize; long copyLength = Math.min(len-bytesRead, blockSize - blockOffset);  System.arraycopy( 	iNode.getDataBlock(blockNr), (int)blockOffset, dest, off+(int)bytesRead, (int)copyLength);  bytesRead += copyLength; }  iNode.decLocked(); return; }catch(Throwable t) {  iNode.decLocked(); throw new IOException(t); } } }
public void read(long fileOffset, byte[] dest, int off, int len) throws IOException {    synchronized (((Ext2FileSystem) getFileSystem()).getInodeCache()) {   rereadInode();          iNode.incLocked(); }      synchronized (iNode) { try { if (len + off > getLength()) throw new IOException("Can't read past the file!"); long blockSize = iNode.getExt2FileSystem().getBlockSize(); long bytesRead = 0; while (bytesRead < len) { long blockNr = (fileOffset + bytesRead) / blockSize; long blockOffset = (fileOffset + bytesRead) % blockSize; long copyLength = Math.min(len - bytesRead, blockSize - blockOffset);  System.arraycopy(iNode.getDataBlock(blockNr), (int) blockOffset, dest, off + (int) bytesRead, (int) copyLength);  bytesRead += copyLength; } return; } catch (Throwable ex) { final IOException ioe = new IOException(); ioe.initCause(ex); throw ioe; } finally {  iNode.decLocked(); } } }
	public void read(long fileOffset, byte[] dest, int off, int len) throws IOException {		//synchronize to the inode cache to make sure that the inode does not get		//flushed between reading it and locking it		synchronized(((Ext2FileSystem)getFileSystem()).getInodeCache()) {			//reread the inode before synchronizing to it to make sure			//all threads use the same instance			rereadInode();					//lock the inode into the cache so it is not flushed before synchronizing to it			//(otherwise a new instance of INode referring to the same inode could be put			//in the cache resulting in the possibility of two threads manipulating the same			//inode at the same time because they would synchronize to different INode instances)			iNode.incLocked();		}		//a single inode may be represented by more than one Ext2Directory instances, 		//but each will use the same instance of the underlying inode (see Ext2FileSystem.getINode()),		//so synchronize to the inode		synchronized(iNode) {			try{				if(len+off>getLength())					throw new IOException("Can't read past the file!");				long blockSize = iNode.getExt2FileSystem().getBlockSize();				long bytesRead=0;				while( bytesRead < len ) {					long blockNr = (fileOffset+bytesRead) / blockSize;					long blockOffset = (fileOffset+bytesRead) % blockSize;					long copyLength = Math.min(len-bytesRead, blockSize - blockOffset);										System.arraycopy( 	iNode.getDataBlock(blockNr), (int)blockOffset,										dest, off+(int)bytesRead, (int)copyLength);															bytesRead += copyLength;				}				//read done, unlock the inode from the cache				iNode.decLocked();				return;			}catch(Throwable t) {				//could not fininsh the operation, unlock the inode from the cache				iNode.decLocked();				throw new IOException(t);						}		}	}