コード例 #1
0
/*
 * MPSAFE
 */
static int
vn_write(struct file *fp, struct uio *uio, struct ucred *cred, int flags)
{
	struct vnode *vp;
	int error, ioflag;

	KASSERT(uio->uio_td == curthread,
		("uio_td %p is not p %p", uio->uio_td, curthread));
	vp = (struct vnode *)fp->f_data;

	ioflag = IO_UNIT;
	if (vp->v_type == VREG &&
	   ((fp->f_flag & O_APPEND) || (flags & O_FAPPEND))) {
		ioflag |= IO_APPEND;
	}

	if (flags & O_FBLOCKING) {
		/* ioflag &= ~IO_NDELAY; */
	} else if (flags & O_FNONBLOCKING) {
		ioflag |= IO_NDELAY;
	} else if (fp->f_flag & FNONBLOCK) {
		ioflag |= IO_NDELAY;
	}
	if (fp->f_flag & O_DIRECT) {
		ioflag |= IO_DIRECT;
	}
	if (flags & O_FASYNCWRITE) {
		/* ioflag &= ~IO_SYNC; */
	} else if (flags & O_FSYNCWRITE) {
		ioflag |= IO_SYNC;
	} else if (fp->f_flag & O_FSYNC) {
		ioflag |= IO_SYNC;
	}

	if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS))
		ioflag |= IO_SYNC;
	if ((flags & O_FOFFSET) == 0)
		uio->uio_offset = vn_get_fpf_offset(fp);
	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
	ioflag |= sequential_heuristic(uio, fp);
	error = VOP_WRITE(vp, uio, ioflag, cred);
	fp->f_nextoff = uio->uio_offset;
	vn_unlock(vp);
	if ((flags & O_FOFFSET) == 0)
		vn_set_fpf_offset(fp, uio->uio_offset);
	return (error);
}
コード例 #2
0
ファイル: union_vnops.c プロジェクト: AhmadTux/DragonFlyBSD
/*
 * union_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
 *		struct ucred *a_cred)
 */
static int
union_write(struct vop_read_args *ap)
{
	struct union_node *un = VTOUNION(ap->a_vp);
	struct thread *td = ap->a_uio->uio_td;
	struct vnode *uppervp;
	int error;

	if ((uppervp = union_lock_upper(un, td)) == NULLVP)
		panic("union: missing upper layer in write");

	/*
	 * Since our VM pages are associated with our vnode rather then
	 * the real vnode, and since we do not run our reads and writes 
	 * through our own VM cache, we have a VM/VFS coherency problem. 
	 * We solve them by invalidating or flushing the associated VM
	 * pages prior to allowing a normal read or write to occur.
	 *
	 * VM-backed writes (UIO_NOCOPY) have to be converted to normal
	 * writes because we are not cache-coherent.  Normal writes need
	 * to be made coherent with our VM-backing store, which we do by
	 * first flushing any dirty VM pages associated with the write
	 * range, and then destroying any clean VM pages associated with
	 * the write range.
	 */

	if (ap->a_uio->uio_segflg == UIO_NOCOPY) {
		ap->a_uio->uio_segflg = UIO_SYSSPACE;
	} else if (ap->a_vp->v_flag & VOBJBUF) {
		union_vm_coherency(ap->a_vp, ap->a_uio, 1);
	}

	error = VOP_WRITE(uppervp, ap->a_uio, ap->a_ioflag, ap->a_cred);

	/*
	 * the size of the underlying object may be changed by the
	 * write.
	 */
	if (error == 0) {
		off_t cur = ap->a_uio->uio_offset;

		if (cur > un->un_uppersz)
			union_newsize(ap->a_vp, cur, VNOVAL);
	}
	union_unlock_upper(uppervp, td);
	return (error);
}
コード例 #3
0
ファイル: tty_tty.c プロジェクト: AhmadTux/DragonFlyBSD
/*
 * Read from the controlling terminal (/dev/tty).  The tty is refed as
 * of the cttyvp(), but the ref can get ripped out from under us if
 * the controlling terminal is revoked while we are blocked on the lock,
 * so use vget() instead of vn_lock().
 */
static	int
cttywrite(struct dev_write_args *ap)
{
	struct proc *p = curproc;
	struct vnode *ttyvp;
	int error;

	KKASSERT(p);
	ttyvp = cttyvp(p);
	if (ttyvp == NULL)
		return (EIO);
	if ((error = vget(ttyvp, LK_EXCLUSIVE | LK_RETRY)) == 0) {
		error = VOP_WRITE(ttyvp, ap->a_uio, ap->a_ioflag, NOCRED);
		vput(ttyvp);
	}
	return (error);
}
コード例 #4
0
ファイル: nandsim_swap.c プロジェクト: JabirTech/Source
static int
swap_file_write(struct chip_swap *swap, struct block_state *blk_state)
{
	struct block_space *blk_space;
	struct thread *td;
	struct mount *mp;
	struct vnode *vp;
	struct uio auio;
	struct iovec aiov;

	if (swap == NULL || blk_state == NULL)
		return (-1);

	blk_space = blk_state->blk_sp;
	if (blk_state->offset == -1) {
		blk_state->offset = swap->swap_offset;
		swap->swap_offset += swap->blk_size;
	}

	nand_debug(NDBG_SIM,"saving %p[%p] at %x\n",
	    blk_space, blk_space->blk_ptr, blk_state->offset);

	bzero(&aiov, sizeof(aiov));
	bzero(&auio, sizeof(auio));

	aiov.iov_base = blk_space->blk_ptr;
	aiov.iov_len = swap->blk_size;
	td = curthread;
	vp = swap->swap_vp;

	auio.uio_iov = &aiov;
	auio.uio_offset = blk_state->offset;
	auio.uio_segflg = UIO_SYSSPACE;
	auio.uio_rw = UIO_WRITE;
	auio.uio_iovcnt = 1;
	auio.uio_resid = swap->blk_size;
	auio.uio_td = td;

	vn_start_write(vp, &mp, V_WAIT);
	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
	VOP_WRITE(vp, &auio, IO_UNIT, swap->swap_cred);
	VOP_UNLOCK(vp, 0);
	vn_finished_write(mp);

	return (0);
}
コード例 #5
0
/*
 * Update the disk quota in the quota file.
 */
