proc/pid/mem: implement SEEK_DATA and SEEK_HOLE
Subsystems (2)
RFC PATCH 1/1 proc/pid/mem: implement SEEK_DATA and SEEK_HOLE
lseek(fd, addr, SEEK_DATA) adjust file offset to the start address of next VMA, or to addr if this address is allocated.
lseek(fd, addr, SEEK_HOLE) adjust file offset to the end address of VMA which addr belongs to, or to addr itself if there is hole.
This way SEEK_HOLE reports a virtual zero-length hole between each contiguous VMAs. This hack seems completely legit and allows to simplify implementation (there is no function for finding next hole in VMAs' tree, walking along
->vm_next might be expensive) This also gives more information about layout.
---
I have no practical use for this, just found this interesting.
--- fs/proc/base.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-)
fs/proc/base.c +29 -2
@@ -769,13 +769,40 @@ static ssize_t mem_write(struct file *file, const char __user *buf,loff_t mem_lseek (struct file *file,loff_t offset,int orig) { +struct mm_struct *mm = file->private_data; +struct vm_area_struct *vma; +switch (orig) { -case 0 : +case SEEK_SET : file->f_pos = offset;break ; -case 1 : +case SEEK_CUR : file->f_pos += offset;break ; +case SEEK_DATA : +case SEEK_HOLE : +if (!mm || !atomic_inc_not_zero (&mm->mm_users)) +return -ENXIO ; +down_read (&mm->mmap_sem); + vma =find_vma (mm, offset); +if (vma) { +if (orig ==SEEK_DATA ) { +if (offset >= vma->vm_start) + file->f_pos = offset; +else + file->f_pos = vma->vm_start; + }else { +if (offset < vma->vm_start) + file->f_pos = offset; +else + file->f_pos = vma->vm_end; + } + } +up_read (&mm->mmap_sem); +mmput (mm); +if (!vma) +return -ENXIO ; +break ;default :return -EINVAL ; }
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>