summaryrefslogtreecommitdiffstats
path: root/runtime/access_process_vm.h
diff options
context:
space:
mode:
authorDave Brolley <brolley@redhat.com>2009-09-17 20:36:24 -0400
committerDave Brolley <brolley@redhat.com>2009-09-17 20:36:24 -0400
commit762684a57fa5420cc122b475f592545e8eeb29cd (patch)
treec1b55657f1aff31e7298d76852bbe8522a84db13 /runtime/access_process_vm.h
parent8afee8bbf045e858dae186d40653293c99dbbcdd (diff)
parent6bde4f381475cea055352d8ad5f60bb2f24de21d (diff)
downloadsystemtap-steved-762684a57fa5420cc122b475f592545e8eeb29cd.tar.gz
systemtap-steved-762684a57fa5420cc122b475f592545e8eeb29cd.tar.xz
systemtap-steved-762684a57fa5420cc122b475f592545e8eeb29cd.zip
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap
Diffstat (limited to 'runtime/access_process_vm.h')
-rw-r--r--runtime/access_process_vm.h54
1 files changed, 54 insertions, 0 deletions
diff --git a/runtime/access_process_vm.h b/runtime/access_process_vm.h
new file mode 100644
index 00000000..70489d48
--- /dev/null
+++ b/runtime/access_process_vm.h
@@ -0,0 +1,54 @@
+/*
+ * The kernel's access_process_vm is not exported in kernel.org kernels, although
+ * some distros export it on some architectures. To workaround this inconsistency,
+ * we copied and pasted it here. Fortunately, everything it calls is exported.
+ */
+#include <linux/pagemap.h>
+#include <asm/cacheflush.h>
+static int __access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
+{
+ struct mm_struct *mm;
+ struct vm_area_struct *vma;
+ struct page *page;
+ void *old_buf = buf;
+
+ mm = get_task_mm(tsk);
+ if (!mm)
+ return 0;
+
+ down_read(&mm->mmap_sem);
+ /* ignore errors, just check how much was sucessfully transfered */
+ while (len) {
+ int bytes, ret, offset;
+ void *maddr;
+
+ ret = get_user_pages(tsk, mm, addr, 1,
+ write, 1, &page, &vma);
+ if (ret <= 0)
+ break;
+
+ bytes = len;
+ offset = addr & (PAGE_SIZE-1);
+ if (bytes > PAGE_SIZE-offset)
+ bytes = PAGE_SIZE-offset;
+
+ maddr = kmap(page);
+ if (write) {
+ copy_to_user_page(vma, page, addr,
+ maddr + offset, buf, bytes);
+ set_page_dirty_lock(page);
+ } else {
+ copy_from_user_page(vma, page, addr,
+ buf, maddr + offset, bytes);
+ }
+ kunmap(page);
+ page_cache_release(page);
+ len -= bytes;
+ buf += bytes;
+ addr += bytes;
+ }
+ up_read(&mm->mmap_sem);
+ mmput(mm);
+
+ return buf - old_buf;
+}