static int
ufs_dqsync(struct vnode *vp, struct ufs_dquot *dq)
{
	struct vnode *dqvp;
	struct iovec aiov;
	struct uio auio;
	int error;

	if (dq == NODQUOT)
		panic("dqsync: dquot");
	if ((dq->dq_flags & DQ_MOD) == 0)
		return (0);
	if ((dqvp = dq->dq_ump->um_quotas[dq->dq_type]) == NULLVP)
		panic("dqsync: file");
	if (vp != dqvp)
		vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY);
	while (dq->dq_flags & DQ_LOCK) {
		dq->dq_flags |= DQ_WANT;
		(void) tsleep((caddr_t)dq, 0, "dqsync", 0);
		if ((dq->dq_flags & DQ_MOD) == 0) {
			if (vp != dqvp)
				vn_unlock(dqvp);
			return (0);
		}
	}
	dq->dq_flags |= DQ_LOCK;
	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
	aiov.iov_base = (caddr_t)&dq->dq_dqb;
	aiov.iov_len = sizeof (struct ufs_dqblk);
	auio.uio_resid = sizeof (struct ufs_dqblk);
	auio.uio_offset = (off_t)(dq->dq_id * sizeof (struct ufs_dqblk));
	auio.uio_segflg = UIO_SYSSPACE;
	auio.uio_rw = UIO_WRITE;
	auio.uio_td = NULL;
	error = VOP_WRITE(dqvp, &auio, 0, dq->dq_ump->um_cred[dq->dq_type]);
	if (auio.uio_resid && error == 0)
		error = EIO;
	if (dq->dq_flags & DQ_WANT)
		wakeup((caddr_t)dq);
	dq->dq_flags &= ~(DQ_MOD|DQ_LOCK|DQ_WANT);
	if (vp != dqvp)
		vn_unlock(dqvp);
	return (error);
}
コード例 #6
0
int
smb_vop_write(vnode_t *vp, uio_t *uiop, int ioflag, uint32_t *lcount,
    cred_t *cr)
{
	int error;

	*lcount = uiop->uio_resid;

	uiop->uio_llimit = MAXOFFSET_T;

	(void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, &smb_ct);
	error = VOP_WRITE(vp, uiop, ioflag, cr, &smb_ct);
	VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, &smb_ct);

	*lcount -= uiop->uio_resid;

	return (error);
}
コード例 #7
0
ファイル: swap.c プロジェクト: jiangxiaoyong/ece344
int swap_out(paddr_t paddr, int swap_index)
{
	int result;
	struct uio u;
//	struct vnode *swap_vnode;

	result = vfs_open(SWAP_DEVICE, O_RDWR, &swap_vnode);
	mk_kuio(&u, paddr, PAGE_SIZE, swap_index * PAGE_SIZE, UIO_WRITE);
	result = VOP_WRITE(swap_vnode, &u);

	if (result) {
		return result;
	}

	vfs_close(swap_vnode);

	return 0;
}
コード例 #8
0
static void swaponepagein(int idx, struct addrspace* as) {
	(void) as;
	// 3. clear their tlb entries if present TODO
	cm_setEntryDirtyState(COREMAP(idx),true);
	struct page* pg = findPageFromCoreMap(COREMAP(idx), idx);
	int spl = splhigh();
	int tlbpos = tlb_probe(pg->pt_pagebase * PAGE_SIZE, 0);
	if (tlbpos >= 0) {
		tlb_write(TLBHI_INVALID(tlbpos), TLBLO_INVALID(), tlbpos);
	} else {
		//kprintf("was not on tlb\n");
	}
	splx(spl);

	int swapPageindex = getOneSwapPage();
	kprintf("Swap in :\tswap= %x,\tpage=%x \n",swapPageindex,pg->pt_virtbase);
	//kprintf("Swap in page Vaddr = %x\n", pg->pt_virtbase);
	struct iovec iov;
	struct uio kuio;
	iov.iov_kbase = (void*) PADDR_TO_KVADDR(cm_getEntryPaddr(idx));
	iov.iov_len = PAGE_SIZE; // length of the memory space
	kuio.uio_iov = &iov;
	kuio.uio_iovcnt = 1;
	kuio.uio_resid = PAGE_SIZE; // amount to write to the file
	kuio.uio_space = NULL;
	kuio.uio_offset = swap_map[swapPageindex].se_paddr * PAGE_SIZE;
	kuio.uio_segflg = UIO_SYSSPACE;
	kuio.uio_rw = UIO_WRITE;
	//kprintf("before write \n");
	// 4. write them to disk
	spinlock_release(&coremap_lock);
	int result = VOP_WRITE(swap_vnode, &kuio);
	spinlock_acquire(&coremap_lock);
	if (result) {
		// release lock on the vnode
		panic("WRITE FAILED!\n");
		return;
	}
	cm_setEntryDirtyState(COREMAP(idx),false);
	//kprintf("write complete\n");

	pg->pt_state = PT_STATE_SWAPPED;
	pg->pt_pagebase = swap_map[swapPageindex].se_paddr;
}
コード例 #9
0
static int
unionfs_write(void *v)
{
	struct vop_write_args *ap = v;
	int		error;
	struct unionfs_node *unp;
	struct vnode   *tvp;

	/* UNIONFS_INTERNAL_DEBUG("unionfs_write: enter\n"); */

	unp = VTOUNIONFS(ap->a_vp);
	tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);

	error = VOP_WRITE(tvp, ap->a_uio, ap->a_ioflag, ap->a_cred);

	/* UNIONFS_INTERNAL_DEBUG("unionfs_write: leave (%d)\n", error); */

	return (error);
}
コード例 #10
0
ファイル: file_syscalls.c プロジェクト: babuprasad/os161
int
write(int fd, userptr_t buf, size_t buflen, int *err)
{
	int ret;
	if ( fd < 0 || fd > OPEN_MAX)
	{
		*err = EBADF;
		return -1;
	}
	if (curthread->ft[fd] == NULL)
	{
		*err = EBADF;
		return -1;
	}
	if (buf == NULL)
	{
		*err = EFAULT;
		return -1;
	}
	lock_acquire(curthread->ft[fd]->lock);
	struct iovec iov;
	struct uio uio;
	iov.iov_ubase = buf;
	iov.iov_len = buflen;
	uio.uio_iov = &iov;
	uio.uio_iovcnt = 1;
	uio.uio_offset = curthread->ft[fd]->offset;
	uio.uio_resid = buflen;
	uio.uio_segflg = UIO_USERSPACE;
	uio.uio_space = curthread->t_addrspace;
	uio.uio_rw=UIO_WRITE;
	if((ret = VOP_WRITE(curthread->ft[fd]->vn,&uio))!=0)
	{
		*err = ret;
		return -1;
	}
	int diff = uio.uio_offset - curthread->ft[fd]->offset ;
	curthread->ft[fd]->offset=uio.uio_offset;
	lock_release(curthread->ft[fd]->lock);
	*err=0;
	return diff;
}
コード例 #11
0
static int zfsfuse_write(fuse_req_t req, fuse_ino_t ino, const char *buf, size_t size, off_t off, struct fuse_file_info *fi)
{
	file_info_t *info = (file_info_t *)(uintptr_t) fi->fh;

	vnode_t *vp = info->vp;
	ASSERT(vp != NULL);
	ASSERT(VTOZ(vp) != NULL);
	ASSERT(VTOZ(vp)->z_id == ino);

	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	ZFS_ENTER(zfsvfs);

	iovec_t iovec;
	uio_t uio;
	uio.uio_iov = &iovec;
	uio.uio_iovcnt = 1;
	uio.uio_segflg = UIO_SYSSPACE;
	uio.uio_fmode = 0;
	uio.uio_llimit = RLIM64_INFINITY;

	iovec.iov_base = (void *) buf;
	iovec.iov_len = size;
	uio.uio_resid = iovec.iov_len;
	uio.uio_loffset = off;

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	int error = VOP_WRITE(vp, &uio, info->flags, &cred, NULL);

	ZFS_EXIT(zfsvfs);

	if(!error) {
		/* When not using direct_io, we must always write 'size' bytes */
		VERIFY(uio.uio_resid == 0);
		fuse_reply_write(req, size - uio.uio_resid);
	}

	return error;
}
コード例 #12
0
ファイル: swap.c プロジェクト: Adam-Koza/A3
/*
 * swap_io: Does one swap I/O. Panics on failure.
 *
 * Synchronization: none specifically. The physical page should be
 * marked "pinned" (locked) so it won't be touched by other people.
 */
