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/dat.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/dat.c')
-rw-r--r-- | fs/nilfs2/dat.c | 21 |
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) | |||
376 | return ret; | 376 | return ret; |
377 | } | 377 | } |
378 | 378 | ||
379 | ssize_t nilfs_dat_get_vinfo(struct inode *dat, struct nilfs_vinfo *vinfo, | 379 | ssize_t nilfs_dat_get_vinfo(struct inode *dat, void *buf, unsigned visz, |
380 | size_t nvi) | 380 | size_t nvi) |
381 | { | 381 | { |
382 | struct buffer_head *entry_bh; | 382 | struct buffer_head *entry_bh; |
383 | struct nilfs_dat_entry *entry; | 383 | struct nilfs_dat_entry *entry; |
384 | struct nilfs_vinfo *vinfo = buf; | ||
384 | __u64 first, last; | 385 | __u64 first, last; |
385 | void *kaddr; | 386 | void *kaddr; |
386 | unsigned long entries_per_block = NILFS_MDT(dat)->mi_entries_per_block; | 387 | unsigned long entries_per_block = NILFS_MDT(dat)->mi_entries_per_block; |
387 | int i, j, n, ret; | 388 | int i, j, n, ret; |
388 | 389 | ||
389 | for (i = 0; i < nvi; i += n) { | 390 | for (i = 0; i < nvi; i += n) { |
390 | ret = nilfs_palloc_get_entry_block(dat, vinfo[i].vi_vblocknr, | 391 | ret = nilfs_palloc_get_entry_block(dat, vinfo->vi_vblocknr, |
391 | 0, &entry_bh); | 392 | 0, &entry_bh); |
392 | if (ret < 0) | 393 | if (ret < 0) |
393 | return ret; | 394 | return ret; |
394 | kaddr = kmap_atomic(entry_bh->b_page, KM_USER0); | 395 | kaddr = kmap_atomic(entry_bh->b_page, KM_USER0); |
395 | /* last virtual block number in this block */ | 396 | /* last virtual block number in this block */ |
396 | first = vinfo[i].vi_vblocknr; | 397 | first = vinfo->vi_vblocknr; |
397 | do_div(first, entries_per_block); | 398 | do_div(first, entries_per_block); |
398 | first *= entries_per_block; | 399 | first *= entries_per_block; |
399 | last = first + entries_per_block - 1; | 400 | last = first + entries_per_block - 1; |
400 | for (j = i, n = 0; | 401 | for (j = i, n = 0; |
401 | j < nvi && vinfo[j].vi_vblocknr >= first && | 402 | j < nvi && vinfo->vi_vblocknr >= first && |
402 | vinfo[j].vi_vblocknr <= last; | 403 | vinfo->vi_vblocknr <= last; |
403 | j++, n++) { | 404 | j++, n++, vinfo = (void *)vinfo + visz) { |
404 | entry = nilfs_palloc_block_get_entry( | 405 | entry = nilfs_palloc_block_get_entry( |
405 | dat, vinfo[j].vi_vblocknr, entry_bh, kaddr); | 406 | dat, vinfo->vi_vblocknr, entry_bh, kaddr); |
406 | vinfo[j].vi_start = le64_to_cpu(entry->de_start); | 407 | vinfo->vi_start = le64_to_cpu(entry->de_start); |
407 | vinfo[j].vi_end = le64_to_cpu(entry->de_end); | 408 | vinfo->vi_end = le64_to_cpu(entry->de_end); |
408 | vinfo[j].vi_blocknr = le64_to_cpu(entry->de_blocknr); | 409 | vinfo->vi_blocknr = le64_to_cpu(entry->de_blocknr); |
409 | } | 410 | } |
410 | kunmap_atomic(kaddr, KM_USER0); | 411 | kunmap_atomic(kaddr, KM_USER0); |
411 | brelse(entry_bh); | 412 | brelse(entry_bh); |