本文整理汇总了C++中page_cache_release函数的典型用法代码示例。如果您正苦于以下问题:C++ page_cache_release函数的具体用法?C++ page_cache_release怎么用?C++ page_cache_release使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了page_cache_release函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: try_to_swap_out
/* mm->page_table_lock is held. mmap_sem is not held */
static inline int try_to_swap_out(struct mm_struct * mm, struct vm_area_struct* vma, unsigned long address, pte_t * page_table, struct page *page, zone_t * classzone)
{
pte_t pte;
swp_entry_t entry;
/* Don't look at this pte if it's been accessed recently. */
if ((vma->vm_flags & VM_LOCKED) || ptep_test_and_clear_young(page_table)) {
mark_page_accessed(page);
return 0;
}
/* Don't bother unmapping pages that are active */
if (PageActive(page))
return 0;
/* Don't bother replenishing zones not under pressure.. */
if (!memclass(page_zone(page), classzone))
return 0;
if (TryLockPage(page))
return 0;
/* From this point on, the odds are that we're going to
* nuke this pte, so read and clear the pte. This hook
* is needed on CPUs which update the accessed and dirty
* bits in hardware.
*/
flush_cache_page(vma, address);
pte = ptep_get_and_clear(page_table);
flush_tlb_page(vma, address);
if (pte_dirty(pte))
set_page_dirty(page);
/*
* Is the page already in the swap cache? If so, then
* we can just drop our reference to it without doing
* any IO - it's already up-to-date on disk.
*/
if (PageSwapCache(page)) {
entry.val = page->index;
swap_duplicate(entry);
set_swap_pte:
set_pte(page_table, swp_entry_to_pte(entry));
drop_pte:
mm->rss--;
UnlockPage(page);
{
int freeable = page_count(page) - !!page->buffers <= 2;
page_cache_release(page);
return freeable;
}
}
/*
* Is it a clean page? Then it must be recoverable
* by just paging it in again, and we can just drop
* it.. or if it's dirty but has backing store,
* just mark the page dirty and drop it.
*
* However, this won't actually free any real
* memory, as the page will just be in the page cache
* somewhere, and as such we should just continue
* our scan.
*
* Basically, this just makes it possible for us to do
* some real work in the future in "refill_inactive()".
*/
if (page->mapping)
goto drop_pte;
if (!PageDirty(page))
goto drop_pte;
/*
* Anonymous buffercache pages can be left behind by
* concurrent truncate and pagefault.
*/
if (page->buffers)
goto preserve;
/*
* This is a dirty, swappable page. First of all,
* get a suitable swap entry for it, and make sure
* we have the swap cache set up to associate the
* page with that swap entry.
*/
for (;;) {
entry = get_swap_page();
if (!entry.val)
break;
/* Add it to the swap cache and mark it dirty
* (adding to the page cache will clear the dirty
* and uptodate bits, so we need to do it again)
*/
if (add_to_swap_cache(page, entry) == 0) {
SetPageUptodate(page);
set_page_dirty(page);
goto set_swap_pte;
}
//.........这里部分代码省略.........
示例2: nilfs_rename
static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
struct inode *old_inode = d_inode(old_dentry);
struct inode *new_inode = d_inode(new_dentry);
struct page *dir_page = NULL;
struct nilfs_dir_entry *dir_de = NULL;
struct page *old_page;
struct nilfs_dir_entry *old_de;
struct nilfs_transaction_info ti;
int err;
err = nilfs_transaction_begin(old_dir->i_sb, &ti, 1);
if (unlikely(err))
return err;
err = -ENOENT;
old_de = nilfs_find_entry(old_dir, &old_dentry->d_name, &old_page);
if (!old_de)
goto out;
if (S_ISDIR(old_inode->i_mode)) {
err = -EIO;
dir_de = nilfs_dotdot(old_inode, &dir_page);
if (!dir_de)
goto out_old;
}
if (new_inode) {
struct page *new_page;
struct nilfs_dir_entry *new_de;
err = -ENOTEMPTY;
if (dir_de && !nilfs_empty_dir(new_inode))
goto out_dir;
err = -ENOENT;
new_de = nilfs_find_entry(new_dir, &new_dentry->d_name, &new_page);
if (!new_de)
goto out_dir;
nilfs_set_link(new_dir, new_de, new_page, old_inode);
nilfs_mark_inode_dirty(new_dir);
new_inode->i_ctime = CURRENT_TIME;
if (dir_de)
drop_nlink(new_inode);
drop_nlink(new_inode);
nilfs_mark_inode_dirty(new_inode);
} else {
err = nilfs_add_link(new_dentry, old_inode);
if (err)
goto out_dir;
if (dir_de) {
inc_nlink(new_dir);
nilfs_mark_inode_dirty(new_dir);
}
}
/*
* Like most other Unix systems, set the ctime for inodes on a
* rename.
*/
old_inode->i_ctime = CURRENT_TIME;
nilfs_delete_entry(old_de, old_page);
if (dir_de) {
nilfs_set_link(old_inode, dir_de, dir_page, new_dir);
drop_nlink(old_dir);
}
nilfs_mark_inode_dirty(old_dir);
nilfs_mark_inode_dirty(old_inode);
err = nilfs_transaction_commit(old_dir->i_sb);
return err;
out_dir:
if (dir_de) {
kunmap(dir_page);
page_cache_release(dir_page);
}
out_old:
kunmap(old_page);
page_cache_release(old_page);
out:
nilfs_transaction_abort(old_dir->i_sb);
return err;
}
示例3: zswap_writeback_entry
/*
* Attempts to free an entry by adding a page to the swap cache,
* decompressing the entry data into the page, and issuing a
* bio write to write the page back to the swap device.
*
* This can be thought of as a "resumed writeback" of the page
* to the swap device. We are basically resuming the same swap
* writeback path that was intercepted with the frontswap_store()
* in the first place. After the page has been decompressed into
* the swap cache, the compressed version stored by zswap can be
* freed.
*/
static int zswap_writeback_entry(struct zpool *pool, unsigned long handle)
{
struct zswap_header *zhdr;
swp_entry_t swpentry;
struct zswap_tree *tree;
pgoff_t offset;
struct zswap_entry *entry;
struct page *page;
u8 *src, *dst;
unsigned int dlen;
int ret;
struct writeback_control wbc = {
.sync_mode = WB_SYNC_NONE,
};
/* extract swpentry from data */
zhdr = zpool_map_handle(pool, handle, ZPOOL_MM_RO);
swpentry = zhdr->swpentry; /* here */
zpool_unmap_handle(pool, handle);
tree = zswap_trees[swp_type(swpentry)];
offset = swp_offset(swpentry);
/* find and ref zswap entry */
spin_lock(&tree->lock);
entry = zswap_entry_find_get(&tree->rbroot, offset);
if (!entry) {
/* entry was invalidated */
spin_unlock(&tree->lock);
return 0;
}
spin_unlock(&tree->lock);
BUG_ON(offset != entry->offset);
/* try to allocate swap cache page */
switch (zswap_get_swap_cache_page(swpentry, &page)) {
case ZSWAP_SWAPCACHE_FAIL: /* no memory or invalidate happened */
ret = -ENOMEM;
goto fail;
case ZSWAP_SWAPCACHE_EXIST:
/* page is already in the swap cache, ignore for now */
page_cache_release(page);
ret = -EEXIST;
goto fail;
case ZSWAP_SWAPCACHE_NEW: /* page is locked */
/* decompress */
dlen = PAGE_SIZE;
src = (u8 *)zpool_map_handle(zswap_pool, entry->handle,
ZPOOL_MM_RO) + sizeof(struct zswap_header);
dst = kmap_atomic(page);
ret = zswap_comp_op(ZSWAP_COMPOP_DECOMPRESS, src,
entry->length, dst, &dlen);
kunmap_atomic(dst);
zpool_unmap_handle(zswap_pool, entry->handle);
BUG_ON(ret);
BUG_ON(dlen != PAGE_SIZE);
/* page is up to date */
SetPageUptodate(page);
}
/* move it to the tail of the inactive list after end_writeback */
SetPageReclaim(page);
/* start writeback */
__swap_writepage(page, &wbc, end_swap_bio_write);
page_cache_release(page);
zswap_written_back_pages++;
spin_lock(&tree->lock);
/* drop local reference */
zswap_entry_put(tree, entry);
/*
* There are two possible situations for entry here:
* (1) refcount is 1(normal case), entry is valid and on the tree
* (2) refcount is 0, entry is freed and not on the tree
* because invalidate happened during writeback
* search the tree and free the entry if find entry
*/
if (entry == zswap_rb_search(&tree->rbroot, offset))
zswap_entry_put(tree, entry);
spin_unlock(&tree->lock);
goto end;
/*
//.........这里部分代码省略.........
示例4: mcopy_atomic_pte
static int mcopy_atomic_pte(struct mm_struct *dst_mm,
pmd_t *dst_pmd,
struct vm_area_struct *dst_vma,
unsigned long dst_addr,
unsigned long src_addr,
struct page **pagep)
{
struct mem_cgroup *memcg;
pte_t _dst_pte, *dst_pte;
spinlock_t *ptl;
void *page_kaddr;
int ret;
struct page *page;
if (!*pagep) {
ret = -ENOMEM;
page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, dst_vma, dst_addr);
if (!page)
goto out;
page_kaddr = kmap_atomic(page);
ret = copy_from_user(page_kaddr,
(const void __user *) src_addr,
PAGE_SIZE);
kunmap_atomic(page_kaddr);
/* fallback to copy_from_user outside mmap_sem */
if (unlikely(ret)) {
ret = -EFAULT;
*pagep = page;
/* don't free the page */
goto out;
}
} else {
page = *pagep;
*pagep = NULL;
}
/*
* The memory barrier inside __SetPageUptodate makes sure that
* preceeding stores to the page contents become visible before
* the set_pte_at() write.
*/
__SetPageUptodate(page);
ret = -ENOMEM;
if (mem_cgroup_try_charge(page, dst_mm, GFP_KERNEL, &memcg, false))
goto out_release;
_dst_pte = mk_pte(page, dst_vma->vm_page_prot);
if (dst_vma->vm_flags & VM_WRITE)
_dst_pte = pte_mkwrite(pte_mkdirty(_dst_pte));
ret = -EEXIST;
dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl);
if (!pte_none(*dst_pte))
goto out_release_uncharge_unlock;
inc_mm_counter(dst_mm, MM_ANONPAGES);
page_add_new_anon_rmap(page, dst_vma, dst_addr, false);
mem_cgroup_commit_charge(page, memcg, false, false);
lru_cache_add_active_or_unevictable(page, dst_vma);
set_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte);
/* No need to invalidate - it was non-present before */
update_mmu_cache(dst_vma, dst_addr, dst_pte);
pte_unmap_unlock(dst_pte, ptl);
ret = 0;
out:
return ret;
out_release_uncharge_unlock:
pte_unmap_unlock(dst_pte, ptl);
mem_cgroup_cancel_charge(page, memcg, false);
out_release:
page_cache_release(page);
goto out;
}
示例5: ext4_da_write_inline_data_begin
/*
* Prepare the write for the inline data.
* If the the data can be written into the inode, we just read
* the page and make it uptodate, and start the journal.
* Otherwise read the page, makes it dirty so that it can be
* handle in writepages(the i_disksize update is left to the
* normal ext4_da_write_end).
*/
int ext4_da_write_inline_data_begin(struct address_space *mapping,
struct inode *inode,
loff_t pos, unsigned len,
unsigned flags,
struct page **pagep,
void **fsdata)
{
int ret, inline_size;
handle_t *handle;
struct page *page;
struct ext4_iloc iloc;
ret = ext4_get_inode_loc(inode, &iloc);
if (ret)
return ret;
handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
if (IS_ERR(handle)) {
ret = PTR_ERR(handle);
handle = NULL;
goto out;
}
inline_size = ext4_get_max_inline_size(inode);
ret = -ENOSPC;
if (inline_size >= pos + len) {
ret = ext4_prepare_inline_data(handle, inode, pos + len);
if (ret && ret != -ENOSPC)
goto out;
}
if (ret == -ENOSPC) {
ret = ext4_da_convert_inline_data_to_extent(mapping,
inode,
flags,
fsdata);
goto out;
}
/*
* We cannot recurse into the filesystem as the transaction
* is already started.
*/
flags |= AOP_FLAG_NOFS;
page = grab_cache_page_write_begin(mapping, 0, flags);
if (!page) {
ret = -ENOMEM;
goto out;
}
down_read(&EXT4_I(inode)->xattr_sem);
if (!ext4_has_inline_data(inode)) {
ret = 0;
goto out_release_page;
}
if (!PageUptodate(page)) {
ret = ext4_read_inline_page(inode, page);
if (ret < 0)
goto out_release_page;
}
up_read(&EXT4_I(inode)->xattr_sem);
*pagep = page;
handle = NULL;
brelse(iloc.bh);
return 1;
out_release_page:
up_read(&EXT4_I(inode)->xattr_sem);
unlock_page(page);
page_cache_release(page);
out:
if (handle)
ext4_journal_stop(handle);
brelse(iloc.bh);
return ret;
}
示例6: rtR0MemObjNativeLockUser
int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
{
const int cPages = cb >> PAGE_SHIFT;
struct task_struct *pTask = rtR0ProcessToLinuxTask(R0Process);
struct vm_area_struct **papVMAs;
PRTR0MEMOBJLNX pMemLnx;
int rc = VERR_NO_MEMORY;
NOREF(fAccess);
/*
* Check for valid task and size overflows.
*/
if (!pTask)
return VERR_NOT_SUPPORTED;
if (((size_t)cPages << PAGE_SHIFT) != cb)
return VERR_OUT_OF_RANGE;
/*
* Allocate the memory object and a temporary buffer for the VMAs.
*/
pMemLnx = (PRTR0MEMOBJLNX)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJLNX, apPages[cPages]), RTR0MEMOBJTYPE_LOCK, (void *)R3Ptr, cb);
if (!pMemLnx)
return VERR_NO_MEMORY;
papVMAs = (struct vm_area_struct **)RTMemAlloc(sizeof(*papVMAs) * cPages);
if (papVMAs)
{
down_read(&pTask->mm->mmap_sem);
/*
* Get user pages.
*/
rc = get_user_pages(pTask, /* Task for fault acounting. */
pTask->mm, /* Whose pages. */
R3Ptr, /* Where from. */
cPages, /* How many pages. */
1, /* Write to memory. */
0, /* force. */
&pMemLnx->apPages[0], /* Page array. */
papVMAs); /* vmas */
if (rc == cPages)
{
/*
* Flush dcache (required?), protect against fork and _really_ pin the page
* table entries. get_user_pages() will protect against swapping out the
* pages but it will NOT protect against removing page table entries. This
* can be achieved with
* - using mlock / mmap(..., MAP_LOCKED, ...) from userland. This requires
* an appropriate limit set up with setrlimit(..., RLIMIT_MEMLOCK, ...).
* Usual Linux distributions support only a limited size of locked pages
* (e.g. 32KB).
* - setting the PageReserved bit (as we do in rtR0MemObjLinuxAllocPages()
* or by
* - setting the VM_LOCKED flag. This is the same as doing mlock() without
* a range check.
*/
/** @todo The Linux fork() protection will require more work if this API
* is to be used for anything but locking VM pages. */
while (rc-- > 0)
{
flush_dcache_page(pMemLnx->apPages[rc]);
papVMAs[rc]->vm_flags |= (VM_DONTCOPY | VM_LOCKED);
}
up_read(&pTask->mm->mmap_sem);
RTMemFree(papVMAs);
pMemLnx->Core.u.Lock.R0Process = R0Process;
pMemLnx->cPages = cPages;
Assert(!pMemLnx->fMappedToRing0);
*ppMem = &pMemLnx->Core;
return VINF_SUCCESS;
}
/*
* Failed - we need to unlock any pages that we succeeded to lock.
*/
while (rc-- > 0)
{
if (!PageReserved(pMemLnx->apPages[rc]))
SetPageDirty(pMemLnx->apPages[rc]);
page_cache_release(pMemLnx->apPages[rc]);
}
up_read(&pTask->mm->mmap_sem);
RTMemFree(papVMAs);
rc = VERR_LOCK_FAILED;
}
rtR0MemObjDelete(&pMemLnx->Core);
return rc;
}
示例7: j4fs_write_begin
int j4fs_write_begin(struct file *filp, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata)
{
struct page *pg = NULL;
pgoff_t index = pos >> PAGE_CACHE_SHIFT;
uint32_t offset = pos & (PAGE_CACHE_SIZE - 1);
uint32_t to = offset + len;
int ret = 0;
int space_held = 0;
if(j4fs_panic==1) {
T(J4FS_TRACE_ALWAYS,("%s %d: j4fs panic\n",__FUNCTION__,__LINE__));
return -ENOSPC;
}
T(J4FS_TRACE_FS, ("start j4fs_write_begin\n"));
if(to>PAGE_CACHE_SIZE) {
T(J4FS_TRACE_ALWAYS,("%s %d: page size overflow(pos,index,offset,len,to)=(%d,%d,%d,%d,%d)\n",__FUNCTION__,__LINE__,pos,index,offset,len,to));
j4fs_panic("page size overflow");
return -ENOSPC;
}
/* Get a page */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
pg = grab_cache_page_write_begin(mapping, index, flags);
#else
pg = __grab_cache_page(mapping, index);
#endif
*pagep = pg;
if (!pg) {
ret = -ENOMEM;
goto out;
}
/* Get fs space */
space_held = j4fs_hold_space(PAGE_CACHE_SIZE);
if (!space_held) {
ret = -ENOSPC;
goto out;
}
/* Update page if required */
if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
ret = j4fs_readpage_nolock(filp, pg);
if (ret)
goto out;
/* Happy path return */
T(J4FS_TRACE_FS, ("end j4fs_write_begin - ok\n"));
return 0;
out:
T(J4FS_TRACE_FS, ("end j4fs_write_begin fail returning %d\n", ret));
if (pg) {
unlock_page(pg);
page_cache_release(pg);
}
return ret;
}
示例8: find_get_page
/*
* Locate a page of swap in physical memory, reserving swap cache space
* and reading the disk if it is not already cached.
* A failure return means that either the page allocation failed or that
* the swap entry is no longer in use.
*/
struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
struct vm_area_struct *vma, unsigned long addr)
{
struct page *found_page, *new_page = NULL;
int err;
do {
/*
* First check the swap cache. Since this is normally
* called after lookup_swap_cache() failed, re-calling
* that would confuse statistics.
*/
found_page = find_get_page(&swapper_space, entry.val);
if (found_page)
break;
/*
* Get a new page to read into from swap.
*/
if (!new_page) {
new_page = alloc_page_vma(gfp_mask, vma, addr);
if (!new_page)
break; /* Out of memory */
}
/*
* call radix_tree_preload() while we can wait.
*/
err = radix_tree_preload(gfp_mask & GFP_KERNEL);
if (err)
break;
/*
* Swap entry may have been freed since our caller observed it.
*/
err = swapcache_prepare(entry);
if (err == -EEXIST) {
radix_tree_preload_end();
/*
* We might race against get_swap_page() and stumble
* across a SWAP_HAS_CACHE swap_map entry whose page
* has not been brought into the swapcache yet, while
* the other end is scheduled away waiting on discard
* I/O completion at scan_swap_map().
*
* In order to avoid turning this transitory state
* into a permanent loop around this -EEXIST case
* if !CONFIG_PREEMPT and the I/O completion happens
* to be waiting on the CPU waitqueue where we are now
* busy looping, we just conditionally invoke the
* scheduler here, if there are some more important
* tasks to run.
*/
cond_resched();
continue;
}
if (err) { /* swp entry is obsolete ? */
radix_tree_preload_end();
break;
}
/* May fail (-ENOMEM) if radix-tree node allocation failed. */
__set_page_locked(new_page);
SetPageSwapBacked(new_page);
err = __add_to_swap_cache(new_page, entry);
if (likely(!err)) {
radix_tree_preload_end();
/*
* Initiate read into locked page and return.
*/
lru_cache_add_anon(new_page);
swap_readpage(new_page);
return new_page;
}
radix_tree_preload_end();
ClearPageSwapBacked(new_page);
__clear_page_locked(new_page);
/*
* add_to_swap_cache() doesn't return -EEXIST, so we can safely
* clear SWAP_HAS_CACHE flag.
*/
swapcache_free(entry, NULL);
} while (err != -ENOMEM);
if (new_page)
page_cache_release(new_page);
return found_page;
}
示例9: rtR0MemObjNativeFree
int rtR0MemObjNativeFree(RTR0MEMOBJ pMem)
{
PRTR0MEMOBJLNX pMemLnx = (PRTR0MEMOBJLNX)pMem;
/*
* Release any memory that we've allocated or locked.
*/
switch (pMemLnx->Core.enmType)
{
case RTR0MEMOBJTYPE_LOW:
case RTR0MEMOBJTYPE_PAGE:
case RTR0MEMOBJTYPE_CONT:
case RTR0MEMOBJTYPE_PHYS:
case RTR0MEMOBJTYPE_PHYS_NC:
rtR0MemObjLinuxVUnmap(pMemLnx);
rtR0MemObjLinuxFreePages(pMemLnx);
break;
case RTR0MEMOBJTYPE_LOCK:
if (pMemLnx->Core.u.Lock.R0Process != NIL_RTR0PROCESS)
{
struct task_struct *pTask = rtR0ProcessToLinuxTask(pMemLnx->Core.u.Lock.R0Process);
size_t iPage;
Assert(pTask);
if (pTask && pTask->mm)
down_read(&pTask->mm->mmap_sem);
iPage = pMemLnx->cPages;
while (iPage-- > 0)
{
if (!PageReserved(pMemLnx->apPages[iPage]))
SetPageDirty(pMemLnx->apPages[iPage]);
page_cache_release(pMemLnx->apPages[iPage]);
}
if (pTask && pTask->mm)
up_read(&pTask->mm->mmap_sem);
}
/* else: kernel memory - nothing to do here. */
break;
case RTR0MEMOBJTYPE_RES_VIRT:
Assert(pMemLnx->Core.pv);
if (pMemLnx->Core.u.ResVirt.R0Process != NIL_RTR0PROCESS)
{
struct task_struct *pTask = rtR0ProcessToLinuxTask(pMemLnx->Core.u.Lock.R0Process);
Assert(pTask);
if (pTask && pTask->mm)
{
MY_DO_MUNMAP(pTask->mm, (unsigned long)pMemLnx->Core.pv, pMemLnx->Core.cb);
}
}
else
{
vunmap(pMemLnx->Core.pv);
Assert(pMemLnx->cPages == 1 && pMemLnx->apPages[0] != NULL);
__free_page(pMemLnx->apPages[0]);
pMemLnx->apPages[0] = NULL;
pMemLnx->cPages = 0;
}
pMemLnx->Core.pv = NULL;
break;
case RTR0MEMOBJTYPE_MAPPING:
Assert(pMemLnx->cPages == 0); Assert(pMemLnx->Core.pv);
if (pMemLnx->Core.u.ResVirt.R0Process != NIL_RTR0PROCESS)
{
struct task_struct *pTask = rtR0ProcessToLinuxTask(pMemLnx->Core.u.Lock.R0Process);
Assert(pTask);
if (pTask && pTask->mm)
{
MY_DO_MUNMAP(pTask->mm, (unsigned long)pMemLnx->Core.pv, pMemLnx->Core.cb);
}
}
else
vunmap(pMemLnx->Core.pv);
pMemLnx->Core.pv = NULL;
break;
default:
AssertMsgFailed(("enmType=%d\n", pMemLnx->Core.enmType));
return VERR_INTERNAL_ERROR;
}
return VINF_SUCCESS;
}
示例10: nilfs_btnode_submit_block
int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
sector_t pblocknr, struct buffer_head **pbh,
int newblk)
{
struct buffer_head *bh;
struct inode *inode = NILFS_BTNC_I(btnc);
int err;
bh = nilfs_grab_buffer(inode, btnc, blocknr, 1 << BH_NILFS_Node);
if (unlikely(!bh))
return -ENOMEM;
err = -EEXIST; /* internal code */
if (newblk) {
if (unlikely(buffer_mapped(bh) || buffer_uptodate(bh) ||
buffer_dirty(bh))) {
brelse(bh);
BUG();
}
memset(bh->b_data, 0, 1 << inode->i_blkbits);
bh->b_bdev = NILFS_I_NILFS(inode)->ns_bdev;
bh->b_blocknr = blocknr;
set_buffer_mapped(bh);
set_buffer_uptodate(bh);
goto found;
}
if (buffer_uptodate(bh) || buffer_dirty(bh))
goto found;
if (pblocknr == 0) {
pblocknr = blocknr;
if (inode->i_ino != NILFS_DAT_INO) {
struct inode *dat =
nilfs_dat_inode(NILFS_I_NILFS(inode));
/* blocknr is a virtual block number */
err = nilfs_dat_translate(dat, blocknr, &pblocknr);
if (unlikely(err)) {
brelse(bh);
goto out_locked;
}
}
}
lock_buffer(bh);
if (buffer_uptodate(bh)) {
unlock_buffer(bh);
err = -EEXIST; /* internal code */
goto found;
}
set_buffer_mapped(bh);
bh->b_bdev = NILFS_I_NILFS(inode)->ns_bdev;
bh->b_blocknr = pblocknr; /* set block address for read */
bh->b_end_io = end_buffer_read_sync;
get_bh(bh);
submit_bh(READ, bh);
bh->b_blocknr = blocknr; /* set back to the given block address */
err = 0;
found:
*pbh = bh;
out_locked:
unlock_page(bh->b_page);
page_cache_release(bh->b_page);
return err;
}
示例11: smb_fill_cache
/*
* Create dentry/inode for this file and add it to the dircache.
*/
int
smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
struct smb_cache_control *ctrl, struct qstr *qname,
struct smb_fattr *entry)
{
struct dentry *newdent, *dentry = filp->f_dentry;
struct inode *newino, *inode = dentry->d_inode;
struct smb_cache_control ctl = *ctrl;
int valid = 0;
int hashed = 0;
ino_t ino = 0;
qname->hash = full_name_hash(qname->name, qname->len);
if (dentry->d_op && dentry->d_op->d_hash)
if (dentry->d_op->d_hash(dentry, qname) != 0)
goto end_advance;
newdent = d_lookup(dentry, qname);
if (!newdent) {
newdent = d_alloc(dentry, qname);
if (!newdent)
goto end_advance;
} else {
hashed = 1;
memcpy((char *) newdent->d_name.name, qname->name,
newdent->d_name.len);
}
if (!newdent->d_inode) {
smb_renew_times(newdent);
entry->f_ino = iunique(inode->i_sb, 2);
newino = smb_iget(inode->i_sb, entry);
if (newino) {
smb_new_dentry(newdent);
d_instantiate(newdent, newino);
if (!hashed)
d_rehash(newdent);
}
} else
smb_set_inode_attr(newdent->d_inode, entry);
if (newdent->d_inode) {
ino = newdent->d_inode->i_ino;
newdent->d_fsdata = (void *) ctl.fpos;
smb_new_dentry(newdent);
}
if (ctl.idx >= SMB_DIRCACHE_SIZE) {
if (ctl.page) {
kunmap(ctl.page);
SetPageUptodate(ctl.page);
unlock_page(ctl.page);
page_cache_release(ctl.page);
}
ctl.cache = NULL;
ctl.idx -= SMB_DIRCACHE_SIZE;
ctl.ofs += 1;
ctl.page = grab_cache_page(&inode->i_data, ctl.ofs);
if (ctl.page)
ctl.cache = kmap(ctl.page);
}
if (ctl.cache) {
ctl.cache->dentry[ctl.idx] = newdent;
valid = 1;
}
dput(newdent);
end_advance:
if (!valid)
ctl.valid = 0;
if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
if (!ino)
ino = find_inode_number(dentry, qname);
if (!ino)
ino = iunique(inode->i_sb, 2);
ctl.filled = filldir(dirent, qname->name, qname->len,
filp->f_pos, ino, DT_UNKNOWN);
if (!ctl.filled)
filp->f_pos += 1;
}
ctl.fpos += 1;
ctl.idx += 1;
*ctrl = ctl;
return (ctl.valid || !ctl.filled);
}
示例12: free_page_and_swap_cache
/*
* Perform a free_page(), also freeing any swap cache associated with
* this page if it is the last user of the page.
*/
void free_page_and_swap_cache(struct page *page)
{
free_swap_cache(page);
page_cache_release(page);
}
示例13: read_mapping_page
/*
* Returns a pointer to a buffer containing at least LEN bytes of
* filesystem starting at byte offset OFFSET into the filesystem.
*/
static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len)
{
struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
struct page *pages[BLKS_PER_BUF];
unsigned i, blocknr, buffer, unread;
unsigned long devsize;
char *data;
if (!len)
return NULL;
blocknr = offset >> PAGE_CACHE_SHIFT;
offset &= PAGE_CACHE_SIZE - 1;
/* Check if an existing buffer already has the data.. */
for (i = 0; i < READ_BUFFERS; i++) {
unsigned int blk_offset;
if (buffer_dev[i] != sb)
continue;
if (blocknr < buffer_blocknr[i])
continue;
blk_offset = (blocknr - buffer_blocknr[i]) << PAGE_CACHE_SHIFT;
blk_offset += offset;
if (blk_offset + len > BUFFER_SIZE)
continue;
return read_buffers[i] + blk_offset;
}
devsize = mapping->host->i_size >> PAGE_CACHE_SHIFT;
/* Ok, read in BLKS_PER_BUF pages completely first. */
unread = 0;
for (i = 0; i < BLKS_PER_BUF; i++) {
struct page *page = NULL;
if (blocknr + i < devsize) {
page = read_mapping_page(mapping, blocknr + i, NULL);
/* synchronous error? */
if (IS_ERR(page))
page = NULL;
}
pages[i] = page;
}
for (i = 0; i < BLKS_PER_BUF; i++) {
struct page *page = pages[i];
if (page) {
wait_on_page_locked(page);
if (!PageUptodate(page)) {
/* asynchronous error */
page_cache_release(page);
pages[i] = NULL;
}
}
}
buffer = next_buffer;
next_buffer = NEXT_BUFFER(buffer);
buffer_blocknr[buffer] = blocknr;
buffer_dev[buffer] = sb;
data = read_buffers[buffer];
for (i = 0; i < BLKS_PER_BUF; i++) {
struct page *page = pages[i];
if (page) {
memcpy(data, kmap(page), PAGE_CACHE_SIZE);
kunmap(page);
page_cache_release(page);
} else
memset(data, 0, PAGE_CACHE_SIZE);
data += PAGE_CACHE_SIZE;
}
return read_buffers[buffer] + offset;
}
示例14: __mcopy_atomic
//.........这里部分代码省略.........
/*
* FIXME: only allow copying on anonymous vmas, tmpfs should
* be added.
*/
if (dst_vma->vm_ops)
goto out_unlock;
/*
* Ensure the dst_vma has a anon_vma or this page
* would get a NULL anon_vma when moved in the
* dst_vma.
*/
err = -ENOMEM;
if (unlikely(anon_vma_prepare(dst_vma)))
goto out_unlock;
while (src_addr < src_start + len) {
pmd_t dst_pmdval;
BUG_ON(dst_addr >= dst_start + len);
dst_pmd = mm_alloc_pmd(dst_mm, dst_addr);
if (unlikely(!dst_pmd)) {
err = -ENOMEM;
break;
}
dst_pmdval = pmd_read_atomic(dst_pmd);
/*
* If the dst_pmd is mapped as THP don't
* override it and just be strict.
*/
if (unlikely(pmd_trans_huge(dst_pmdval))) {
err = -EEXIST;
break;
}
if (unlikely(pmd_none(dst_pmdval)) &&
unlikely(__pte_alloc(dst_mm, dst_pmd, dst_addr))) {
err = -ENOMEM;
break;
}
/* If an huge pmd materialized from under us fail */
if (unlikely(pmd_trans_huge(*dst_pmd))) {
err = -EFAULT;
break;
}
BUG_ON(pmd_none(*dst_pmd));
BUG_ON(pmd_trans_huge(*dst_pmd));
if (!zeropage)
err = mcopy_atomic_pte(dst_mm, dst_pmd, dst_vma,
dst_addr, src_addr, &page);
else
err = mfill_zeropage_pte(dst_mm, dst_pmd, dst_vma,
dst_addr);
cond_resched();
if (unlikely(err == -EFAULT)) {
void *page_kaddr;
up_read(&dst_mm->mmap_sem);
BUG_ON(!page);
page_kaddr = kmap(page);
err = copy_from_user(page_kaddr,
(const void __user *) src_addr,
PAGE_SIZE);
kunmap(page);
if (unlikely(err)) {
err = -EFAULT;
goto out;
}
goto retry;
} else
BUG_ON(page);
if (!err) {
dst_addr += PAGE_SIZE;
src_addr += PAGE_SIZE;
copied += PAGE_SIZE;
if (fatal_signal_pending(current))
err = -EINTR;
}
if (err)
break;
}
out_unlock:
up_read(&dst_mm->mmap_sem);
out:
if (page)
page_cache_release(page);
BUG_ON(copied < 0);
BUG_ON(err > 0);
BUG_ON(!copied && !err);
return copied ? copied : err;
}
示例15: ttm_tt_swapout
int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistant_swap_storage)
{
struct address_space *swap_space;
struct file *swap_storage;
struct page *from_page;
struct page *to_page;
void *from_virtual;
void *to_virtual;
int i;
BUG_ON(ttm->state != tt_unbound && ttm->state != tt_unpopulated);
BUG_ON(ttm->caching_state != tt_cached);
/*
* For user buffers, just unpin the pages, as there should be
* vma references.
*/
if (ttm->page_flags & TTM_PAGE_FLAG_USER) {
ttm_tt_free_user_pages(ttm);
ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED;
ttm->swap_storage = NULL;
return 0;
}
if (!persistant_swap_storage) {
swap_storage = shmem_file_setup("ttm swap",
ttm->num_pages << PAGE_SHIFT,
0);
if (unlikely(IS_ERR(swap_storage))) {
printk(KERN_ERR "Failed allocating swap storage.\n");
return -ENOMEM;
}
} else
swap_storage = persistant_swap_storage;
swap_space = swap_storage->f_path.dentry->d_inode->i_mapping;
for (i = 0; i < ttm->num_pages; ++i) {
from_page = ttm->pages[i];
if (unlikely(from_page == NULL))
continue;
to_page = read_mapping_page(swap_space, i, NULL);
if (unlikely(to_page == NULL))
goto out_err;
preempt_disable();
from_virtual = kmap_atomic(from_page, KM_USER0);
to_virtual = kmap_atomic(to_page, KM_USER1);
memcpy(to_virtual, from_virtual, PAGE_SIZE);
kunmap_atomic(to_virtual, KM_USER1);
kunmap_atomic(from_virtual, KM_USER0);
preempt_enable();
set_page_dirty(to_page);
mark_page_accessed(to_page);
page_cache_release(to_page);
}
ttm_tt_free_alloced_pages(ttm);
ttm->swap_storage = swap_storage;
ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED;
if (persistant_swap_storage)
ttm->page_flags |= TTM_PAGE_FLAG_PERSISTANT_SWAP;
return 0;
out_err:
if (!persistant_swap_storage)
fput(swap_storage);
return -ENOMEM;
}