static
void
swap_io(paddr_t pa, off_t swapaddr, enum uio_rw rw)
{
	struct iovec iov;
	struct uio u;
	vaddr_t va;
	int result;

	KASSERT(lock_do_i_hold(global_paging_lock));

	KASSERT(pa != INVALID_PADDR);
	KASSERT(swapaddr % PAGE_SIZE == 0);
	KASSERT(coremap_pageispinned(pa));
	KASSERT(bitmap_isset(swapmap, swapaddr / PAGE_SIZE));

	va = coremap_map_swap_page(pa);

	uio_kinit(&iov, &u, (char *)va, PAGE_SIZE, swapaddr, rw);
	if (rw==UIO_READ) {
		result = VOP_READ(swapstore, &u);
	}
	else {
		result = VOP_WRITE(swapstore, &u);
	}

	coremap_unmap_swap_page(va, pa);

	if (result==EIO) {
		panic("swap: EIO on swapfile (offset %ld)\n",
		      (long)swapaddr);
	}
	else if (result==EINVAL) {
		panic("swap: EINVAL from swapfile (offset %ld)\n",
		      (long)swapaddr);
	}
	else if (result) {
		panic("swap: Error %d from swapfile (offset %ld)\n",
		      result, (long)swapaddr);
	}
}
コード例 #13
0
ファイル: file.c プロジェクト: klevstul/CSE-9201-OS
int sys_write(int filehandle, userptr_t buf, size_t size, int *retval)
{
  	struct uio io;
	int r;
	
	r = check_fd_access(filehandle, curthread->t_fdt, F_WRITE);
	if (r) return r;
	
	mk_uio(&io, buf, size, 
	       curthread->t_fdt->fd[filehandle]->fp,
	       UIO_WRITE);
	
	r = VOP_WRITE(curthread->t_fdt->fd[filehandle]->vn, &io);
	if (r) {
	  return r;
	}
	*retval = io.uio_offset - curthread->t_fdt->fd[filehandle]->fp;
	curthread->t_fdt->fd[filehandle]->fp = io.uio_offset;
	
	return 0;	
}
コード例 #14
0
ファイル: xfs_file.c プロジェクト: BackupTheBerlios/arp2-svn
STATIC inline ssize_t
__xfs_file_write(
	struct kiocb	*iocb,
	const char	__user *buf,
	int		ioflags,
	size_t		count,
	loff_t		pos)
{
	struct iovec	iov = {(void __user *)buf, count};
	struct file	*file = iocb->ki_filp;
	struct inode	*inode = file->f_mapping->host;
	vnode_t		*vp = vn_from_inode(inode);
	ssize_t		rval;

	BUG_ON(iocb->ki_pos != pos);
	if (unlikely(file->f_flags & O_DIRECT))
		ioflags |= IO_ISDIRECT;

	VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
	return rval;
}
コード例 #15
0
ファイル: write.c プロジェクト: NickStephens/os161
int
sys_write(int fd, const void *buf, size_t nbytes)
{
	struct sys_filemapping *mpg;	
	struct uio ku;
	char *kbuf;
	int result;

	mpg = resolvefd(fd);
	if (mpg==NULL)
		return -EBADF;

	/* check flags */
	if (!((mpg->flags & O_WRONLY) || (mpg->flags & O_RDWR)))
		return -1;


	kbuf = (char *) kmalloc(nbytes);
	if (kbuf==NULL)
		return -ENOMEM;


	result = copyin(buf, kbuf, nbytes);
	if (result)
	{
		kfree(kbuf);
		return -result;
	}

	mk_kuio(&ku, kbuf, nbytes, mpg->offset, UIO_WRITE);
	result = VOP_WRITE(mpg->vn, &ku);

	if (result)
		return -result;

	mpg->offset += nbytes;

	kfree(kbuf);
	return nbytes;
}
コード例 #16
0
int _write(int filehandle,void *buf, size_t size,int* retval){
	
	if(filehandle < 0 || filehandle > MAX_FILE_FILETAB){
		*retval = -1;
		return EBADF;
	}	
	if(curthread->fdesc[filehandle] == NULL)
	{
		*retval = -1;
		return EBADF;
	}
	if(! (curthread->fdesc[filehandle]->flags != O_WRONLY || curthread->fdesc[filehandle]->flags!=O_RDWR) )
	{
		*retval = -1;
		return EINVAL;
	}
	lock_acquire(curthread->fdesc[filehandle]->f_lock);
       
	struct uio writeuio;
	struct iovec iov;
	size_t size1;
	char *buffer = (char*)kmalloc(size);
	copyinstr((userptr_t)buf,buffer,strlen(buffer),&size1);
	
	uio_kinit(&iov, &writeuio, (void*) buffer, size, curthread->fdesc[filehandle]->offset, UIO_WRITE);
	int result=VOP_WRITE(curthread->fdesc[filehandle]->vnode, &writeuio);
        if (result) {
		kfree(buffer);
		lock_release(curthread->fdesc[filehandle]->f_lock);
		*retval = -1; 
                return result;
        }
	curthread->fdesc[filehandle]->offset = writeuio.uio_offset;
	*retval = size - writeuio.uio_resid;
	kfree(buffer);
	lock_release(curthread->fdesc[filehandle]->f_lock);
        return 0;
}
コード例 #17
0
ファイル: file_syscalls.c プロジェクト: deerishi/old_pc_OS161
int
sys_write(int fdesc,userptr_t ubuf,unsigned int nbytes,int *retval)
{
  struct iovec iov;
  struct uio u;
  int res;

  //DEBUG(DB_SYSCALL,"Syscall: write(%d,%x,%d)\n",fdesc,(unsigned int)ubuf,nbytes);
  
  /* only stdout and stderr writes are currently implemented */
  if (!((fdesc==STDOUT_FILENO)||(fdesc==STDERR_FILENO))) {
    return EUNIMP;
  }
  KASSERT(curproc != NULL);
  KASSERT(curproc->console != NULL);
  KASSERT(curproc->p_addrspace != NULL);

  /* set up a uio structure to refer to the user program's buffer (ubuf) */
  iov.iov_ubase = ubuf;
  iov.iov_len = nbytes;
  u.uio_iov = &iov;
  u.uio_iovcnt = 1;
  u.uio_offset = 0;  /* not needed for the console */
  u.uio_resid = nbytes;
  u.uio_segflg = UIO_USERSPACE;
  u.uio_rw = UIO_WRITE;
  u.uio_space = curproc->p_addrspace;

  res = VOP_WRITE(curproc->console,&u);
  if (res) {
    return res;
  }

  /* pass back the number of bytes actually written */
  *retval = nbytes - u.uio_resid;
  KASSERT(*retval >= 0);
  return 0;
}
コード例 #18
0
ファイル: xfs_file.c プロジェクト: BackupTheBerlios/arp2-svn
STATIC inline ssize_t
__xfs_file_writev(
	struct file		*file,
	const struct iovec 	*iov,
	int			ioflags,
	unsigned long		nr_segs,
	loff_t			*ppos)
{
	struct inode	*inode = file->f_mapping->host;
	vnode_t		*vp = vn_from_inode(inode);
	struct kiocb	kiocb;
	ssize_t		rval;

	init_sync_kiocb(&kiocb, file);
	kiocb.ki_pos = *ppos;
	if (unlikely(file->f_flags & O_DIRECT))
		ioflags |= IO_ISDIRECT;

	VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);

	*ppos = kiocb.ki_pos;
	return rval;
}
コード例 #19
0
ファイル: swap.c プロジェクト: akileshsadassivam/os-161
int
write_page(void* kbuf, off_t* newoffset, int index){
	(void)index;
	struct iovec iovectr;
	struct uio uiovar;
	off_t offset;

	KASSERT(sw_vn != NULL);

	offset = index * PAGE_SIZE;
	uio_kinit(&iovectr, &uiovar, kbuf, PAGE_SIZE, offset, UIO_WRITE);

	spinlock_release(&cm_lock);
	int ret = VOP_WRITE(sw_vn, &uiovar);
	spinlock_acquire(&cm_lock);

	if(ret){
		return 1;
	}

	*newoffset = offset;
	return 0;
}
コード例 #20
0
ファイル: vfs_vnops.c プロジェクト: AhmadTux/DragonFlyBSD
/*
 * Package up an I/O request on a vnode into a uio and do it.
 *
 * MPSAFE
 */
