summaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/dat.c
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2009-05-11 20:58:47 +0200
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2009-06-10 16:41:11 +0200
commit003ff182fddde09ddfb8d079bbdb02f9d2122082 (patch)
treed949fa673353767d8854355987e49d82821935f6 /fs/nilfs2/dat.c
parentNILFS2: Pagecache usage optimization on NILFS2 (diff)
downloadlinux-003ff182fddde09ddfb8d079bbdb02f9d2122082.tar.xz
linux-003ff182fddde09ddfb8d079bbdb02f9d2122082.zip
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/dat.c')
-rw-r--r--fs/nilfs2/dat.c21
1 files changed, 11 insertions, 10 deletions
diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c
index 1827f62c772d..0b2710e2d565 100644
--- a/fs/nilfs2/dat.c
+++ b/fs/nilfs2/dat.c
@@ -376,36 +376,37 @@ int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp)
return ret;
}
-ssize_t nilfs_dat_get_vinfo(struct inode *dat, struct nilfs_vinfo *vinfo,
+ssize_t nilfs_dat_get_vinfo(struct inode *dat, void *buf, unsigned visz,
size_t nvi)
{
struct buffer_head *entry_bh;
struct nilfs_dat_entry *entry;
+ struct nilfs_vinfo *vinfo = buf;
__u64 first, last;
void *kaddr;
unsigned long entries_per_block = NILFS_MDT(dat)->mi_entries_per_block;
int i, j, n, ret;
for (i = 0; i < nvi; i += n) {
- ret = nilfs_palloc_get_entry_block(dat, vinfo[i].vi_vblocknr,
+ ret = nilfs_palloc_get_entry_block(dat, vinfo->vi_vblocknr,
0, &entry_bh);
if (ret < 0)
return ret;
kaddr = kmap_atomic(entry_bh->b_page, KM_USER0);
/* last virtual block number in this block */
- first = vinfo[i].vi_vblocknr;
+ first = vinfo->vi_vblocknr;
do_div(first, entries_per_block);
first *= entries_per_block;
last = first + entries_per_block - 1;
for (j = i, n = 0;
- j < nvi && vinfo[j].vi_vblocknr >= first &&
- vinfo[j].vi_vblocknr <= last;
- j++, n++) {
+ j < nvi && vinfo->vi_vblocknr >= first &&
+ vinfo->vi_vblocknr <= last;
+ j++, n++, vinfo = (void *)vinfo + visz) {
entry = nilfs_palloc_block_get_entry(
- dat, vinfo[j].vi_vblocknr, entry_bh, kaddr);
- vinfo[j].vi_start = le64_to_cpu(entry->de_start);
- vinfo[j].vi_end = le64_to_cpu(entry->de_end);
- vinfo[j].vi_blocknr = le64_to_cpu(entry->de_blocknr);
+ dat, vinfo->vi_vblocknr, entry_bh, kaddr);
+ vinfo->vi_start = le64_to_cpu(entry->de_start);
+ vinfo->vi_end = le64_to_cpu(entry->de_end);
+ vinfo->vi_blocknr = le64_to_cpu(entry->de_blocknr);
}
kunmap_atomic(kaddr, KM_USER0);
brelse(entry_bh);