summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak2010-01-20 20:01:59 +0100
committerKarel Zak2010-01-20 20:01:59 +0100
commit15a8fb429ce7d07d19a7f0044a85f0919fe57b27 (patch)
tree95e412d99412068b17e9ce471725b1e77f41ab06
parenttests: update FS test images (diff)
downloadkernel-qcow2-util-linux-15a8fb429ce7d07d19a7f0044a85f0919fe57b27.tar.gz
kernel-qcow2-util-linux-15a8fb429ce7d07d19a7f0044a85f0919fe57b27.tar.xz
kernel-qcow2-util-linux-15a8fb429ce7d07d19a7f0044a85f0919fe57b27.zip
libblkid: rewrite blkid_probe_get_buffer()
The library does not use any buffer with fixed size any more. The new version calls read() for necessary data only. Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--shlibs/blkid/src/blkidP.h21
-rw-r--r--shlibs/blkid/src/probe.c187
-rw-r--r--shlibs/blkid/src/superblocks/vfat.c6
3 files changed, 68 insertions, 146 deletions
diff --git a/shlibs/blkid/src/blkidP.h b/shlibs/blkid/src/blkidP.h
index fb40505be..975878c4b 100644
--- a/shlibs/blkid/src/blkidP.h
+++ b/shlibs/blkid/src/blkidP.h
@@ -133,8 +133,6 @@ struct blkid_prval
struct blkid_chain *chain; /* owner */
};
-#define BLKID_SB_BUFSIZ 0x11000
-
/*
* Filesystem / Raid magic strings
*/
@@ -172,6 +170,13 @@ struct blkid_idinfo
*/
#define BLKID_IDINFO_TOLERANT (1 << 1)
+struct blkid_bufinfo {
+ unsigned char *data;
+ blkid_loff_t off;
+ blkid_loff_t len;
+ struct list_head bufs; /* list of buffers */
+};
+
/*
* Low-level probing control struct
*/
@@ -187,13 +192,7 @@ struct blkid_struct_probe
int flags; /* private libray flags */
- unsigned char *sbbuf; /* superblok buffer */
- size_t sbbuf_len; /* size of data in superblock buffer */
-
- unsigned char *buf; /* seek buffer */
- blkid_loff_t buf_off; /* offset of seek buffer */
- size_t buf_len; /* size of data in seek buffer */
- size_t buf_max; /* allocated size of seek buffer */
+ struct list_head buffers; /* list of buffers */
struct blkid_chain chains[BLKID_NCHAINS]; /* array of chains */
struct blkid_chain *cur_chain; /* current chain */
@@ -360,12 +359,8 @@ extern void blkid_free_dev(blkid_dev dev);
/* probe.c */
extern int blkid_probe_is_tiny(blkid_probe pr);
-extern int blkid_probe_has_buffer(blkid_probe pr,
- blkid_loff_t off, blkid_loff_t len);
extern unsigned char *blkid_probe_get_buffer(blkid_probe pr,
blkid_loff_t off, blkid_loff_t len);
-extern unsigned char *blkid_probe_get_extra_buffer(blkid_probe pr,
- blkid_loff_t off, blkid_loff_t len);
extern unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector);
diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c
index 1bd98b55d..91366851e 100644
--- a/shlibs/blkid/src/probe.c
+++ b/shlibs/blkid/src/probe.c
@@ -115,6 +115,7 @@ static const struct blkid_chaindrv *chains_drvs[] = {
};
static void blkid_probe_reset_vals(blkid_probe pr);
+static void blkid_probe_reset_buffer(blkid_probe pr);
/**
* blkid_new_probe:
@@ -137,6 +138,7 @@ blkid_probe blkid_new_probe(void)
pr->chains[i].flags = chains_drvs[i]->dflt_flags;
pr->chains[i].enabled = chains_drvs[i]->dflt_enabled;
}
+ INIT_LIST_HEAD(&pr->buffers);
return pr;
}
@@ -202,26 +204,13 @@ void blkid_free_probe(blkid_probe pr)
ch->driver->free_data(pr, ch->data);
free(ch->fltr);
}
- free(pr->buf);
- free(pr->sbbuf);
if ((pr->flags & BLKID_PRIVATE_FD) && pr->fd >= 0)
close(pr->fd);
+ blkid_probe_reset_buffer(pr);
free(pr);
}
-static void blkid_probe_reset_buffer(blkid_probe pr)
-{
- DBG(DEBUG_LOWPROBE, printf("reseting blkid probe buffer\n"));
- if (pr->buf)
- memset(pr->buf, 0, pr->buf_max);
- pr->buf_off = 0;
- pr->buf_len = 0;
- if (pr->sbbuf)
- memset(pr->sbbuf, 0, BLKID_SB_BUFSIZ);
- pr->sbbuf_len = 0;
-}
-
/*
* Removes chain values from probing result.
@@ -470,141 +459,79 @@ int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[
return 0;
}
-int blkid_probe_has_buffer(blkid_probe pr,
+unsigned char *blkid_probe_get_buffer(blkid_probe pr,
blkid_loff_t off, blkid_loff_t len)
{
- return pr && (off + len <= pr->sbbuf_len ||
- (pr->buf_off < off && off + len < pr->buf_len));
-}
+ struct list_head *p;
+ struct blkid_bufinfo *bf = NULL;
+
+ list_for_each(p, &pr->buffers) {
+ struct blkid_bufinfo *x =
+ list_entry(p, struct blkid_bufinfo, bufs);
+
+ if (x->off <= off && off + len <= x->off + x->len) {
+ DBG(DEBUG_LOWPROBE,
+ printf("\treuse buffer: off=%jd len=%jd\n",
+ x->off, x->len));
+ bf = x;
+ break;
+ }
+ }
+ if (!bf) {
+ ssize_t ret;
-/*
- * Returns buffer from the begin (69kB) of the device.
- */
-static unsigned char *blkid_probe_get_sb_buffer(blkid_probe pr,
- blkid_loff_t off, blkid_loff_t len)
-{
- if (off + len > BLKID_SB_BUFSIZ)
- return NULL;
- if (!pr->sbbuf) {
- pr->sbbuf = malloc(BLKID_SB_BUFSIZ);
- if (!pr->sbbuf)
+ if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0)
return NULL;
- }
- if (off + len > pr->sbbuf_len) {
- /*
- * The sbbuf is not completely in memory.
- *
- */
- ssize_t ret_read;
- blkid_loff_t want, have = pr->sbbuf_len;
-
- if (blkid_probe_is_tiny(pr))
- /* We don't read whole BLKID_SB_BUFSIZ by one read(),
- * it's too aggresive to small devices (floppies). We
- * read necessary data to complete the current request
- * (off + len) only.
- */
- want = off + len - have;
- else
- /* large disk -- read all SB */
- want = BLKID_SB_BUFSIZ - have;
+
+ /* allocate info and space for data by why call */
+ bf = calloc(1, sizeof(struct blkid_bufinfo) + len);
+ if (!bf)
+ return NULL;
+
+ bf->data = ((unsigned char *) bf) + sizeof(struct blkid_bufinfo);
+ bf->len = len;
+ bf->off = off;
+ INIT_LIST_HEAD(&bf->bufs);
DBG(DEBUG_LOWPROBE,
- printf("\tsb-buffer read() off=%jd len=%jd\n", have, want));
+ printf("\tbuffer read: off=%jd len=%jd\n", off, len));
- if (lseek(pr->fd, pr->off + have, SEEK_SET) < 0)
+ ret = read(pr->fd, bf->data, len);
+ if (ret != (ssize_t) len) {
+ free(bf);
return NULL;
-
- ret_read = read(pr->fd, pr->sbbuf + have, want);
- if (ret_read < 0)
- ret_read = 0;
- pr->sbbuf_len = have + ret_read;
+ }
+ list_add_tail(&bf->bufs, &pr->buffers);
}
- if (off + len > pr->sbbuf_len)
- return NULL;
- return pr->sbbuf + off;
+
+ return off ? bf->data + (off - bf->off) : bf->data;
}
-/*
- * Returns pointer to the buffer on arbitrary offset on the device
- */
-unsigned char *blkid_probe_get_extra_buffer(blkid_probe pr,
- blkid_loff_t off, blkid_loff_t len)
+
+static void blkid_probe_reset_buffer(blkid_probe pr)
{
- unsigned char *newbuf = NULL;
-
- if (off + len <= BLKID_SB_BUFSIZ &&
- (!blkid_probe_is_tiny(pr) || blkid_probe_has_buffer(pr, off, len)))
- /*
- * Don't use extra buffer for superblock data if
- * - data are already in SB buffer
- * - or the device is large and we needn't extra
- * optimalization for tiny devices
- */
- return blkid_probe_get_sb_buffer(pr, off, len);
+ ssize_t read_ct = 0, len_ct = 0;
- if (len > pr->buf_max) {
- newbuf = realloc(pr->buf, len);
- if (!newbuf)
- return NULL;
- pr->buf = newbuf;
- pr->buf_max = len;
- pr->buf_off = 0;
- pr->buf_len = 0;
- }
- if (newbuf || off < pr->buf_off ||
- off + len > pr->buf_off + pr->buf_len) {
- ssize_t ret_read;
+ if (!pr || list_empty(&pr->buffers))
+ return;
- if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0)
- return NULL;
+ DBG(DEBUG_LOWPROBE, printf("reseting probing buffers\n"));
- DBG(DEBUG_LOWPROBE,
- printf("\textra-buffer read: off=%jd len=%jd\n", off, len));
+ while (!list_empty(&pr->buffers)) {
+ struct blkid_bufinfo *bf = list_entry(pr->buffers.next,
+ struct blkid_bufinfo, bufs);
- ret_read = read(pr->fd, pr->buf, len);
- if (ret_read != (ssize_t) len)
- return NULL;
- pr->buf_off = off;
- pr->buf_len = len;
+ read_ct++;
+ len_ct += bf->len;
+ list_del(&bf->bufs);
+ free(bf);
}
- return off ? pr->buf + (off - pr->buf_off) : pr->buf;
-}
+ DBG(DEBUG_LOWPROBE,
+ printf("buffers summary: %jd bytes by %jd read() call(s)\n",
+ len_ct, read_ct));
-/*
- * @off: offset within probing area
- * @len: size of requested buffer
- *
- * The probing area is between pr->off and pr->size. The @off = 0 is pr->off, the
- * max @len is pr->size.
- *
- * Note that we have two offsets:
- *
- * 1/ general device offset (pr->off), that's useful for example when we
- * probe a partition from whole disk image:
- * blkid -O <partition_position> -S <size> disk.img
- *
- * 2/ buffer offset (the @off argument), that useful for offsets in
- * superbloks, ...
- *
- * That means never use lseek(fd, 0, SEEK_SET), the zero position is always
- * pr->off, so lseek(fd, pr->off, SEEK_SET).
- *
- */
-unsigned char *blkid_probe_get_buffer(blkid_probe pr,
- blkid_loff_t off, blkid_loff_t len)
-{
- if (off < 0 || len < 0) {
- DBG(DEBUG_LOWPROBE,
- printf("unexpected offset or length of buffer requested\n"));
- return NULL;
- }
- if (off + len > pr->size)
- return NULL;
- if (off + len <= BLKID_SB_BUFSIZ)
- return blkid_probe_get_sb_buffer(pr, off, len);
- return blkid_probe_get_extra_buffer(pr, off, len);
+ INIT_LIST_HEAD(&pr->buffers);
}
/*
diff --git a/shlibs/blkid/src/superblocks/vfat.c b/shlibs/blkid/src/superblocks/vfat.c
index 29066c34c..71c0fbcbd 100644
--- a/shlibs/blkid/src/superblocks/vfat.c
+++ b/shlibs/blkid/src/superblocks/vfat.c
@@ -142,7 +142,7 @@ static unsigned char *search_fat_label(blkid_probe pr,
*/
if (!dir)
ent = (struct vfat_dir_entry *)
- blkid_probe_get_extra_buffer(pr,
+ blkid_probe_get_buffer(pr,
offset + (i * sizeof(struct vfat_dir_entry)),
sizeof(struct vfat_dir_entry));
else
@@ -330,7 +330,7 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag)
/* get FAT entry */
fat_entry_off = (reserved * sector_size) +
(next * sizeof(uint32_t));
- buf = blkid_probe_get_extra_buffer(pr, fat_entry_off, buf_size);
+ buf = blkid_probe_get_buffer(pr, fat_entry_off, buf_size);
if (buf == NULL)
break;
@@ -351,7 +351,7 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag)
if (fsinfo_sect) {
struct fat32_fsinfo *fsinfo;
- buf = blkid_probe_get_extra_buffer(pr,
+ buf = blkid_probe_get_buffer(pr,
fsinfo_sect * sector_size,
sizeof(struct fat32_fsinfo));
if (buf == NULL)