int
vn_rdwr(enum uio_rw rw, struct vnode *vp, caddr_t base, int len,
	off_t offset, enum uio_seg segflg, int ioflg, 
	struct ucred *cred, int *aresid)
{
	struct uio auio;
	struct iovec aiov;
	struct ccms_lock ccms_lock;
	int error;

	if ((ioflg & IO_NODELOCKED) == 0)
		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
	aiov.iov_base = base;
	aiov.iov_len = len;
	auio.uio_resid = len;
	auio.uio_offset = offset;
	auio.uio_segflg = segflg;
	auio.uio_rw = rw;
	auio.uio_td = curthread;
	ccms_lock_get_uio(&vp->v_ccms, &ccms_lock, &auio);
	if (rw == UIO_READ) {
		error = VOP_READ(vp, &auio, ioflg, cred);
	} else {
		error = VOP_WRITE(vp, &auio, ioflg, cred);
	}
	ccms_lock_put(&vp->v_ccms, &ccms_lock);
	if (aresid)
		*aresid = auio.uio_resid;
	else
		if (auio.uio_resid && error == 0)
			error = EIO;
	if ((ioflg & IO_NODELOCKED) == 0)
		vn_unlock(vp);
	return (error);
}
コード例 #21
0
ファイル: swap.c プロジェクト: script3r/os161
static
void
swap_io( paddr_t paddr, off_t offset, enum uio_rw op ) {
	struct iovec		iov;
	struct uio		uio;
	vaddr_t			vaddr;
	int			res;
	
	KASSERT( lock_do_i_hold( giant_paging_lock ) );
	KASSERT( curthread->t_vmp_count == 0 || curthread->t_clone );

	//get the virtual address.
	vaddr = PADDR_TO_KVADDR( paddr );

	//init the uio request.
	uio_kinit( &iov, &uio, (char *)vaddr, PAGE_SIZE, offset, op );
	
	//perform the request.
	res = (op == UIO_READ) ? VOP_READ( vn_sw, &uio ) : VOP_WRITE( vn_sw, &uio );
	
	//if we have a problem ... bail.
	if( res )
		panic( "swap_io: failed to perform a VOP." );
}
コード例 #22
0
ファイル: vfs_vnops.c プロジェクト: orumin/openbsd-efivars
/*
 * Package up an I/O request on a vnode into a uio and do it.
 */
int
vn_rdwr(enum uio_rw rw, struct vnode *vp, caddr_t base, int len, off_t offset,
    enum uio_seg segflg, int ioflg, struct ucred *cred, size_t *aresid,
    struct proc *p)
{
	struct uio auio;
	struct iovec aiov;
	int error;

	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
	aiov.iov_base = base;
	aiov.iov_len = len;
	auio.uio_resid = len;
	auio.uio_offset = offset;
	auio.uio_segflg = segflg;
	auio.uio_rw = rw;
	auio.uio_procp = p;

	if ((ioflg & IO_NODELOCKED) == 0)
		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
	if (rw == UIO_READ) {
		error = VOP_READ(vp, &auio, ioflg, cred);
	} else {
		error = VOP_WRITE(vp, &auio, ioflg, cred);
	}
	if ((ioflg & IO_NODELOCKED) == 0)
		VOP_UNLOCK(vp, 0, p);

	if (aresid)
		*aresid = auio.uio_resid;
	else
		if (auio.uio_resid && error == 0)
			error = EIO;
	return (error);
}
コード例 #23
0
ファイル: vnode_pager.c プロジェクト: kwitaszczyk/freebsd
/*
 * This is now called from local media FS's to operate against their
 * own vnodes if they fail to implement VOP_PUTPAGES.
 *
 * This is typically called indirectly via the pageout daemon and
 * clustering has already typically occurred, so in general we ask the
 * underlying filesystem to write the data out asynchronously rather
 * then delayed.
 */
int
vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *ma, int bytecount,
    int flags, int *rtvals)
{
	int i;
	vm_object_t object;
	vm_page_t m;
	int count;

	int maxsize, ncount;
	vm_ooffset_t poffset;
	struct uio auio;
	struct iovec aiov;
	int error;
	int ioflags;
	int ppscheck = 0;
	static struct timeval lastfail;
	static int curfail;

	object = vp->v_object;
	count = bytecount / PAGE_SIZE;

	for (i = 0; i < count; i++)
		rtvals[i] = VM_PAGER_ERROR;

	if ((int64_t)ma[0]->pindex < 0) {
		printf("vnode_pager_putpages: attempt to write meta-data!!! -- 0x%lx(%lx)\n",
		    (long)ma[0]->pindex, (u_long)ma[0]->dirty);
		rtvals[0] = VM_PAGER_BAD;
		return VM_PAGER_BAD;
	}

	maxsize = count * PAGE_SIZE;
	ncount = count;

	poffset = IDX_TO_OFF(ma[0]->pindex);

	/*
	 * If the page-aligned write is larger then the actual file we
	 * have to invalidate pages occurring beyond the file EOF.  However,
	 * there is an edge case where a file may not be page-aligned where
	 * the last page is partially invalid.  In this case the filesystem
	 * may not properly clear the dirty bits for the entire page (which
	 * could be VM_PAGE_BITS_ALL due to the page having been mmap()d).
	 * With the page locked we are free to fix-up the dirty bits here.
	 *
	 * We do not under any circumstances truncate the valid bits, as
	 * this will screw up bogus page replacement.
	 */
	VM_OBJECT_WLOCK(object);
	if (maxsize + poffset > object->un_pager.vnp.vnp_size) {
		if (object->un_pager.vnp.vnp_size > poffset) {
			int pgoff;

			maxsize = object->un_pager.vnp.vnp_size - poffset;
			ncount = btoc(maxsize);
			if ((pgoff = (int)maxsize & PAGE_MASK) != 0) {
				/*
				 * If the object is locked and the following
				 * conditions hold, then the page's dirty
				 * field cannot be concurrently changed by a
				 * pmap operation.
				 */
				m = ma[ncount - 1];
				vm_page_assert_sbusied(m);
				KASSERT(!pmap_page_is_write_mapped(m),
		("vnode_pager_generic_putpages: page %p is not read-only", m));
				vm_page_clear_dirty(m, pgoff, PAGE_SIZE -
				    pgoff);
			}
		} else {
			maxsize = 0;
			ncount = 0;
		}
		if (ncount < count) {
			for (i = ncount; i < count; i++) {
				rtvals[i] = VM_PAGER_BAD;
			}
		}
	}
	VM_OBJECT_WUNLOCK(object);

	/*
	 * pageouts are already clustered, use IO_ASYNC to force a bawrite()
	 * rather then a bdwrite() to prevent paging I/O from saturating 
	 * the buffer cache.  Dummy-up the sequential heuristic to cause
	 * large ranges to cluster.  If neither IO_SYNC or IO_ASYNC is set,
	 * the system decides how to cluster.
	 */
	ioflags = IO_VMIO;
	if (flags & (VM_PAGER_PUT_SYNC | VM_PAGER_PUT_INVAL))
		ioflags |= IO_SYNC;
	else if ((flags & VM_PAGER_CLUSTER_OK) == 0)
		ioflags |= IO_ASYNC;
	ioflags |= (flags & VM_PAGER_PUT_INVAL) ? IO_INVAL: 0;
	ioflags |= (flags & VM_PAGER_PUT_NOREUSE) ? IO_NOREUSE : 0;
	ioflags |= IO_SEQMAX << IO_SEQSHIFT;

	aiov.iov_base = (caddr_t) 0;
	aiov.iov_len = maxsize;
	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
	auio.uio_offset = poffset;
	auio.uio_segflg = UIO_NOCOPY;
	auio.uio_rw = UIO_WRITE;
	auio.uio_resid = maxsize;
	auio.uio_td = (struct thread *) 0;
	error = VOP_WRITE(vp, &auio, ioflags, curthread->td_ucred);
	PCPU_INC(cnt.v_vnodeout);
	PCPU_ADD(cnt.v_vnodepgsout, ncount);

	if (error) {
		if ((ppscheck = ppsratecheck(&lastfail, &curfail, 1)))
			printf("vnode_pager_putpages: I/O error %d\n", error);
	}
	if (auio.uio_resid) {
		if (ppscheck || ppsratecheck(&lastfail, &curfail, 1))
			printf("vnode_pager_putpages: residual I/O %zd at %lu\n",
			    auio.uio_resid, (u_long)ma[0]->pindex);
	}
	for (i = 0; i < ncount; i++) {
		rtvals[i] = VM_PAGER_OK;
	}
	return rtvals[0];
}
コード例 #24
0
static int
zfs_replay_write(void *arg1, char *arg2, boolean_t byteswap)
{
	zfsvfs_t *zfsvfs = (zfsvfs_t *)arg1;
	lr_write_t *lr = (lr_write_t *)arg2;
	char *data = (char *)(lr + 1);	/* data follows lr_write_t */
	znode_t	*zp;
	int error;
#ifndef LINUX_PORT
	ssize_t resid;
#else 
	uio_t uio;
	int vflg = 0;
	struct iovec iov;
#endif
	if (byteswap)
		byteswap_uint64_array(lr, sizeof (*lr));
	if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) {
		/*
		 * As we can log writes out of order, it's possible the
		 * file has been removed. In this case just drop the write
		 * and return success.
		 */
		if (error == ENOENT)
			error = 0;
		return (error);
	}
#ifndef LINUX_PORT
	offset = lr->lr_offset;
	length = lr->lr_length;
	iov.iov_base = (void *) data;
	iov.iov_len = lr->lr_length;
	 /* This may be a write from a dmu_sync() for a whole block,
	 * and may extend beyond the current end of the file.
	 * We can't just replay what was written for this TX_WRITE as
	 * a future TX_WRITE2 may extend the eof and the data for that
	 * write needs to be there. So we write the whole block and
	 * reduce the eof. This needs to be done within the single dmu
	 * transaction created within vn_rdwr -> zfs_write. So a possible
	 * new end of file is passed through in zfsvfs->z_replay_eof
	 */

	zfsvfs->z_replay_eof = 0; /* 0 means don't change end of file */

	/* If it's a dmu_sync() block, write the whole block */
	if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
		uint64_t blocksize = BP_GET_LSIZE(&lr->lr_blkptr);
		if (length < blocksize) {
			offset -= offset % blocksize;
			length = blocksize;
		}
		if (zp->z_size < eod)
			zfsvfs->z_replay_eof = eod;
	}

	error = vn_rdwr(UIO_WRITE, ZTOV(zp), data, length, offset,
	    UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid);
#else
        iov.iov_base = (void *) data;
        iov.iov_len = lr->lr_length;

        uio.uio_iov = &iov;
        uio.uio_resid = lr->lr_length;
        uio.uio_iovcnt = 1;
        uio.uio_loffset = (offset_t)lr->lr_offset;
        uio.uio_limit = MAXOFFSET_T;
        uio.uio_segflg = UIO_SYSSPACE;
        error = VOP_WRITE(ZTOV(zp), &uio, vflg, NULL , NULL);
#endif
	VN_RELE(ZTOV(zp));
	zfsvfs->z_replay_eof = 0;	/* safety */

	return (error);
}
コード例 #25
0
ファイル: ufs_quota.c プロジェクト: jaredmcneill/freebsd
/*
 * Update the disk quota in the quota file.
 */
