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>
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user