On Fri, Feb 26, 2016 at 04:19:45PM +0100, yegorslists@xxxxxxxxxxxxxx wrote: > From: Yegor Yefremov <yegorslists@xxxxxxxxxxxxxx> > > The driver was imported from Linux 4.4. > > Current implementation supports only XZ decompressor. > > Tested-by: Antony Pavlov <antonynpavlov@xxxxxxxxx> > Signed-off-by: Yegor Yefremov <yegorslists@xxxxxxxxxxxxxx> > --- > Changes: > v4: - add promt to mount examples > - rework squashfs_read to enable non linear reading > - embed super_block into squashfs_priv > - check malloc' return value > > v3: - rework inode searching > - eliminate memleaks in directory search > > v2: - fix checkpatch errors > - remove spinlock/wait code from cache implementation > - fix directory listing > - add documentation entry about SquashFS > - fix compiling without XZ enabled > - fix some memory leaks > > + > +static int squashfs_read(struct device_d *_dev, FILE *f, void *buf, > + size_t insize) > +{ > + unsigned int size = insize; > + unsigned int pos = f->pos; > + unsigned int ofs; > + unsigned int now; > + unsigned int idx; > + unsigned int data_block_pos, data_block; > + struct squashfs_page *page = f->priv; > + > + data_block = f->pos / (32 * PAGE_CACHE_SIZE); > + if (data_block != page->data_block) { > + page->data_block = data_block; > + page->idx = 0; > + } > + > + data_block_pos = f->pos - page->data_block * 32 * PAGE_CACHE_SIZE; > + idx = data_block_pos / PAGE_CACHE_SIZE; > + page->real_page.index = page->data_block * 32; > + > + while (size) { > + if (page->idx == 0) > + squashfs_readpage(NULL, &page->real_page); > + > + /* Read till end of current buffer page */ > + ofs = pos % PAGE_CACHE_SIZE; > + if (ofs) { > + now = min(size, PAGE_CACHE_SIZE - ofs); > + memcpy(buf, page->buf[idx] + ofs, now); > + > + size -= now; > + pos += now; > + buf += now; > + idx++; > + if (idx > 31) { > + idx = 0; > + page->idx = 0; > + page->data_block++; > + page->real_page.index = page->data_block * 32; > + continue; > + } > + } > + > + /* Do full buffer pages */ > + while (size >= PAGE_CACHE_SIZE) { > + memcpy(buf, page->buf[idx], PAGE_CACHE_SIZE); > + size -= PAGE_CACHE_SIZE; > + pos += PAGE_CACHE_SIZE; > + buf += PAGE_CACHE_SIZE; > + idx++; > + if (idx > 31) { > + idx = 0; > + page->idx = 0; > + page->data_block++; > + page->real_page.index = page->data_block * 32; > + continue; Here you increase the real_page.index without calling squashfs_readpage() again. The outer loop shouldn't be necessary. It is used in the if (ofs) above, but this doesn't look entirely correct. I think you are doing too much in this function. It should be easier if you create a helper function that takes the current file position and returns the buffer that belongs to this position. See below for a (completely untested) template: static int squashfs_read_buf(struct squashfs_page *page, int pos, void **buf) { unsigned int data_block = pos / (32 * PAGE_CACHE_SIZE); unsigned int data_block_pos = pos % (32 * PAGE_CACHE_SIZE); unsigned int idx = data_block_pos / PAGE_CACHE_SIZE; if (data_block != page->data_block) { page->real_page.index = data_block * 32; squashfs_readpage(NULL, &page->real_page); page->data_block = data_block; } *buf = page->buf[idx]; return 0; } static int squashfs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize) { unsigned int size = insize; unsigned int pos = f->pos; unsigned int ofs; unsigned int now; void *pagebuf; struct squashfs_page *page = f->priv; /* Read till end of current buffer page */ ofs = pos % PAGE_CACHE_SIZE; if (ofs) { squashfs_read_buf(page, pos, &pagebuf); now = min(size, PAGE_CACHE_SIZE - ofs); memcpy(buf, pagebuf + ofs, now); size -= now; pos += now; buf += now; } /* Do full buffer pages */ while (size >= PAGE_CACHE_SIZE) { squashfs_read_buf(page, pos, &pagebuf); memcpy(buf, pagebuf, PAGE_CACHE_SIZE); size -= PAGE_CACHE_SIZE; pos += PAGE_CACHE_SIZE; buf += PAGE_CACHE_SIZE; } /* And the rest */ if (size) { squashfs_read_buf(page, pos, &pagebuf); memcpy(buf, pagebuf, size); size = 0; } return insize; } Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox