示例#1
0
int hib_wait_on_bio_chain(struct bio **bio_chain)
{
	struct bio *bio;
	struct bio *next_bio;
	int ret = 0;

	if (bio_chain == NULL)
		return 0;

	bio = *bio_chain;
	if (bio == NULL)
		return 0;
	while (bio) {
		struct page *page;

		next_bio = bio->bi_private;
		page = bio->bi_io_vec[0].bv_page;
		wait_on_page_locked(page);
		if (!PageUptodate(page) || PageError(page))
			ret = -EIO;
		put_page(page);
		bio_put(bio);
		bio = next_bio;
	}
	*bio_chain = NULL;
	return ret;
}
示例#2
0
static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent)
{
    struct super_block *sb = sdp->sd_vfs;
    struct gfs2_sb *p;
    struct page *page;
    struct bio *bio;

    page = alloc_page(GFP_NOFS);
    if (unlikely(!page))
        return -ENOBUFS;

    ClearPageUptodate(page);
    ClearPageDirty(page);
    lock_page(page);

    bio = bio_alloc(GFP_NOFS, 1);
    bio->bi_sector = sector * (sb->s_blocksize >> 9);
    bio->bi_bdev = sb->s_bdev;
    bio_add_page(bio, page, PAGE_SIZE, 0);

    bio->bi_end_io = end_bio_io_page;
    bio->bi_private = page;
    submit_bio(READ_SYNC | REQ_META, bio);
    wait_on_page_locked(page);
    bio_put(bio);
    if (!PageUptodate(page)) {
        __free_page(page);
        return -EIO;
    }
    p = kmap(page);
    gfs2_sb_in(sdp, p);
    kunmap(page);
    __free_page(page);
    return gfs2_check_sb(sdp, silent);
}
示例#3
0
/*
 * check a symbolic link to see whether it actually encodes a mountpoint
 * - sets the AFS_VNODE_MOUNTPOINT flag on the vnode appropriately
 */
int afs_mntpt_check_symlink(struct afs_vnode *vnode)
{
	struct page *page;
	size_t size;
	char *buf;
	int ret;

	_enter("{%u,%u}", vnode->fid.vnode, vnode->fid.unique);

	/* read the contents of the symlink into the pagecache */
	page = read_mapping_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0, NULL);
	if (IS_ERR(page)) {
		ret = PTR_ERR(page);
		goto out;
	}

	ret = -EIO;
	wait_on_page_locked(page);
	buf = kmap(page);
	if (!PageUptodate(page))
		goto out_free;
	if (PageError(page))
		goto out_free;

	/* examine the symlink's contents */
	size = vnode->status.size;
	_debug("symlink to %*.*s", size, (int) size, buf);

	if (size > 2 &&
	    (buf[0] == '%' || buf[0] == '#') &&
	    buf[size - 1] == '.'
	    ) {
		_debug("symlink is a mountpoint");
		spin_lock(&vnode->lock);
		vnode->flags |= AFS_VNODE_MOUNTPOINT;
		spin_unlock(&vnode->lock);
	}

	ret = 0;

 out_free:
	kunmap(page);
	page_cache_release(page);
 out:
	_leave(" = %d", ret);
	return ret;

} /* end afs_mntpt_check_symlink() */
/**
 * do_bio_wait - wait for some TuxOnIce I/O to complete
 * @reason: The array index of the reason we're waiting.
 *
 * Wait for a particular page of I/O if we're after a particular page.
 * If we're not after a particular page, wait instead for all in flight
 * I/O to be completed or for us to have enough free memory to be able
 * to submit more I/O.
 *
 * If we wait, we also update our statistics regarding why we waited.
 **/
static void do_bio_wait(int reason)
{
	struct page *was_waiting_on = waiting_on;

	/* On SMP, waiting_on can be reset, so we make a copy */
	if (was_waiting_on) {
		wait_on_page_locked(was_waiting_on);
		atomic_inc(&reasons[reason]);
	} else {
		atomic_inc(&reasons[reason]);

		wait_event(num_in_progress_wait,
			!atomic_read(&toi_io_in_progress) ||
			nr_unallocated_buffer_pages() > free_mem_throttle);
	}
}
示例#5
0
static struct page * dir_get_page(struct inode *dir, unsigned long n)
{
	struct address_space *mapping = dir->i_mapping;
	struct page *page = read_mapping_page(mapping, n, NULL);
	if (!IS_ERR(page)) {
		wait_on_page_locked(page);
		kmap(page);
		if (!PageUptodate(page))
			goto fail;
	}
	return page;

fail:
	dir_put_page(page);
	return ERR_PTR(-EIO);
}
示例#6
0
/**
 * ecryptfs_get1page
 *
 * Get one page from cache or lower f/s, return error otherwise.
 *
 * Returns unlocked and up-to-date page (if ok), with increased
 * refcnt.
 */
static struct page *ecryptfs_get1page(struct file *file, int index)
{
	struct page *page;
	struct dentry *dentry;
	struct inode *inode;
	struct address_space *mapping;

