aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/sufile.c
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2009-05-11 14:58:47 -0400
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2009-06-10 10:41:11 -0400
commit003ff182fddde09ddfb8d079bbdb02f9d2122082 (patch)
treed949fa673353767d8854355987e49d82821935f6 /fs/nilfs2/sufile.c
parent258ef67e246fd548e7ad91c23004ad157c03cce5 (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.c22
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 */
602ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, 603ssize_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);