static int
dqsync(struct vnode *vp, struct dquot *dq)
{
    uint8_t buf[sizeof(struct dqblk64)];
    off_t base, recsize;
    struct vnode *dqvp;
    struct iovec aiov;
    struct uio auio;
    int error;
    struct mount *mp;
    struct ufsmount *ump;

#ifdef DEBUG_VFS_LOCKS
    if (vp != NULL)
        ASSERT_VOP_ELOCKED(vp, "dqsync");
#endif

    mp = NULL;
    error = 0;
    if (dq == NODQUOT)
        panic("dqsync: dquot");
    if ((ump = dq->dq_ump) == NULL)
        return (0);
    UFS_LOCK(ump);
    if ((dqvp = ump->um_quotas[dq->dq_type]) == NULLVP) {
        if (vp == NULL) {
            UFS_UNLOCK(ump);
            return (0);
        } else
            panic("dqsync: file");
    }
    vref(dqvp);
    UFS_UNLOCK(ump);

    DQI_LOCK(dq);
    if ((dq->dq_flags & DQ_MOD) == 0) {
        DQI_UNLOCK(dq);
        vrele(dqvp);
        return (0);
    }
    DQI_UNLOCK(dq);

    (void) vn_start_secondary_write(dqvp, &mp, V_WAIT);
    if (vp != dqvp)
        vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY);

    DQI_LOCK(dq);
    DQI_WAIT(dq, PINOD+2, "dqsync");
    if ((dq->dq_flags & DQ_MOD) == 0)
        goto out;
    dq->dq_flags |= DQ_LOCK;
    DQI_UNLOCK(dq);

    /*
     * Write the quota record to the quota file, performing any
     * necessary conversions.  See dqget() for additional details.
     */
    if (ump->um_qflags[dq->dq_type] & QTF_64BIT) {
        dq_dqb64(dq, (struct dqblk64 *)buf);
        recsize = sizeof(struct dqblk64);
        base = sizeof(struct dqhdr64);
    } else {
        dq_dqb32(dq, (struct dqblk32 *)buf);
        recsize = sizeof(struct dqblk32);
        base = 0;
    }

    auio.uio_iov = &aiov;
    auio.uio_iovcnt = 1;
    aiov.iov_base = buf;
    aiov.iov_len = recsize;
    auio.uio_resid = recsize;
    auio.uio_offset = base + dq->dq_id * recsize;
    auio.uio_segflg = UIO_SYSSPACE;
    auio.uio_rw = UIO_WRITE;
    auio.uio_td = (struct thread *)0;
    error = VOP_WRITE(dqvp, &auio, 0, dq->dq_ump->um_cred[dq->dq_type]);
    if (auio.uio_resid && error == 0)
        error = EIO;

    DQI_LOCK(dq);
    DQI_WAKEUP(dq);
    dq->dq_flags &= ~DQ_MOD;
out:
    DQI_UNLOCK(dq);
    if (vp != dqvp)
        vput(dqvp);
    else
        vrele(dqvp);
    vn_finished_secondary_write(mp);
    return (error);
}
コード例 #26
0
/*
 * Write a directory entry after a call to namei, using the parameters
 * that it left in nameidata.  The argument ip is the inode which the new
 * directory entry will refer to.  Dvp is a pointer to the directory to
 * be written, which was left locked by namei. Remaining parameters
 * (ulr_offset, ulr_count) indicate how the space for the new
 * entry is to be obtained.
 */
int
ext2fs_direnter(struct inode *ip, struct vnode *dvp,
		const struct ufs_lookup_results *ulr,
		struct componentname *cnp)
{
	struct ext2fs_direct *ep, *nep;
	struct inode *dp;
	struct buf *bp;
	struct ext2fs_direct newdir;
	struct iovec aiov;
	struct uio auio;
	u_int dsize;
	int error, loc, newentrysize, spacefree;
	char *dirbuf;
	struct ufsmount *ump = VFSTOUFS(dvp->v_mount);
	int dirblksiz = ump->um_dirblksiz;

	dp = VTOI(dvp);