	dentry = file->f_path.dentry;
	inode = dentry->d_inode;
	mapping = inode->i_mapping;
	page = read_cache_page(mapping, index,
			       (filler_t *)mapping->a_ops->readpage,
			       (void *)file);
	if (IS_ERR(page))
		goto out;
	wait_on_page_locked(page);
out:
	return page;
}
示例#7
0
/* get the link contents into pagecache */
static char *ocfs2_page_getlink(struct dentry * dentry,
				struct page **ppage)
{
	struct page * page;
	struct address_space *mapping = dentry->d_inode->i_mapping;
	page = read_mapping_page(mapping, 0, NULL);
	if (IS_ERR(page))
		goto sync_fail;
	wait_on_page_locked(page);
	if (!PageUptodate(page))
		goto async_fail;
	*ppage = page;
	return kmap(page);

async_fail:
	page_cache_release(page);
	return ERR_PTR(-EIO);

sync_fail:
	return (char*)page;
}
示例#8
0
文件: data.c 项目: aejsmith/linux
struct page *find_data_page(struct inode *inode, pgoff_t index)
{
    struct address_space *mapping = inode->i_mapping;
    struct page *page;

    page = find_get_page(mapping, index);
    if (page && PageUptodate(page))
        return page;
    f2fs_put_page(page, 0);

    page = get_read_data_page(inode, index, READ_SYNC);
    if (IS_ERR(page))
        return page;

    if (PageUptodate(page))
        return page;

    wait_on_page_locked(page);
    if (unlikely(!PageUptodate(page))) {
        f2fs_put_page(page, 0);
        return ERR_PTR(-EIO);
    }
    return page;
}
示例#9
0
文件: dir.c 项目: xricson/knoppix
/*
 * get a page into the pagecache
 */
static struct page *afs_dir_get_page(struct inode *dir, unsigned long index)
{
	struct page *page;

	_enter("{%lu},%lu",dir->i_ino,index);

	page = read_cache_page(dir->i_mapping,index,
			       (filler_t*)dir->i_mapping->a_ops->readpage,NULL);
	if (!IS_ERR(page)) {
		wait_on_page_locked(page);
		kmap(page);
		if (!PageUptodate(page))
			goto fail;
		if (!PageChecked(page))
			afs_dir_check_page(dir,page);
		if (PageError(page))
			goto fail;
	}
	return page;

 fail:
	afs_dir_put_page(page);
	return ERR_PTR(-EIO);
} /* end afs_dir_get_page() */
示例#10
0
/**
 *	submit - submit BIO request.
 *	@rw:	READ or WRITE.
 *	@off	physical offset of page.
 *	@page:	page we're reading or writing.
 *	@bio_chain: list of pending biod (for async reading)
 *
 *	Straight from the textbook - allocate and initialize the bio.
 *	If we're reading, make sure the page is marked as dirty.
 *	Then submit it and, if @bio_chain == NULL, wait.
 */
static int submit(int rw, struct block_device *bdev, sector_t sector,
		struct page *page, struct bio **bio_chain)
{
	const int bio_rw = rw | REQ_SYNC;
	struct bio *bio;

	bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1);
	bio->bi_sector = sector;
	bio->bi_bdev = bdev;
	bio->bi_end_io = end_swap_bio_read;

	if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
		printk(KERN_ERR "PM: Adding page to bio failed at %llu\n",
			(unsigned long long)sector);
		bio_put(bio);
		return -EFAULT;
	}

	lock_page(page);
	bio_get(bio);

	if (bio_chain == NULL) {
		submit_bio(bio_rw, bio);
		wait_on_page_locked(page);
		if (rw == READ)
			bio_set_pages_dirty(bio);
		bio_put(bio);
	} else {
		if (rw == READ)
			get_page(page);	/* These pages are freed later */
		bio->bi_private = *bio_chain;
		*bio_chain = bio;
		submit_bio(bio_rw, bio);
	}
	return 0;
}
示例#11
0
/* read a page from a file, pinning it into cache, and return bytes_read */
static struct page *read_page(struct file *file, unsigned long index,
                              unsigned long *bytes_read)
{
    struct inode *inode = file->f_mapping->host;
    struct page *page = NULL;
    loff_t isize = i_size_read(inode);
    unsigned long end_index = isize >> PAGE_SHIFT;

    PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_SIZE,
           (unsigned long long)index << PAGE_SHIFT);

    page = read_cache_page(inode->i_mapping, index,
                           (filler_t *)inode->i_mapping->a_ops->readpage, file);
    if (IS_ERR(page))
        goto out;
    wait_on_page_locked(page);
    if (!PageUptodate(page) || PageError(page)) {
        put_page(page);
        page = ERR_PTR(-EIO);
        goto out;
    }

    if (index > end_index) /* we have read beyond EOF */
        *bytes_read = 0;
    else if (index == end_index) /* possible short read */
        *bytes_read = isize & ~PAGE_MASK;
    else
        *bytes_read = PAGE_SIZE; /* got a full page */
