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