	newdir.e2d_ino = h2fs32(ip->i_number);
	newdir.e2d_namlen = cnp->cn_namelen;
	if (ip->i_e2fs->e2fs.e2fs_rev > E2FS_REV0 &&
	    (ip->i_e2fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) {
		newdir.e2d_type = inot2ext2dt(IFTODT(ip->i_e2fs_mode));
	} else {
		newdir.e2d_type = 0;
	}
	memcpy(newdir.e2d_name, cnp->cn_nameptr, (unsigned)cnp->cn_namelen + 1);
	newentrysize = EXT2FS_DIRSIZ(cnp->cn_namelen);
	if (ulr->ulr_count == 0) {
		/*
		 * If ulr_count is 0, then namei could find no
		 * space in the directory. Here, ulr_offset will
		 * be on a directory block boundary and we will write the
		 * new entry into a fresh block.
		 */
		if (ulr->ulr_offset & (dirblksiz - 1))
			panic("ext2fs_direnter: newblk");
		auio.uio_offset = ulr->ulr_offset;
		newdir.e2d_reclen = h2fs16(dirblksiz);
		auio.uio_resid = newentrysize;
		aiov.iov_len = newentrysize;
		aiov.iov_base = (void *)&newdir;
		auio.uio_iov = &aiov;
		auio.uio_iovcnt = 1;
		auio.uio_rw = UIO_WRITE;
		UIO_SETUP_SYSSPACE(&auio);
		error = VOP_WRITE(dvp, &auio, IO_SYNC, cnp->cn_cred);
		if (dirblksiz > dvp->v_mount->mnt_stat.f_bsize)
			/* XXX should grow with balloc() */
			panic("ext2fs_direnter: frag size");
		else if (!error) {
			error = ext2fs_setsize(dp,
				roundup(ext2fs_size(dp), dirblksiz));
			if (error)
				return (error);
			dp->i_flag |= IN_CHANGE;
			uvm_vnp_setsize(dvp, ext2fs_size(dp));
		}
		return (error);
	}

	/*
	 * If ulr_count is non-zero, then namei found space
	 * for the new entry in the range ulr_offset to
	 * ulr_offset + ulr_count in the directory.
	 * To use this space, we may have to compact the entries located
	 * there, by copying them together towards the beginning of the
	 * block, leaving the free space in one usable chunk at the end.
	 */

	/*
	 * Get the block containing the space for the new directory entry.
	 */
	if ((error = ext2fs_blkatoff(dvp, (off_t)ulr->ulr_offset, &dirbuf, &bp)) != 0)
		return (error);
	/*
	 * Find space for the new entry. In the simple case, the entry at
	 * offset base will have the space. If it does not, then namei
	 * arranged that compacting the region ulr_offset to
	 * ulr_offset + ulr_count would yield the
	 * space.
	 */
	ep = (struct ext2fs_direct *)dirbuf;
	dsize = EXT2FS_DIRSIZ(ep->e2d_namlen);
	spacefree = fs2h16(ep->e2d_reclen) - dsize;
	for (loc = fs2h16(ep->e2d_reclen); loc < ulr->ulr_count; ) {
		nep = (struct ext2fs_direct *)(dirbuf + loc);
		if (ep->e2d_ino) {
			/* trim the existing slot */
			ep->e2d_reclen = h2fs16(dsize);
			ep = (struct ext2fs_direct *)((char *)ep + dsize);
		} else {
			/* overwrite; nothing there; header is ours */
			spacefree += dsize;
		}
		dsize = EXT2FS_DIRSIZ(nep->e2d_namlen);
		spacefree += fs2h16(nep->e2d_reclen) - dsize;
		loc += fs2h16(nep->e2d_reclen);
		memcpy((void *)ep, (void *)nep, dsize);
	}
	/*
	 * Update the pointer fields in the previous entry (if any),
	 * copy in the new entry, and write out the block.
	 */
	if (ep->e2d_ino == 0) {
#ifdef DIAGNOSTIC
		if (spacefree + dsize < newentrysize)
			panic("ext2fs_direnter: compact1");
#endif
		newdir.e2d_reclen = h2fs16(spacefree + dsize);
	} else {
#ifdef DIAGNOSTIC
		if (spacefree < newentrysize) {
			printf("ext2fs_direnter: compact2 %u %u",
			    (u_int)spacefree, (u_int)newentrysize);
			panic("ext2fs_direnter: compact2");
		}
#endif
		newdir.e2d_reclen = h2fs16(spacefree);
		ep->e2d_reclen = h2fs16(dsize);
		ep = (struct ext2fs_direct *)((char *)ep + dsize);
	}
	memcpy((void *)ep, (void *)&newdir, (u_int)newentrysize);
	error = VOP_BWRITE(bp->b_vp, bp);
	dp->i_flag |= IN_CHANGE | IN_UPDATE;
	if (!error && ulr->ulr_endoff && ulr->ulr_endoff < ext2fs_size(dp))
		error = ext2fs_truncate(dvp, (off_t)ulr->ulr_endoff, IO_SYNC,
		    cnp->cn_cred);
	return (error);
}
int
sys_write(int fdesc,userptr_t ubuf,unsigned int nbytes,int *retval)
{
  struct iovec iov;
  struct uio u;
	struct filedescriptor *fDescriptor;
  int res;
	int bytesWrite;

	if(!ubuf){
		return EFAULT;
	}


	fDescriptor = getFileDescriptor(fdesc, curthread->t_fdManager);
	if(fDescriptor == NULL){
		return EBADF;
	}

  DEBUG(DB_SYSCALL,"Syscall: write(%d,%x,%d)\n",fdesc,(unsigned int)ubuf,nbytes);
  
  /* only stdout and stderr writes are currently implemented */
  if (!((fdesc==STDOUT_FILENO)||(fdesc==STDERR_FILENO))) {
    return EUNIMP;
  }
  KASSERT(curproc != NULL);
  KASSERT(curproc->console != NULL);
  KASSERT(curproc->p_addrspace != NULL);

  /* set up a uio structure to refer to the user program's buffer (ubuf) */
  iov.iov_ubase = ubuf;
  iov.iov_len = nbytes;
  u.uio_iov = &iov;
  u.uio_iovcnt = 1;
  u.uio_offset = fDescriptor->fdoff;  /* not needed for the console */
  u.uio_resid = nbytes;
  u.uio_segflg = UIO_USERSPACE;
  u.uio_rw = UIO_WRITE;
  u.uio_space = curproc->p_addrspace;

	bytesWrite = u.uio_resid;

	lock_acquire(fDescriptor->fdlock);
  res = VOP_WRITE(fDescriptor->fdvnode,&u);
	lock_release(fDescriptor->fdlock);

	bytesWrite = u.uio_resid;
	if(bytesWrite==0){
		return 0;
	}

  if (res) {
    return res;
  }

  /* pass back the number of bytes actually written */
  *retval = nbytes - u.uio_resid;
  KASSERT(*retval >= 0);
	fDescriptor->fdoff += nbytes;

  return 0;
}
コード例 #28
0
ファイル: ufs_extattr.c プロジェクト: markjdb/freebsd-dev
/*
 * Real work associated with removing an extended attribute from a vnode.
 * Assumes the attribute lock has already been grabbed.
 */
static int
ufs_extattr_rm(struct vnode *vp, int attrnamespace, const char *name,
    struct ucred *cred, struct thread *td)
{
	struct ufs_extattr_list_entry *attribute;
	struct ufs_extattr_header ueh;
	struct iovec local_aiov;
	struct uio local_aio;
	struct mount *mp = vp->v_mount;
	struct ufsmount *ump = VFSTOUFS(mp);
	struct inode *ip = VTOI(vp);
	off_t base_offset;
	int error = 0, ioflag;

	if (vp->v_mount->mnt_flag & MNT_RDONLY)  
		return (EROFS);
	if (!(ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_STARTED))
		return (EOPNOTSUPP);
	if (!ufs_extattr_valid_attrname(attrnamespace, name))
		return (EINVAL);

	error = extattr_check_cred(vp, attrnamespace, cred, td, VWRITE);
	if (error)
		return (error);

	attribute = ufs_extattr_find_attr(ump, attrnamespace, name);
	if (!attribute)
		return (ENOATTR);

	/*
	 * Find base offset of header in file based on file header size, and
	 * data header size + maximum data size, indexed by inode number.
	 */
	base_offset = sizeof(struct ufs_extattr_fileheader) +
	    ip->i_number * (sizeof(struct ufs_extattr_header) +
	    attribute->uele_fileheader.uef_size);

	/*
	 * Check to see if currently defined.
	 */
	bzero(&ueh, sizeof(struct ufs_extattr_header));

	local_aiov.iov_base = (caddr_t) &ueh;
	local_aiov.iov_len = sizeof(struct ufs_extattr_header);
	local_aio.uio_iov = &local_aiov;
	local_aio.uio_iovcnt = 1;
	local_aio.uio_rw = UIO_READ;
	local_aio.uio_segflg = UIO_SYSSPACE;
	local_aio.uio_td = td;
	local_aio.uio_offset = base_offset;
	local_aio.uio_resid = sizeof(struct ufs_extattr_header);

	/*
	 * Don't need to get the lock on the backing vnode if the vnode we're
	 * modifying is it, as we already hold the lock.
	 */
	if (attribute->uele_backing_vnode != vp)
		vn_lock(attribute->uele_backing_vnode, LK_EXCLUSIVE | LK_RETRY);

	error = VOP_READ(attribute->uele_backing_vnode, &local_aio,
	    IO_NODELOCKED, ump->um_extattr.uepm_ucred);
	if (error)
		goto vopunlock_exit;

	/* Defined? */
	if ((ueh.ueh_flags & UFS_EXTATTR_ATTR_FLAG_INUSE) == 0) {
		error = ENOATTR;
		goto vopunlock_exit;
	}

	/* Valid for the current inode generation? */
	if (ueh.ueh_i_gen != ip->i_gen) {
		/*
		 * The inode itself has a different generation number than
		 * the attribute data.  For now, the best solution is to
		 * coerce this to undefined, and let it get cleaned up by
		 * the next write or extattrctl clean.
		 */
		printf("ufs_extattr_rm (%s): inode number inconsistency (%d, %jd)\n",
		    mp->mnt_stat.f_mntonname, ueh.ueh_i_gen, (intmax_t)ip->i_gen);
		error = ENOATTR;
		goto vopunlock_exit;
	}

	/* Flag it as not in use. */
	ueh.ueh_flags = 0;
	ueh.ueh_len = 0;

	local_aiov.iov_base = (caddr_t) &ueh;
	local_aiov.iov_len = sizeof(struct ufs_extattr_header);
	local_aio.uio_iov = &local_aiov;
	local_aio.uio_iovcnt = 1;
	local_aio.uio_rw = UIO_WRITE;
	local_aio.uio_segflg = UIO_SYSSPACE;
	local_aio.uio_td = td;
	local_aio.uio_offset = base_offset;
	local_aio.uio_resid = sizeof(struct ufs_extattr_header);

	ioflag = IO_NODELOCKED;
	if (ufs_extattr_sync)
		ioflag |= IO_SYNC;
	error = VOP_WRITE(attribute->uele_backing_vnode, &local_aio, ioflag,
	    ump->um_extattr.uepm_ucred);
	if (error)
		goto vopunlock_exit;

	if (local_aio.uio_resid != 0)
		error = ENXIO;

vopunlock_exit:
	VOP_UNLOCK(attribute->uele_backing_vnode, 0);

	return (error);
}
コード例 #29
0
ファイル: swap.c プロジェクト: jiangxiaoyong/ece344
int
swap_pagein( u_int32_t paddr, int rw, u_int32_t mem, u_int32_t file, u_int32_t offset, int swap, int swap_index)
{
	int result;
	int fillamt;
	struct uio u;
	struct addrspace *as;
//	struct vnode *swap_vnode;

	as = curthread->t_vmspace;

	if(swap == 1)
	{
		result = vfs_open(SWAP_DEVICE, O_RDWR, &swap_vnode);
		mk_kuio(&u, paddr, PAGE_SIZE, swap_index * PAGE_SIZE, UIO_READ);
		result = VOP_READ(swap_vnode, &u);

		if (result) {
			return result;
		}

		vfs_close(swap_vnode);
	}
	else 
	{
		/* Open the file. */
		struct vnode *v;
		result = vfs_open(as->as_progname, O_RDONLY, &v);
		if (result) {
			return result;
		}

		mk_kuio_pd(&u, paddr, mem, file, offset, rw);
		if(rw == UIO_READ)
		{
			result = VOP_READ(v, &u)	;
		}
		else
		{
			result = VOP_WRITE(v, &u);
		}

		if (u.uio_resid != 0) {
			/* short read; problem with executable? */
			kprintf("ELF: short read on segment - file truncated?\n");
			return ENOEXEC;
		}

		/* Fill the rest of the memory space (if any) with zeros */
		fillamt = mem - file;
		if (fillamt > 0) {

			u.uio_resid += fillamt;
			u.uio_rw = UIO_READ;
			result = uiomovezeros(fillamt, &u);
		}
				
		if (result==EIO) {
			panic("swap: EIO on swapfile (offset %ld)\n",
			      (long)as->as_offset1);
		}
		else if (result==EINVAL) {
			panic("swap: EINVAL from swapfile (offset %ld)\n",
			      (long)as->as_offset1);
		}
		else if (result) {
			panic("swap: Error %d from swapfile (offset %ld)\n",
			      result, (long)as->as_offset1);
		}

		/* Done with the file now. */
		vfs_close(v);

		return 0;
	
	}




}
コード例 #30
0
ファイル: kern_alq.c プロジェクト: runsisi/ufreebsdtcp
/*
 * Flush all pending data to disk.  This operation will block.
 */
static int
alq_doio(struct alq *alq)
{
    struct thread *td;
    struct mount *mp;
    struct vnode *vp;
    struct uio auio;
    struct iovec aiov[2];
    int totlen;
    int iov;
    int vfslocked;
    int wrapearly;

    KASSERT((HAS_PENDING_DATA(alq)), ("%s: queue empty!", __func__));

    vp = alq->aq_vp;
    td = curthread;
    totlen = 0;
    iov = 1;
    wrapearly = alq->aq_wrapearly;

    bzero(&aiov, sizeof(aiov));
    bzero(&auio, sizeof(auio));

    /* Start the write from the location of our buffer tail pointer. */
    aiov[0].iov_base = alq->aq_entbuf + alq->aq_writetail;

    if (alq->aq_writetail < alq->aq_writehead) {
        /* Buffer not wrapped. */
        totlen = aiov[0].iov_len = alq->aq_writehead - alq->aq_writetail;
    } else if (alq->aq_writehead == 0) {
        /* Buffer not wrapped (special case to avoid an empty iov). */
        totlen = aiov[0].iov_len = alq->aq_buflen - alq->aq_writetail -
                                   wrapearly;
    } else {
        /*
         * Buffer wrapped, requires 2 aiov entries:
         * - first is from writetail to end of buffer
         * - second is from start of buffer to writehead
         */
        aiov[0].iov_len = alq->aq_buflen - alq->aq_writetail -
                          wrapearly;
        iov++;
        aiov[1].iov_base = alq->aq_entbuf;
        aiov[1].iov_len =  alq->aq_writehead;
        totlen = aiov[0].iov_len + aiov[1].iov_len;
    }

    alq->aq_flags |= AQ_FLUSHING;
    ALQ_UNLOCK(alq);

    auio.uio_iov = &aiov[0];
    auio.uio_offset = 0;
    auio.uio_segflg = UIO_SYSSPACE;
    auio.uio_rw = UIO_WRITE;
    auio.uio_iovcnt = iov;
    auio.uio_resid = totlen;
    auio.uio_td = td;

    /*
     * Do all of the junk required to write now.
     */
    vfslocked = VFS_LOCK_GIANT(vp->v_mount);
    vn_start_write(vp, &mp, V_WAIT);
    vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
    /*
     * XXX: VOP_WRITE error checks are ignored.
     */
#ifdef MAC
    if (mac_vnode_check_write(alq->aq_cred, NOCRED, vp) == 0)
#endif
        VOP_WRITE(vp, &auio, IO_UNIT | IO_APPEND, alq->aq_cred);
    VOP_UNLOCK(vp, 0);
    vn_finished_write(mp);
    VFS_UNLOCK_GIANT(vfslocked);

    ALQ_LOCK(alq);
    alq->aq_flags &= ~AQ_FLUSHING;

    /* Adjust writetail as required, taking into account wrapping. */
    alq->aq_writetail = (alq->aq_writetail + totlen + wrapearly) %
                        alq->aq_buflen;
    alq->aq_freebytes += totlen + wrapearly;

    /*
     * If we just flushed part of the buffer which wrapped, reset the
     * wrapearly indicator.
     */
    if (wrapearly)
        alq->aq_wrapearly = 0;

    /*
     * If we just flushed the buffer completely, reset indexes to 0 to
     * minimise buffer wraps.
     * This is also required to ensure alq_getn() can't wedge itself.
     */
    if (!HAS_PENDING_DATA(alq))
        alq->aq_writehead = alq->aq_writetail = 0;

    KASSERT((alq->aq_writetail >= 0 && alq->aq_writetail < alq->aq_buflen),
            ("%s: aq_writetail < 0 || aq_writetail >= aq_buflen", __func__));

    if (alq->aq_flags & AQ_WANTED) {
        alq->aq_flags &= ~AQ_WANTED;
        return (1);
    }

    return(0);
}