out:
    if (IS_ERR(page))
        printk(KERN_ALERT "md: bitmap read error: (%dB @ %Lu): %ld\n",
               (int)PAGE_SIZE,
               (unsigned long long)index << PAGE_SHIFT,
               PTR_ERR(page));
    return page;
}
示例#12
0
/*
 * create a vfsmount to be automounted
 */
static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
{
	struct afs_super_info *super;
	struct vfsmount *mnt;
	struct page *page = NULL;
	size_t size;
	char *buf, *devname = NULL, *options = NULL;
	int ret;

	kenter("{%s}", mntpt->d_name.name);

	BUG_ON(!mntpt->d_inode);

	ret = -EINVAL;
	size = mntpt->d_inode->i_size;
	if (size > PAGE_SIZE - 1)
		goto error;

	ret = -ENOMEM;
	devname = (char *) get_zeroed_page(GFP_KERNEL);
	if (!devname)
		goto error;

	options = (char *) get_zeroed_page(GFP_KERNEL);
	if (!options)
		goto error;

	/* read the contents of the AFS special symlink */
	page = read_mapping_page(mntpt->d_inode->i_mapping, 0, NULL);
	if (IS_ERR(page)) {
		ret = PTR_ERR(page);
		goto error;
	}

	ret = -EIO;
	wait_on_page_locked(page);
	if (!PageUptodate(page) || PageError(page))
		goto error;

	buf = kmap(page);
	memcpy(devname, buf, size);
	kunmap(page);
	page_cache_release(page);
	page = NULL;

	/* work out what options we want */
	super = AFS_FS_S(mntpt->d_sb);
	memcpy(options, "cell=", 5);
	strcpy(options + 5, super->volume->cell->name);
	if (super->volume->type == AFSVL_RWVOL)
		strcat(options, ",rwpath");

	/* try and do the mount */
	kdebug("--- attempting mount %s -o %s ---", devname, options);
	mnt = vfs_kern_mount(&afs_fs_type, 0, devname, options);
	kdebug("--- mount result %p ---", mnt);

	free_page((unsigned long) devname);
	free_page((unsigned long) options);
	kleave(" = %p", mnt);
	return mnt;

 error:
	if (page)
		page_cache_release(page);
	if (devname)
		free_page((unsigned long) devname);
	if (options)
		free_page((unsigned long) options);
	kleave(" = %d", ret);
	return ERR_PTR(ret);
} /* end afs_mntpt_do_automount() */
示例#13
0
/*
 * We completely avoid races by reading each swap page in advance,
 * and then search for the process using it.  All the necessary
 * page table adjustments can then be made atomically.
 */
