📄 mmap.c
字号:
wrapfs_shift_inward(file_t *file, /* hidden file we're shifting */ off_t dst_offset, /* where to shift to (abs offset) */ off_t src_offset, /* where to shift from (abs offset) */ off_t total_bytes_to_shift){ int dst_page_index, src_page_index; unsigned int dst_page_offset, src_page_offset; page_t *dst_page, *src_page; off_t bytes_to_copy; int dst_page_bytes_left, src_page_bytes_left; char *dst_kaddr, *src_kaddr; int err = 0; struct address_space_operations *a_ops; print_entry_location(); if (total_bytes_to_shift <= 0) { printk("wrapfs_shift_inward asked to shift %ld bytes\n", total_bytes_to_shift); goto out; } /* compute page indices */ dst_page_index = dst_offset >> PAGE_CACHE_SHIFT; src_page_index = src_offset >> PAGE_CACHE_SHIFT; /* compute offsets within pages */ dst_page_offset = dst_offset & ~PAGE_CACHE_MASK; src_page_offset = src_offset & ~PAGE_CACHE_MASK; /* compute number of bytes left in pages */ dst_page_bytes_left = PAGE_CACHE_SIZE - dst_page_offset; src_page_bytes_left = PAGE_CACHE_SIZE - src_page_offset; /* get pages */ dst_page = wrapfs_get1page(file, dst_page_index); if (IS_ERR(dst_page)) { err = PTR_ERR(dst_page); goto out; } src_page = wrapfs_get1page(file, src_page_index); if (IS_ERR(src_page)) { page_cache_release(dst_page); err = PTR_ERR(src_page); goto out; } src_kaddr = (char *) kmap(src_page); a_ops = file->f_dentry->d_inode->i_mapping->a_ops; while (1) { src_page_bytes_left = MIN(src_page_bytes_left, total_bytes_to_shift); bytes_to_copy = MIN(src_page_bytes_left, dst_page_bytes_left); /* lock destination page */ lock_page(dst_page); err = a_ops->prepare_write(file, dst_page, dst_page_offset, dst_page_offset+bytes_to_copy); if (err < 0) { /* XXX: what about partial writes */ UnlockPage(dst_page); goto out_release; } dst_kaddr = (char *) page_address(dst_page); /* actually copy some bytes */ memmove(dst_kaddr + dst_page_offset, src_kaddr + src_page_offset, bytes_to_copy); err = a_ops->commit_write(file, dst_page, dst_page_offset, dst_page_offset+bytes_to_copy); UnlockPage(dst_page); if (err < 0) goto out_release; total_bytes_to_shift -= bytes_to_copy; if (total_bytes_to_shift == 0) break; /* adjust destinations as needed */ dst_page_bytes_left -= bytes_to_copy; if (dst_page_bytes_left == 0) { /* get new page */ page_cache_release(dst_page); dst_page_index++; dst_page_offset = 0; dst_page_bytes_left = PAGE_CACHE_SIZE; dst_page = wrapfs_get1page(file, dst_page_index); if (IS_ERR(dst_page)) { page_cache_release(src_page); err = PTR_ERR(dst_page); goto out; } } else { dst_page_offset += bytes_to_copy; } /* adjust sources as needed */ src_page_bytes_left -= bytes_to_copy; if (src_page_bytes_left == 0) { /* get new page */ kunmap(src_page); page_cache_release(src_page); src_page_index++; src_page_offset = 0; src_page_bytes_left = PAGE_CACHE_SIZE; src_page = wrapfs_get1page(file, src_page_index); if (IS_ERR(src_page)) { page_cache_release(dst_page); err = PTR_ERR(src_page); goto out; } src_kaddr = (char *) kmap(src_page); } else { src_page_offset += bytes_to_copy; } if (current->need_resched) schedule(); } /* end of "while (1)" */ out_release: page_cache_release(dst_page); page_cache_release(src_page); out: print_exit_status(err); return err;}/* * shift data inwards; return 0 if ok or -errno */intwrapfs_shift_outward(file_t *file, /* hidden file we're shifting */ off_t dst_offset, /* where to shift to (abs offset) */ off_t src_offset, /* where to shift from (abs offset) */ off_t total_bytes_to_shift){ int dst_page_index, src_page_index; unsigned int dst_page_offset, src_page_offset; page_t *dst_page, *src_page; off_t bytes_to_copy; int dst_page_bytes_left, src_page_bytes_left; char *dst_kaddr, *src_kaddr; int err = 0; struct address_space_operations *a_ops; print_entry_location(); fist_dprint(8, "%s args: dst_off=%d, src_off=%d, bytes=%d\n", __FUNCTION__, dst_offset, src_offset, total_bytes_to_shift); if (total_bytes_to_shift <= 0) { printk("wrapfs_shift_outward asked to shift %ld bytes\n", total_bytes_to_shift); goto out; } /* compute page indices */ dst_page_index = (dst_offset + total_bytes_to_shift) >> PAGE_CACHE_SHIFT; src_page_index = (src_offset + total_bytes_to_shift) >> PAGE_CACHE_SHIFT; /* compute offsets within pages */ dst_page_offset = (dst_offset + total_bytes_to_shift) & ~PAGE_CACHE_MASK; src_page_offset = (src_offset + total_bytes_to_shift) & ~PAGE_CACHE_MASK; /* compute number of bytes left in pages */ dst_page_bytes_left = dst_page_offset; src_page_bytes_left = src_page_offset; fist_dprint(8, "%s dst: index=%d, offset=%d, bytesleft=%d\n", __FUNCTION__, dst_page_index, dst_page_offset, dst_page_bytes_left); fist_dprint(8, "%s src: index=%d, offset=%d, bytesleft=%d\n", __FUNCTION__, src_page_index, src_page_offset, src_page_bytes_left); /* get pages */ dst_page = wrapfs_get1page(file, dst_page_index); if (IS_ERR(dst_page)) { err = PTR_ERR(dst_page); goto out; } src_page = wrapfs_get1page(file, src_page_index); if (IS_ERR(src_page)) { page_cache_release(dst_page); err = PTR_ERR(src_page); goto out; } src_kaddr = (char *) kmap(src_page); a_ops = file->f_dentry->d_inode->i_mapping->a_ops; while (1) { src_page_bytes_left = MIN(src_page_bytes_left, total_bytes_to_shift); bytes_to_copy = MIN(src_page_bytes_left, dst_page_bytes_left); dst_page_offset -= bytes_to_copy; src_page_offset -= bytes_to_copy; /* lock destination page */ lock_page(dst_page); err = a_ops->prepare_write(file, dst_page, dst_page_offset, dst_page_offset+bytes_to_copy); if (err < 0) { /* XXX: what about partial writes */ UnlockPage(dst_page); goto out_release; } dst_kaddr = (char *) page_address(dst_page); /* actually copy some bytes */ memmove(dst_kaddr + dst_page_offset, src_kaddr + src_page_offset, bytes_to_copy); err = a_ops->commit_write(file, dst_page, dst_page_offset, dst_page_offset+bytes_to_copy); UnlockPage(dst_page); if (err < 0) goto out_release; total_bytes_to_shift -= bytes_to_copy; if (total_bytes_to_shift == 0) break; /* adjust destinations as needed */ dst_page_bytes_left -= bytes_to_copy; if (dst_page_bytes_left == 0) { /* get new page */ page_cache_release(dst_page); dst_page_index--; dst_page_offset = PAGE_CACHE_SIZE; dst_page_bytes_left = PAGE_CACHE_SIZE; fist_dprint(8, "%s dst: index=%d, offset=%d, bytesleft=%d\n", __FUNCTION__, dst_page_index, dst_page_offset, dst_page_bytes_left); dst_page = wrapfs_get1page(file, dst_page_index); if (IS_ERR(dst_page)) { page_cache_release(src_page); err = PTR_ERR(dst_page); goto out; } } /* adjust sources as needed */ src_page_bytes_left -= bytes_to_copy; if (src_page_bytes_left == 0) { /* get new page */ page_cache_release(src_page); src_page_index--; src_page_offset = PAGE_CACHE_SIZE; src_page_bytes_left = PAGE_CACHE_SIZE; fist_dprint(8, "%s src: index=%d, offset=%d, bytesleft=%d\n", __FUNCTION__, src_page_index, src_page_offset, src_page_bytes_left); src_page = wrapfs_get1page(file, src_page_index); if (IS_ERR(src_page)) { page_cache_release(dst_page); err = PTR_ERR(src_page); goto out; } src_kaddr = (char *) kmap(src_page); } if (current->need_resched) schedule(); } /* end of "while (1)" */ out_release: page_cache_release(dst_page); page_cache_release(src_page); out: print_exit_status(err); return err;}/* * copy data bytes; return 0 if ok or -errno */intwrapfs_copy_encoded_data(file_t *file, /* hidden file */ off_t dst_offset, /* where to copy to (abs offset) */ encoded_pages_t *encoded_pages, off_t total_bytes_to_copy){ int dst_page_index; unsigned int dst_page_offset, src_page_offset; page_t *dst_page; off_t bytes_to_copy; int dst_page_bytes_left, src_page_bytes_left; char *dst_kaddr, *src_kaddr; int err = 0; struct address_space_operations *a_ops; print_entry_location(); // XXX: check errors // printk("EZK0: total_bytes_to_copy 0x%x\n", (int) total_bytes_to_copy); /* compute page indices */ dst_page_index = dst_offset >> PAGE_CACHE_SHIFT; /* compute offsets within pages */ dst_page_offset = dst_offset & ~PAGE_CACHE_MASK; src_page_offset = 0; /* compute number of bytes left in pages */ dst_page_bytes_left = PAGE_CACHE_SIZE - dst_page_offset; src_page_bytes_left = PAGE_CACHE_SIZE; /* adjusted below */ /* get pages */ dst_page = wrapfs_get1page(file, dst_page_index); if (IS_ERR(dst_page)) { err = PTR_ERR(dst_page); goto out; } /* map pages into kernel addresses */ src_kaddr = encoded_pages->data; a_ops = file->f_dentry->d_inode->i_mapping->a_ops; while (1) { src_page_bytes_left = MIN(src_page_bytes_left, total_bytes_to_copy); bytes_to_copy = MIN(src_page_bytes_left, dst_page_bytes_left); /* lock destination page */ lock_page(dst_page); err = a_ops->prepare_write(file, dst_page, dst_page_offset, dst_page_offset + bytes_to_copy); if (err < 0) { /* XXX: what about partial writes */ UnlockPage(dst_page); goto out_release; } dst_kaddr = (char *) page_address(dst_page); /* actually copy some bytes */ memmove(dst_kaddr + dst_page_offset, src_kaddr + src_page_offset, bytes_to_copy); err = a_ops->commit_write(file, dst_page, dst_page_offset, dst_page_offset + bytes_to_copy); UnlockPage(dst_page); if (err < 0) goto out_release; total_bytes_to_copy -= bytes_to_copy; // printk("EZK1: total_bytes_to_copy 0x%x\n", (int) total_bytes_to_copy); if (total_bytes_to_copy == 0) break; /* adjust destinations as needed */ dst_page_bytes_left -= bytes_to_copy; if (dst_page_bytes_left == 0) { /* get new page */ page_cache_release(dst_page); dst_page_index++; dst_page_offset = 0; dst_page_bytes_left = PAGE_CACHE_SIZE; dst_page = wrapfs_get1page(file, dst_page_index); if (IS_ERR(dst_page)) { err = PTR_ERR(dst_page); goto out; } } else { dst_page_offset += bytes_to_copy; } /* adjust sources as needed */ src_page_bytes_left -= bytes_to_copy; if (src_page_bytes_left == 0) { /* get new page */ src_page_offset = 0; src_page_bytes_left = PAGE_CACHE_SIZE; encoded_pages = encoded_pages->next; src_kaddr = encoded_pages->data; } else { src_page_offset += bytes_to_copy; } if (current->need_resched) schedule(); } /* end of "while (1)" */ out_release: page_cache_release(dst_page); out: print_exit_status(err); return err;}STATIC intwrapfs_commit_write(file_t *file, page_t *page, unsigned from, unsigned to){ int err; inode_t *inode; inode_t *hidden_inode; file_t *hidden_file = NULL; loff_t pos = 0; struct encoded_page *ep = NULL, *next_ep, **cur_ep; unsigned real_to, hidden_size, page_offset; struct iattr attr; void *opaque = NULL; off_t old_hidden_size, hidden_offset, old_hidden_offset, delta; dentry_t *hidden_dentry; struct scafs_header *hdr; int need_to_call = 1; print_entry_location(); inode = page->mapping->host;/* CPW: Moved below print_entry_location */ hidden_inode = itohi(inode); ASSERT(file != NULL); hidden_file = ftohf(file); hidden_dentry = hidden_file->f_dentry; down(&hidden_inode->i_sem); /* * here we have a kmapped page, with data from the user copied * into it. we need to encode_block it, and then call the lower * commit_write. We also need to simulate same behavior of * generic_file_write, and call prepare_write on the lower f/s first. */# ifdef FIST_COUNT_WRITES count_writes++;# endif /* FIST_COUNT_WRITES */ hdr = &itopd(inode)->hdr; page_offset = page->index << PAGE_CACHE_SHIFT; if (inode->i_size > page_offset + to) if (inode->i_size > page_offset + PAGE_CACHE_SIZE) real_to = PAGE_CACHE_SIZE; else real_to = inode->i_size - page_offset; else real_to = to; hidden_size = 0; cur_ep = &ep; while (need_to_call) { *cur_ep = kmalloc(sizeof(struct encoded_page), GFP_KERNEL); if (!*cur_ep) { err = -ENOMEM; goto out_free; } (*cur_ep)->data = (char *) __get_free_page(GFP_KERNEL);#ifdef FIST_FAST_TAILS if (CAN_BE_FASTTAIL_PAGE(real_to, inode) && page->index + 1 >= hdr->num_chunks) { memcpy((*cur_ep)->data, (char *) page_address(page), real_to); need_to_call = 0; err = real_to; hdr->flags |= SCA_FLAG_FASTTAIL; } else#endif /* FIST_FAST_TAILS */ { err = wrapfs_encode_buffers((*cur_ep)->data, (char *) page_address(page), &need_to_call, real_to, inode, inode->i_sb, &opaque); if (page->index + 1 >= hdr->num_chunks) hdr->flags &= ~SCA_FLAG_FASTTAIL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -