diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2009-05-11 14:58:47 -0400 |
---|---|---|
committer | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2009-06-10 10:41:11 -0400 |
commit | 003ff182fddde09ddfb8d079bbdb02f9d2122082 (patch) | |
tree | d949fa673353767d8854355987e49d82821935f6 /fs/nilfs2/sufile.c | |
parent | 258ef67e246fd548e7ad91c23004ad157c03cce5 (diff) |
nilfs2: allow future expansion of metadata read out via get info ioctl
Nilfs has some ioctl commands to read out metadata from meta data
files:
- NILFS_IOCTL_GET_CPINFO for checkpoint file,
- NILFS_IOCTL_GET_SUINFO for segment usage file, and
- NILFS_IOCTL_GET_VINFO for Disk Address Transalation (DAT) file,
respectively.
Every routine on these metadata files is implemented so that it allows
future expansion of on-disk format. But, the above ioctl commands do
not support expansion even though nilfs_argv structure can handle
arbitrary size for data exchanged via ioctl.
This allows future expansion of the following structures which give
basic format of the "get information" ioctls:
- struct nilfs_cpinfo
- struct nilfs_suinfo
- struct nilfs_vinfo
So, this introduces forward compatility of such ioctl commands.
In this patch, a sanity check in nilfs_ioctl_get_info() function is
changed to accept larger data structure [1], and metadata read
routines are rewritten so that they become compatible for larger
structures; the routines will just ignore the remaining fields which
the current version of nilfs doesn't know.
[1] The ioctl function already has another upper limit (PAGE_SIZE
against a structure, which appears in nilfs_ioctl_wrap_copy
function), and this will not cause security problem.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2/sufile.c')
-rw-r--r-- | fs/nilfs2/sufile.c | 22 |
1 files changed, 13 insertions, 9 deletions
diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c index da127325fdaa..37994d4a59cc 100644 --- a/fs/nilfs2/sufile.c +++ b/fs/nilfs2/sufile.c | |||
@@ -587,7 +587,8 @@ void nilfs_sufile_do_set_error(struct inode *sufile, __u64 segnum, | |||
587 | * nilfs_sufile_get_suinfo - | 587 | * nilfs_sufile_get_suinfo - |
588 | * @sufile: inode of segment usage file | 588 | * @sufile: inode of segment usage file |
589 | * @segnum: segment number to start looking | 589 | * @segnum: segment number to start looking |
590 | * @si: array of suinfo | 590 | * @buf: array of suinfo |
591 | * @sisz: byte size of suinfo | ||
591 | * @nsi: size of suinfo array | 592 | * @nsi: size of suinfo array |
592 | * | 593 | * |
593 | * Description: | 594 | * Description: |
@@ -599,11 +600,12 @@ void nilfs_sufile_do_set_error(struct inode *sufile, __u64 segnum, | |||
599 | * | 600 | * |
600 | * %-ENOMEM - Insufficient amount of memory available. | 601 | * %-ENOMEM - Insufficient amount of memory available. |
601 | */ | 602 | */ |
602 | ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, | 603 | ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf, |
603 | struct nilfs_suinfo *si, size_t nsi) | 604 | unsigned sisz, size_t nsi) |
604 | { | 605 | { |
605 | struct buffer_head *su_bh; | 606 | struct buffer_head *su_bh; |
606 | struct nilfs_segment_usage *su; | 607 | struct nilfs_segment_usage *su; |
608 | struct nilfs_suinfo *si = buf; | ||
607 | size_t susz = NILFS_MDT(sufile)->mi_entry_size; | 609 | size_t susz = NILFS_MDT(sufile)->mi_entry_size; |
608 | struct the_nilfs *nilfs = NILFS_MDT(sufile)->mi_nilfs; | 610 | struct the_nilfs *nilfs = NILFS_MDT(sufile)->mi_nilfs; |
609 | void *kaddr; | 611 | void *kaddr; |
@@ -628,20 +630,22 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, | |||
628 | if (ret != -ENOENT) | 630 | if (ret != -ENOENT) |
629 | goto out; | 631 | goto out; |
630 | /* hole */ | 632 | /* hole */ |
631 | memset(&si[i], 0, sizeof(struct nilfs_suinfo) * n); | 633 | memset(si, 0, sisz * n); |
634 | si = (void *)si + sisz * n; | ||
632 | continue; | 635 | continue; |
633 | } | 636 | } |
634 | 637 | ||
635 | kaddr = kmap_atomic(su_bh->b_page, KM_USER0); | 638 | kaddr = kmap_atomic(su_bh->b_page, KM_USER0); |
636 | su = nilfs_sufile_block_get_segment_usage( | 639 | su = nilfs_sufile_block_get_segment_usage( |
637 | sufile, segnum, su_bh, kaddr); | 640 | sufile, segnum, su_bh, kaddr); |
638 | for (j = 0; j < n; j++, su = (void *)su + susz) { | 641 | for (j = 0; j < n; |
639 | si[i + j].sui_lastmod = le64_to_cpu(su->su_lastmod); | 642 | j++, su = (void *)su + susz, si = (void *)si + sisz) { |
640 | si[i + j].sui_nblocks = le32_to_cpu(su->su_nblocks); | 643 | si->sui_lastmod = le64_to_cpu(su->su_lastmod); |
641 | si[i + j].sui_flags = le32_to_cpu(su->su_flags) & | 644 | si->sui_nblocks = le32_to_cpu(su->su_nblocks); |
645 | si->sui_flags = le32_to_cpu(su->su_flags) & | ||
642 | ~(1UL << NILFS_SEGMENT_USAGE_ACTIVE); | 646 | ~(1UL << NILFS_SEGMENT_USAGE_ACTIVE); |
643 | if (nilfs_segment_is_active(nilfs, segnum + j)) | 647 | if (nilfs_segment_is_active(nilfs, segnum + j)) |
644 | si[i + j].sui_flags |= | 648 | si->sui_flags |= |
645 | (1UL << NILFS_SEGMENT_USAGE_ACTIVE); | 649 | (1UL << NILFS_SEGMENT_USAGE_ACTIVE); |
646 | } | 650 | } |
647 | kunmap_atomic(kaddr, KM_USER0); | 651 | kunmap_atomic(kaddr, KM_USER0); |