static int try_to_unuse(unsigned int type)
{
	struct swap_info_struct * si = &swap_info[type];
	struct mm_struct *start_mm;
	unsigned short *swap_map;
	unsigned short swcount;
	struct page *page;
	swp_entry_t entry;
	unsigned int i = 0;
	int retval = 0;
	int reset_overflow = 0;
	int shmem;

	/*
	 * When searching mms for an entry, a good strategy is to
	 * start at the first mm we freed the previous entry from
	 * (though actually we don't notice whether we or coincidence
	 * freed the entry).  Initialize this start_mm with a hold.
	 *
	 * A simpler strategy would be to start at the last mm we
	 * freed the previous entry from; but that would take less
	 * advantage of mmlist ordering, which clusters forked mms
	 * together, child after parent.  If we race with dup_mmap(), we
	 * prefer to resolve parent before child, lest we miss entries
	 * duplicated after we scanned child: using last mm would invert
	 * that.  Though it's only a serious concern when an overflowed
	 * swap count is reset from SWAP_MAP_MAX, preventing a rescan.
	 */
	start_mm = &init_mm;
	atomic_inc(&init_mm.mm_users);

	/*
	 * Keep on scanning until all entries have gone.  Usually,
	 * one pass through swap_map is enough, but not necessarily:
	 * there are races when an instance of an entry might be missed.
	 */
	while ((i = find_next_to_unuse(si, i)) != 0) {
		if (signal_pending(current)) {
			retval = -EINTR;
			break;
		}

		/* 
		 * Get a page for the entry, using the existing swap
		 * cache page if there is one.  Otherwise, get a clean
		 * page and read the swap into it. 
		 */
		swap_map = &si->swap_map[i];
		entry = swp_entry(type, i);
		page = read_swap_cache_async(entry, NULL, 0);
		if (!page) {
			/*
			 * Either swap_duplicate() failed because entry
			 * has been freed independently, and will not be
			 * reused since sys_swapoff() already disabled
			 * allocation from here, or alloc_page() failed.
			 */
			if (!*swap_map)
				continue;
			retval = -ENOMEM;
			break;
		}

		/*
		 * Don't hold on to start_mm if it looks like exiting.
		 */
		if (atomic_read(&start_mm->mm_users) == 1) {
			mmput(start_mm);
			start_mm = &init_mm;
			atomic_inc(&init_mm.mm_users);
		}

		/*
		 * Wait for and lock page.  When do_swap_page races with
		 * try_to_unuse, do_swap_page can handle the fault much
		 * faster than try_to_unuse can locate the entry.  This
		 * apparently redundant "wait_on_page_locked" lets try_to_unuse
		 * defer to do_swap_page in such a case - in some tests,
		 * do_swap_page and try_to_unuse repeatedly compete.
		 */
		wait_on_page_locked(page);
		wait_on_page_writeback(page);
		lock_page(page);
		wait_on_page_writeback(page);

		/*
		 * Remove all references to entry.
		 * Whenever we reach init_mm, there's no address space
		 * to search, but use it as a reminder to search shmem.
		 */
		shmem = 0;
		swcount = *swap_map;
		if (swcount > 1) {
			if (start_mm == &init_mm)
				shmem = shmem_unuse(entry, page);
			else
				retval = unuse_mm(start_mm, entry, page);
		}
		if (*swap_map > 1) {
			int set_start_mm = (*swap_map >= swcount);
			struct list_head *p = &start_mm->mmlist;
			struct mm_struct *new_start_mm = start_mm;
			struct mm_struct *prev_mm = start_mm;
			struct mm_struct *mm;

			atomic_inc(&new_start_mm->mm_users);
			atomic_inc(&prev_mm->mm_users);
			spin_lock(&mmlist_lock);
			while (*swap_map > 1 && !retval &&
					(p = p->next) != &start_mm->mmlist) {
				mm = list_entry(p, struct mm_struct, mmlist);
				if (!atomic_inc_not_zero(&mm->mm_users))
					continue;
				spin_unlock(&mmlist_lock);
				mmput(prev_mm);
				prev_mm = mm;

				cond_resched();

				swcount = *swap_map;
				if (swcount <= 1)
					;
				else if (mm == &init_mm) {
					set_start_mm = 1;
					shmem = shmem_unuse(entry, page);
				} else
					retval = unuse_mm(mm, entry, page);
				if (set_start_mm && *swap_map < swcount) {
					mmput(new_start_mm);
					atomic_inc(&mm->mm_users);
					new_start_mm = mm;
					set_start_mm = 0;
				}
				spin_lock(&mmlist_lock);
			}
			spin_unlock(&mmlist_lock);
			mmput(prev_mm);
			mmput(start_mm);
			start_mm = new_start_mm;
		}
		if (retval) {
			unlock_page(page);
			page_cache_release(page);
			break;
		}

		/*
		 * How could swap count reach 0x7fff when the maximum
		 * pid is 0x7fff, and there's no way to repeat a swap
		 * page within an mm (except in shmem, where it's the
		 * shared object which takes the reference count)?
		 * We believe SWAP_MAP_MAX cannot occur in Linux 2.4.
		 *
		 * If that's wrong, then we should worry more about
		 * exit_mmap() and do_munmap() cases described above:
		 * we might be resetting SWAP_MAP_MAX too early here.
		 * We know "Undead"s can happen, they're okay, so don't
		 * report them; but do report if we reset SWAP_MAP_MAX.
		 */
		if (*swap_map == SWAP_MAP_MAX) {
			spin_lock(&swap_lock);
			*swap_map = 1;
			spin_unlock(&swap_lock);
			reset_overflow = 1;
		}

		/*
		 * If a reference remains (rare), we would like to leave
		 * the page in the swap cache; but try_to_unmap could
		 * then re-duplicate the entry once we drop page lock,
		 * so we might loop indefinitely; also, that page could
		 * not be swapped out to other storage meanwhile.  So:
		 * delete from cache even if there's another reference,
		 * after ensuring that the data has been saved to disk -
		 * since if the reference remains (rarer), it will be
		 * read from disk into another page.  Splitting into two
		 * pages would be incorrect if swap supported "shared
		 * private" pages, but they are handled by tmpfs files.
		 *
		 * Note shmem_unuse already deleted a swappage from
		 * the swap cache, unless the move to filepage failed:
		 * in which case it left swappage in cache, lowered its
		 * swap count to pass quickly through the loops above,
		 * and now we must reincrement count to try again later.
		 */
		if ((*swap_map > 1) && PageDirty(page) && PageSwapCache(page)) {
			struct writeback_control wbc = {
				.sync_mode = WB_SYNC_NONE,
			};

			swap_writepage(page, &wbc);
			lock_page(page);
			wait_on_page_writeback(page);
		}
		if (PageSwapCache(page)) {
			if (shmem)
				swap_duplicate(entry);
			else
				delete_from_swap_cache(page);
		}

		/*
		 * So we could skip searching mms once swap count went
		 * to 1, we did not mark any present ptes as dirty: must
		 * mark page dirty so shrink_page_list will preserve it.
		 */
		SetPageDirty(page);
		unlock_page(page);
		page_cache_release(page);

		/*
		 * Make sure that we aren't completely killing
		 * interactive performance.
		 */
		cond_resched();
	}
示例#14
0
/*
 * 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_comm(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;
	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. */
	for (i = 0; i < BLKS_PER_BUF; i++) {
		struct page *page = NULL;

		if (blocknr + i < devsize) {
			page = read_mapping_page_async(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;
}
示例#15
0
/* for every page of file: read page, cut part of extent pointing to this page,
   put data of page tree by tail item */
int extent2tail(struct file * file, struct unix_file_info *uf_info)
{
	int result;
	struct inode *inode;
	struct page *page;
	unsigned long num_pages, i;
	unsigned long start_page;
	reiser4_key from;
	reiser4_key to;
	unsigned count;
	__u64 offset;

	assert("nikita-3362", ea_obtained(uf_info));
	inode = unix_file_info_to_inode(uf_info);
	assert("nikita-3412", !IS_RDONLY(inode));
	assert("vs-1649", uf_info->container != UF_CONTAINER_TAILS);
	assert("", !reiser4_inode_get_flag(inode, REISER4_PART_IN_CONV));

	offset = 0;
	if (reiser4_inode_get_flag(inode, REISER4_PART_MIXED)) {
		/*
		 * file is marked on disk as there was a conversion which did
		 * not complete due to either crash or some error. Find which
		 * offset tail conversion stopped at
		 */
		result = find_start(inode, EXTENT_POINTER_ID, &offset);
		if (result == -ENOENT) {
			/* no extent found, everything is converted */
			uf_info->container = UF_CONTAINER_TAILS;
			complete_conversion(inode);
			return 0;
		} else if (result != 0)
			/* some other error */
			return result;
	}

	reiser4_inode_set_flag(inode, REISER4_PART_IN_CONV);

	/* number of pages in the file */
	num_pages =
	    (inode->i_size + - offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
	start_page = offset >> PAGE_CACHE_SHIFT;

	inode_file_plugin(inode)->key_by_inode(inode, offset, &from);
	to = from;

	result = 0;
	for (i = 0; i < num_pages; i++) {
		__u64 start_byte;

		result = reserve_extent2tail_iteration(inode);
		if (result != 0)
			break;
		if (i == 0 && offset == 0) {
			reiser4_inode_set_flag(inode, REISER4_PART_MIXED);
			reiser4_update_sd(inode);
		}

		page = read_mapping_page(inode->i_mapping,
					 (unsigned)(i + start_page), NULL);
		if (IS_ERR(page)) {
			result = PTR_ERR(page);
			break;
		}

		wait_on_page_locked(page);

		if (!PageUptodate(page)) {
			page_cache_release(page);
			result = RETERR(-EIO);
			break;
		}

		/* cut part of file we have read */
		start_byte = (__u64) ((i + start_page) << PAGE_CACHE_SHIFT);
		set_key_offset(&from, start_byte);
		set_key_offset(&to, start_byte + PAGE_CACHE_SIZE - 1);
		/*
		 * reiser4_cut_tree_object() returns -E_REPEAT to allow atom
		 * commits during over-long truncates. But
		 * extent->tail conversion should be performed in one
		 * transaction.
		 */
		result = reiser4_cut_tree(reiser4_tree_by_inode(inode), &from,
					  &to, inode, 0);

		if (result) {
			page_cache_release(page);
			break;
		}

		/* put page data into tree via tail_write */
		count = PAGE_CACHE_SIZE;
		if ((i == (num_pages - 1)) &&
		    (inode->i_size & ~PAGE_CACHE_MASK))
			/* last page can be incompleted */
			count = (inode->i_size & ~PAGE_CACHE_MASK);
		while (count) {
			loff_t pos = start_byte;

			assert("edward-1537",
			       file != NULL && file->f_dentry != NULL);
			assert("edward-1538",
			       file->f_dentry->d_inode == inode);

			result = reiser4_write_tail(file, inode,
						    (char __user *)kmap(page),
						    count, &pos);
			reiser4_free_file_fsdata(file);
			if (result <= 0) {
				warning("", "reiser4_write_tail failed");
				page_cache_release(page);
				reiser4_inode_clr_flag(inode, REISER4_PART_IN_CONV);
				return result;
			}
			count -= result;
		}

		/* release page */
		lock_page(page);
		/* page is already detached from jnode and mapping. */
		assert("vs-1086", page->mapping == NULL);
		assert("nikita-2690",
		       (!PagePrivate(page) && jprivate(page) == 0));
		/* waiting for writeback completion with page lock held is
		 * perfectly valid. */
		wait_on_page_writeback(page);
		reiser4_drop_page(page);
		/* release reference taken by read_cache_page() above */
		page_cache_release(page);

		drop_exclusive_access(uf_info);
		/*
		 * throttle the conversion.
		 * FIXME-EDWARD: Calculate and pass the precise number
		 * of pages that was dirtied
		 */
		reiser4_throttle_write(inode, 1);
		get_exclusive_access(uf_info);
		/*
		 * nobody is allowed to complete conversion but a process which
		 * started it
		 */
		assert("", reiser4_inode_get_flag(inode, REISER4_PART_MIXED));
	}

	reiser4_inode_clr_flag(inode, REISER4_PART_IN_CONV);

	if (i == num_pages) {
		/* file is converted to formatted items */
		assert("vs-1698", reiser4_inode_get_flag(inode,
							 REISER4_PART_MIXED));
		assert("vs-1260",
		       inode_has_no_jnodes(reiser4_inode_data(inode)));

		uf_info->container = UF_CONTAINER_TAILS;
		complete_conversion(inode);
		return 0;
	}
	/*
	 * conversion is not complete. Inode was already marked as
	 * REISER4_PART_MIXED and stat-data were updated at the first
	 * iteration of the loop above.
	 */
	warning("nikita-2282",
		"Partial conversion of %llu: %lu of %lu: %i",
		(unsigned long long)get_inode_oid(inode), i,
		num_pages, result);

	/* this flag should be cleared, otherwise get_exclusive_access_careful()
	   will fall into infinite loop */
	assert("edward-1550", !reiser4_inode_get_flag(inode,
						      REISER4_PART_IN_CONV));
	return result;
}
示例#16
0
文件: file.c 项目: MohsenKoohi/GSFS
ssize_t GSFS_file_read (struct file *filp, char __user *charp, size_t len, loff_t *off){
	struct inode		*inode=filp->f_mapping->host;
	struct GSFS_inode	*inf=(struct GSFS_inode*)inode->i_private;
	sector_t sec_start,
		 sec_end,
		 sec_len;
	struct page	**res,
			**res2,
			**restemp;
	unsigned int *pn,
		     *pn2,
		     *pntemp;
	int 	i,
		odirect=filp->f_flags&O_SYNC,
		j,
		lock,
		pncount,
		pn2count;
	unsigned long 	pagestartbyte=0,
			pageendbyte,
			bufstart,
			bytes_in_first_buf_page;
	unsigned long	pagelen;		
	size_t  rlen;
	//char	*dest,
	//	*src;
	
	gwf(printk("<0>" "File read with inode :%lu size:%lu offset:%llu , off:%llu, charp:%lx, pid:%u\n",inode->i_ino,len,*off,filp->f_pos,(unsigned long)charp,current->pid));
	if((*off>=inode->i_size)){
		gwf(printk("<0>" "File read ended for *pos<size with inode :%lu size:%lu offset:%llu , off:%llu, charp:%lx, pid:%u\n",inode->i_ino,len,*off,filp->f_pos,(unsigned long)charp,current->pid));
		return 0;
	}
	if(!access_ok(VERIFY_WRITE,charp,len)){
		gwf(printk("<0>" "File read ended for access_nok with inode :%lu size:%lu offset:%llu , off:%llu, charp:%lx, pid:%u\n",inode->i_ino,len,*off,filp->f_pos,(unsigned long)charp,current->pid));
		return -EIO;
	}
	sec_start=(*off)>>Block_Size_Bits;
	if((*off+len)>inode->i_size)
		len=inode->i_size-*off;
	sec_end=(*off+len-1)>>Block_Size_Bits;
	sec_len=sec_end-sec_start+1;
	bytes_in_first_buf_page=((1+~((*off)&((unsigned long)Block_Size-1)))&(Block_Size-1));
	if(!bytes_in_first_buf_page)
		bytes_in_first_buf_page=Block_Size;
	pn=kzalloc(sec_len*sizeof(unsigned int),GFP_KERNEL);
	pn2=kzalloc(sec_len*sizeof(unsigned int),GFP_KERNEL);
	res=kzalloc(sec_len*sizeof(struct page*),GFP_KERNEL);
	res2=kzalloc(sec_len*sizeof(struct page*),GFP_KERNEL);
	for(i=sec_start,j=0;i<=sec_end;i++,j++)
		pn[j]=i;
	
	gwf(printk("<0>" "GSFS_file_read: sec_start:%lu, sec_end:%lu, sec_len:%lu, bytes_in_first_buf_page: %lu\n",
			sec_start,sec_end,sec_len,bytes_in_first_buf_page));
			
	pncount=GSFS_get_data_pages_of_inode(inode, pn, sec_len ,res,odirect);	
	//printk("<0>" "res[%u]=%d \n",j,res[j]);
	rlen=0;
	pn2count=0;
	lock=0;
	do{
		for(j=0;j<pncount;j++){
			//printk("<0>" "res[%u]=%lx \n",j,res[j]);
			
			if(unlikely(!res[j]))
				continue;
			
			if(lock && PageLocked(res[j])){
				//printk("<0>" "Locking for j:%u\n",j);
				wait_on_page_locked(res[j]);
				lock=0;
			}
			else 
				if(PageLocked(res[j])){
					pn2[pn2count]=pn[j];
					res2[pn2count]=res[j];
					pn2count++;
					continue;
				}
				
			//the page is available for writing to buffer
			 
			if(pn[j]==sec_start){
				pagestartbyte=((*off)&(Block_Size-1));
				bufstart=(unsigned long)charp;
			}
			else{
				pagestartbyte=0;
				bufstart=(unsigned long)(charp)+bytes_in_first_buf_page+((pn[j]-sec_start-1)<<Block_Size_Bits);
			}
			if(pn[j]==sec_end)
				pageendbyte=((*off+len-1)&(Block_Size-1));
			else
				pageendbyte=Block_Size-1;
			pagelen=(unsigned long)(pageendbyte-pagestartbyte+1);
			
			if(inf->igflags & igflag_secure){
				struct GSFS_page	*gp=(struct GSFS_page*)page_private(res[j]);
				
				if(unlikely(!gp || !gp->sip) || unlikely(!(gp->sip->spflags & spflag_page_is_ready_for_read)) ){
					//printk("<0>" "page is not ready for inode:%lu, index: %lu\n", inode->i_ino, res[j]->index);
					//if(gp && gp->sip)
					//	printk("<0>" "and flags:%d\n",gp->sip->spflags);
					goto add_cont;
				}
			}
			
			i=__copy_to_user_inatomic((void*)bufstart,page_address(res[j])+pagestartbyte,pagelen);
add_cont:			
			rlen+=(pagelen-i);
			mark_page_accessed(res[j]);
			/*
			dest=(char*)bufstart;
			src=(char*)pagestartbyte;
			for(i=0;i<pagelen;i++)
				dest[i]=src[i];
			*/
			//printk("<0>" "asdfasd%s",dest);
			//rlen+=i;
			GSFS_put_data_page_of_inode(inode,res[j]);
			//gwf(printk("<0>" "file read for inode:%lu, j:%u pn[j]:%u pagestartbyte:%lx bufstart:%lx pagelen:%lu i:%u sec_start:%lu\n",
			//		inode->i_ino, j, pn[j],(unsigned long)pagestartbyte,(unsigned long)bufstart,pagelen,i,sec_start));
		}
		lock=1;
		pncount=pn2count;
		pn2count=0;
		
		pntemp=pn2;
		pn2=pn;
		pn=pntemp;
		
		restemp=res2;
		res2=res;
		res=restemp;
		
		gwf(printk("<0>" "file read for inode:%lu pncount:%u\n",inode->i_ino,pncount));
	}while(pncount);
	
	kfree(pn);
	kfree(pn2);
	kfree(res);
	kfree(res2);
	
	(*off)+=rlen;
	gwf(printk("<0>" "file read ends rlen=%lu len:%lu\n",rlen,len));
	return rlen;
}
示例#17
0
文件: file.c 项目: MohsenKoohi/GSFS
ssize_t GSFS_file_write(struct file *filp, const char __user *buf, size_t len, loff_t *off){
	struct inode		*inode=filp->f_mapping->host;
	struct address_space	*mapping=filp->f_mapping;
	sector_t 		sec_start,
				sec_end,
				sec_len;
	unsigned long 		bufstart,
				bytes_in_first_buf_page,
				bytes_in_last_buf_page,
				pagestartbyte,
				pageendbyte,
				pagelen;
	size_t  		rlen;
	struct page		*res[2],
				*page,
				**pages;
	unsigned int 		i,
				j,
				pages_count,
				start_read,
				end_read;
		
	gwf(printk("<0>" "File write with inode :%lu len:%lu offset:%llu , filepos:%llu, buf:%lx inode_size:%llu, pid:%u\n",inode->i_ino,len,*off,filp->f_pos,(unsigned long)buf,inode->i_size,current->pid));
	if(unlikely(!access_ok(VERIFY_READ,buf,len)))
		return -1;
	
	mutex_lock(&inode->i_mutex);	
	
	if((*off+len)>inode->i_size){
		if((*off+len)>inode->i_sb->s_maxbytes)
			return -1;
		inode->i_size=(*off+len);
		GSFS_truncate(inode);		
	}
	
	if(filp->f_flags & O_APPEND)
		*off=inode->i_size;
	
	current->backing_dev_info=mapping->backing_dev_info;
	file_remove_suid(filp);
	file_update_time(filp);
	//inode_inc_iversion(inode);
	
	sec_start=(*off)>>Block_Size_Bits;
	sec_end=(*off+len-1)>>Block_Size_Bits;
	sec_len=sec_end-sec_start+1;
	
	pages=kzalloc(sizeof(struct page*) * sec_len, GFP_KERNEL);
	
	bytes_in_first_buf_page=Block_Size-((*off)&((unsigned long)Block_Size-1));
	bytes_in_last_buf_page=((*off+len)&((unsigned long)Block_Size-1));
	if(bytes_in_last_buf_page==0)
		bytes_in_last_buf_page=Block_Size;	
	
	start_read=(bytes_in_first_buf_page!=Block_Size)?1:0;
	end_read=(bytes_in_last_buf_page!=Block_Size && inode->i_size>(*off+len))?1:0;

	gwf(printk("<0>" "GSFS write bytes_in_first_buf_page:%lu, bytes_in_last_buf_page:%lu\n",bytes_in_first_buf_page,bytes_in_last_buf_page));
	gwf(printk("<0>" "GSFS write start_read:%u, end_read:%u, sec_start:%lu, sec_end:%lu\n",start_read,end_read,sec_start,sec_end));
	
	if(sec_start==sec_end){
		if(start_read || end_read){
			res[0]=GSFS_get_data_page_of_inode_with_read(inode, sec_start);
			gwf(printk("<0>" "sec_start==sec_end, start_read || end_read , res[0]=%lx",(unsigned long)res[0]));
		}
		else{
			res[0]=GSFS_get_locked_data_page_of_inode_without_read(inode,sec_start);
			if(likely(res[0]))
				unlock_page(res[0]);
			gwf(printk("<0>" "sec_start==sec_end, !(start_read || end_read) , res[0]=%lx",(unsigned long)res[0]));
		}
		res[1]=0;
		if(unlikely(!res[0])){
			gwf(printk("<0>" "GSFS write len:-1\n"));
			mutex_unlock(&inode->i_mutex);
			printk("<1>" "GSFS write len:-1\n");
			
			kfree(pages);
			
			return len;
		}
	}
	else{
		if(start_read){
			res[0]=GSFS_get_data_page_of_inode_with_read(inode, sec_start);
			gwf(printk("<0>" "sec_start!=sec_end, start_read, res[0]=%lx",(unsigned long)res[0]));
		}
		else{
			res[0]=GSFS_get_locked_data_page_of_inode_without_read(inode,sec_start);
			if(likely(res[0]))
				unlock_page(res[0]);
			gwf(printk("<0>" "sec_start!=sec_end, !start_read, res[0]=%lx",(unsigned long)res[0]));
		}
	}
	
	pages_count=0;
	if(sec_len>1)
		for(i=sec_start+1;i<=sec_end-1;i++)
			pages[pages_count++]=GSFS_get_locked_data_page_of_inode_without_read(inode,i);
	
	if(sec_start != sec_end){
		if(end_read){
			res[1]=GSFS_get_data_page_of_inode_with_read(inode,sec_end);
			gwf(printk("<0>" "sec_start!=sec_end, end_read, res[1]=%lx",(unsigned long)res[1]));
		}
		else{
			res[1]=GSFS_get_locked_data_page_of_inode_without_read(inode,sec_end);
			if(likely(res[1]))
				unlock_page(res[1]);
			gwf(printk("<0>" "sec_start!=sec_end, !end_read, res[1]=%lx",(unsigned long)res[1]));
		}
		
		if(unlikely(!res[0] || !res[1])){
			gwf(printk("<0>" "GSFS write len:-1\n"));
			printk("<1>" "GSFS write len:-1\n");
			mutex_unlock(&inode->i_mutex);
			
			kfree(pages);
			
			return len;
		}
	}
	
	rlen=0;
	bufstart=(unsigned long)buf+bytes_in_first_buf_page;
	pagelen=Block_Size;
	
	//100% expected complete pages that should be copied
	pages_count=0;
	if(sec_len>1)
		for(i=sec_start+1;i<=sec_end-1;i++){
			gwf(printk("<0>" "write page complete pages, i:%u, bufstart:%lx, rlen=%lu\n",i,bufstart,rlen));
			
			page=pages[pages_count++];
			if(unlikely(!page))
				goto buf_cont;
			
			j=__copy_from_user_inatomic(page_address(page),(void*)bufstart,pagelen);
			
			rlen+=(Block_Size-j);
			
			mark_page_accessed(page);
			set_page_dirty(page);
			put_page(page);
			
			unlock_page(page);
buf_cont:			
			bufstart+=pagelen;		
		}
	
	//first and last page that are not surely complete
	for(i=0;i<2 && res[i];i++){		
		page=res[i];
		wait_on_page_locked(page);
		lock_page(page);
		if(page->index==sec_start){
			bufstart=(unsigned long)buf;
			pagestartbyte=Block_Size-bytes_in_first_buf_page;
			if(sec_start==sec_end)
				pageendbyte=pagestartbyte+len-1;
			else
				pageendbyte=Block_Size-1;
		}
		else{
			bufstart=(unsigned long)buf+bytes_in_first_buf_page+((sec_len-2)<<Block_Size_Bits);
			pageendbyte=bytes_in_last_buf_page-1;
			pagestartbyte=0;
		}
		gwf(printk("<0>" "gsfs_write for first and last page, i=%u, page:%lx, bufstart:%lx, pagestartbyte:%lu, pageendbyte:%lu\n",
				i,(unsigned long)page,bufstart,pagestartbyte,pageendbyte));
		pagelen=pageendbyte-pagestartbyte+1;
		j=__copy_from_user_inatomic(page_address(page)+pagestartbyte,(void*)bufstart,pagelen);
		rlen+=(pagelen-j);		
		mark_page_accessed(page);
		set_page_dirty(page);
		put_page(page);
		unlock_page(page);		
	}
	
	mutex_unlock(&inode->i_mutex);
	(*off)+=rlen;
	
	gwf(printk("<0>" "GSFS write rlen:%lu\n",rlen));
	
	kfree(pages);
	
	if(filp->f_flags & O_SYNC){
		write_inode_now(inode,1);
	}
	
	return rlen;
}