示例#1
0
int32_t
bread(int fd, char *buf, daddr_t blk, long size)
{
	char *cp;
	int i, errs;
	offset_t offset = ldbtob(blk);
	offset_t addr;

	if (llseek(fd, offset, 0) < 0)
		rwerror(gettext("SEEK"), blk);
	else if (read(fd, buf, (int)size) == size)
		return (0);
	rwerror(gettext("READ"), blk);
	if (llseek(fd, offset, 0) < 0)
		rwerror(gettext("SEEK"), blk);
	errs = 0;
	bzero(buf, (int)size);
	pwarn(gettext("THE FOLLOWING SECTORS COULD NOT BE READ:"));
	for (cp = buf, i = 0; i < btodb(size); i++, cp += DEV_BSIZE) {
		addr = ldbtob(blk + i);
		if (llseek(fd, addr, SEEK_CUR) < 0 ||
		    read(fd, cp, (int)secsize) < 0) {
			(void) printf(" %ld", blk + i);
			errs++;
		}
	}
	(void) printf("\n");
	return (errs);
}
示例#2
0
void
bwrite(int fd, char *buf, daddr_t blk, long size)
{
	int i, n;
	char *cp;
	offset_t offset = ldbtob(blk);
	offset_t addr;

	if (fd < 0)
		return;
	if (llseek(fd, offset, 0) < 0)
		rwerror(gettext("SEEK"), blk);
	else if (write(fd, buf, (int)size) == size) {
		fsmodified = 1;
		return;
	}
	rwerror(gettext("WRITE"), blk);
	if (llseek(fd, offset, 0) < 0)
		rwerror(gettext("SEEK"), blk);
	pwarn(gettext("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"));
	for (cp = buf, i = 0; i < btodb(size); i++, cp += DEV_BSIZE) {
		n = 0;
		addr = ldbtob(blk + i);
		if (llseek(fd, addr, SEEK_CUR) < 0 ||
		    (n = write(fd, cp, DEV_BSIZE)) < 0) {
			(void) printf(" %ld", blk + i);
		} else if (n > 0) {
			fsmodified = 1;
		}

	}
	(void) printf("\n");
}
示例#3
0
static int diskuse (const char *device, struct usage *use_by_uid)
{
	ino_t inode;
	daddr32_t inode_blk;
	int i;
	int fd;
	int num_inodes;
	struct dinode inode_tab [MAXBSIZE / sizeof (struct dinode)];
	union sb_union sbu;

	if ((fd = open (device, O_RDONLY)) == -1) {
		err_ret ("diskuse: %s", device);
		return (-1);
	}

	sync ();

	if (pread (fd, &sb, SBSIZE, ldbtob (SBLOCK)) == -1) {
		close (fd);
		return (-1);
	}

	num_inodes = sb.fs_ipg * sb.fs_ncg;

	for (inode = 0; inode < num_inodes;) {
		inode_blk = fsbtodb (&sb, itod (&sb, inode));
		if (pread (fd, inode_tab, sb.fs_bsize, ldbtob (inode_blk)) == -1) {
			close (fd);
			return (-1);
		}

		for (i = 0; i < INOPB (&sb) && inode < num_inodes; i++, inode++) {
			if (inode < UFSROOTINO)
				continue;

			if ((inode_tab [i].di_mode & IFMT) == 0)
				continue;

			use_by_uid [inode_tab [i].di_uid].blocks +=
				inode_tab [i].di_blocks;
 			use_by_uid [inode_tab [i].di_uid].inodes++;
		}
	}

	return (0);
}
示例#4
0
/*
 * Called from roll thread;
 *	buffer set for reading master
 * Returns
 *	0 - success, can continue with next buffer
 *	1 - failure due to logmap deltas being in use
 */
int
top_read_roll(rollbuf_t *rbp, ml_unit_t *ul)
{
	buf_t		*bp	= &rbp->rb_bh;
	offset_t	mof	= ldbtob(bp->b_blkno);

	/*
	 * get a list of deltas
	 */
	if (logmap_list_get_roll(ul->un_logmap, mof, rbp)) {
		/* logmap deltas are in use */
		return (1);
	}

	/*
	 * no deltas were found, nothing to roll
	 */
	if (rbp->rb_age == NULL) {
		bp->b_flags |= B_INVAL;
		return (0);
	}

	/*
	 * If there is one cached roll buffer that cover all the deltas then
	 * we can use that instead of copying to a separate roll buffer.
	 */
	if (rbp->rb_crb) {
		rbp->rb_bh.b_blkno = lbtodb(rbp->rb_crb->c_mof);
		return (0);
	}

	/*
	 * Set up the read.
	 * If no read is needed logmap_setup_read() returns 0.
	 */
	if (logmap_setup_read(rbp->rb_age, rbp)) {
		/*
		 * async read the data from master
		 */
		logstats.ls_rreads.value.ui64++;
		bp->b_bcount = MAPBLOCKSIZE;
		(void) bdev_strategy(bp);
		lwp_stat_update(LWP_STAT_INBLK, 1);
	} else {
		sema_v(&bp->b_io); /* mark read as complete */
	}
	return (0);
}
示例#5
0
static void
vdev_file_io_strategy(void *arg)
{
	buf_t *bp = arg;
	vnode_t *vp = bp->b_private;
	ssize_t resid;
	int error;

	error = vn_rdwr((bp->b_flags & B_READ) ? UIO_READ : UIO_WRITE,
	    vp, bp->b_un.b_addr, bp->b_bcount, ldbtob(bp->b_lblkno),
	    UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid);

	if (error == 0) {
		bp->b_resid = resid;
		biodone(bp);
	} else {
		bioerror(bp, error);
		biodone(bp);
	}
}
示例#6
0
文件: zvol.c 项目: andreiw/polaris
int
zvol_strategy(buf_t *bp)
{
	zvol_state_t *zv = ddi_get_soft_state(zvol_state, getminor(bp->b_edev));
	uint64_t off, volsize;
	size_t size, resid;
	char *addr;
	objset_t *os;
	int error = 0;
	int sync;
	int reading;
	int txg_sync_needed = B_FALSE;

	if (zv == NULL) {
		bioerror(bp, ENXIO);
		biodone(bp);
		return (0);
	}

	if (getminor(bp->b_edev) == 0) {
		bioerror(bp, EINVAL);
		biodone(bp);
		return (0);
	}

	if (zv->zv_readonly && !(bp->b_flags & B_READ)) {
		bioerror(bp, EROFS);
		biodone(bp);
		return (0);
	}

	off = ldbtob(bp->b_blkno);
	volsize = zv->zv_volsize;

	os = zv->zv_objset;
	ASSERT(os != NULL);
	sync = !(bp->b_flags & B_ASYNC) && !(zil_disable);

	bp_mapin(bp);
	addr = bp->b_un.b_addr;
	resid = bp->b_bcount;

	/*
	 * There must be no buffer changes when doing a dmu_sync() because
	 * we can't change the data whilst calculating the checksum.
	 * A better approach than a per zvol rwlock would be to lock ranges.
	 */
	reading = bp->b_flags & B_READ;
	if (reading || resid <= zvol_immediate_write_sz)
		rw_enter(&zv->zv_dslock, RW_READER);
	else
		rw_enter(&zv->zv_dslock, RW_WRITER);

	while (resid != 0 && off < volsize) {

		size = MIN(resid, 1UL << 20);	/* cap at 1MB per tx */

		if (size > volsize - off)	/* don't write past the end */
			size = volsize - off;

		if (reading) {
			error = dmu_read(os, ZVOL_OBJ, off, size, addr);
		} else {
			dmu_tx_t *tx = dmu_tx_create(os);
			dmu_tx_hold_write(tx, ZVOL_OBJ, off, size);
			error = dmu_tx_assign(tx, TXG_WAIT);
			if (error) {
				dmu_tx_abort(tx);
			} else {
				dmu_write(os, ZVOL_OBJ, off, size, addr, tx);
				if (sync) {
					/* use the ZIL to commit this write */
					if (zvol_log_write(zv, tx, off, size,
					    addr) != 0) {
						txg_sync_needed = B_TRUE;
					}
				}
				dmu_tx_commit(tx);
			}
		}
		if (error)
			break;
		off += size;
		addr += size;
		resid -= size;
	}
	rw_exit(&zv->zv_dslock);

	if ((bp->b_resid = resid) == bp->b_bcount)
		bioerror(bp, off > volsize ? EINVAL : error);

	biodone(bp);

	if (sync) {
		if (txg_sync_needed)
			txg_wait_synced(dmu_objset_pool(os), 0);
		else
			zil_commit(zv->zv_zilog, UINT64_MAX, 0);
	}

	return (0);
}
示例#7
0
void
lqfs_write_strategy(ml_unit_t *ul, buf_t *bp)
{
	offset_t	mof	= ldbtob(bp->b_blkno);
	off_t		nb	= bp->b_bcount;
	char		*va;
	mapentry_t	*me;
	uchar_t		ord;
	qfsvfs_t	*qfsvfsp = ul->un_qfsvfs;
#ifdef LUFS
#else
	caddr_t		buf;

	va = bp_mapin_common(bp, VM_SLEEP);
	buf = bp->b_un.b_addr;
#endif /* LUFS */

	ASSERT((nb & DEV_BMASK) == 0);
	ul->un_logmap->mtm_ref = 1;

	/*
	 * if there are deltas, move into log
	 */
	ord = lqfs_find_ord(qfsvfsp, bp);
#ifdef LUFS
	me = deltamap_remove(ul->un_deltamap, mof, ord, nb);
	if (me) {
		va = bp_mapin_common(bp, VM_SLEEP);

		ASSERT(((ul->un_debug & MT_WRITE_CHECK) == 0) ||
		    (ul->un_matamap == NULL)||
		    matamap_within(ul->un_matamap, mof, ord, nb));

		/*
		 * move to logmap
		 */
		if (qfs_crb_enable) {
			logmap_add_buf(ul, va, mof, ord, me,
			    bp->b_un.b_addr, nb);
		} else {
			logmap_add(ul, va, mof, ord, me);
		}

		if (ul->un_flags & LDL_ERROR) {
			bp->b_flags |= B_ERROR;
			bp->b_error = EIO;
		}
		biodone(bp);
		return;
	}
#else
	if (buf && qfs_crb_enable) {
		uint32_t	bufsz;
		offset_t	vamof;
		offset_t	hmof;
		uchar_t		vaord;
		uchar_t		hord;
		uint32_t	hnb, nb1;

		bufsz = bp->b_bcount;
		ASSERT((bufsz & DEV_BMASK) == 0);

		vamof = mof;
		vaord = ord;

		/*
		 * Move any deltas to the logmap. Split requests that
		 * straddle MAPBLOCKSIZE hash boundaries (i.e. summary info).
		 */
		for (hmof = vamof - (va - buf), nb1 = nb; bufsz;
		    bufsz -= hnb, hmof += hnb, buf += hnb, nb1 -= hnb) {
			hnb = MAPBLOCKSIZE - (hmof & MAPBLOCKOFF);
			if (hnb > bufsz) {
				hnb = bufsz;
			}
			LQFS_MSG(CE_WARN, "lqfs_write_strategy(): Removing "
			    "deltamap deltas within mof 0x%llx ord %d nb %d\n",
			    MAX(hmof, vamof), vaord, MIN(hnb, nb1));
			me = deltamap_remove(ul->un_deltamap,
			    MAX(hmof, vamof), vaord, MIN(hnb, nb1));
			hord = vaord;
			if (me) {
				logmap_add_buf(ul, va, hmof, hord,
				    me, buf, hnb);

				if (ul->un_flags & LDL_ERROR) {
					bp->b_flags |= B_ERROR;
					bp->b_error = EIO;
				}
				biodone(bp);
				return;
			}
		}
	} else {
		/*
		 * if there are deltas
		 */
		LQFS_MSG(CE_WARN, "lqfs_write_strategy(): Removing "
		    "deltamap deltas within mof 0x%x ord %d nb %d\n",
		    mof, ord, nb);
		me = deltamap_remove(ul->un_deltamap, mof, ord, nb);
		if (me) {
			ASSERT(((ul->un_debug & MT_WRITE_CHECK) == 0) ||
			    (ul->un_matamap == NULL)||
			    matamap_within(ul->un_matamap, mof, ord, nb));

			/*
			 * move to logmap
			 */
			logmap_add(ul, va, mof, ord, me);

			if (ul->un_flags & LDL_ERROR) {
				bp->b_flags |= B_ERROR;
				bp->b_error = EIO;
			}
			biodone(bp);
			return;
		}
	}
#endif /* LUFS */
	if (ul->un_flags & LDL_ERROR) {
		bp->b_flags |= B_ERROR;
		bp->b_error = EIO;
		biodone(bp);
		return;
	}

	/*
	 * Check that we are not updating metadata, or if so then via B_PHYS.
	 */
	ASSERT((ul->un_matamap == NULL) ||
	    !(matamap_overlap(ul->un_matamap, mof, ord, nb) &&
	    ((bp->b_flags & B_PHYS) == 0)));

	LQFS_SET_IOTSTAMP(ul->un_qfsvfs, ddi_get_lbolt());
	logstats.ls_lwrites.value.ui64++;

#ifdef LQFS_TODO_SNAPSHOT
	/* If snapshots are enabled, write through the snapshot driver */
	if (ul->un_qfsvfs->vfs_snapshot) {
		fssnap_strategy(&ul->un_qfsvfs->vfs_snapshot, bp);
	} else {
#endif /* LQFS_TODO_SNAPSHOT */
		if ((bp->b_flags & B_READ) == 0) {
			LQFS_MSG(CE_WARN, "lqfs_write_strategy(): "
			    "bdev_strategy writing mof 0x%x edev %ld "
			    "nb %d\n", bp->b_blkno * 512, bp->b_edev,
			    bp->b_bcount);
		} else {
			LQFS_MSG(CE_WARN, "lqfs_write_strategy(): "
			    "bdev_strategy reading mof 0x%x edev %ld "
			    "nb %d\n", bp->b_blkno * 512, bp->b_edev,
			    bp->b_bcount);
		}
		(void) bdev_strategy(bp);
#ifdef LQFS_TODO_SNAPSHOT
	}
#endif /* LQFS_TODO_SNAPSHOT */

#ifdef LQFS_TODO_STATS
	lwp_stat_update(LWP_STAT_OUBLK, 1);
#endif /* LQFS_TODO_STATS */
}
示例#8
0
void
lqfs_read_strategy(ml_unit_t *ul, buf_t *bp)
{
	mt_map_t	*logmap	= ul->un_logmap;
	offset_t	mof	= ldbtob(bp->b_blkno);
	off_t		nb	= bp->b_bcount;
	mapentry_t	*age;
	char		*va;
	int		(*saviodone)();
	int		entire_range;
	uchar_t		ord;
	qfsvfs_t	*qfsvfsp = ul->un_qfsvfs;

	/*
	 * get a linked list of overlapping deltas
	 * returns with &mtm->mtm_rwlock held
	 */
	ord = lqfs_find_ord(qfsvfsp, bp);
	entire_range = logmap_list_get(logmap, mof, ord, nb, &age);

	/*
	 * no overlapping deltas were found; read master
	 */
	if (age == NULL) {
		rw_exit(&logmap->mtm_rwlock);
		if (ul->un_flags & LDL_ERROR) {
			bp->b_flags |= B_ERROR;
			bp->b_error = EIO;
			biodone(bp);
		} else {
			LQFS_SET_IOTSTAMP(ul->un_qfsvfs, ddi_get_lbolt());
			logstats.ls_lreads.value.ui64++;
			if ((bp->b_flags & B_READ) == 0) {
				LQFS_MSG(CE_WARN, "lqfs_read_strategy(): "
				    "bdev_strategy writing mof 0x%x "
				    "edev %ld nb %d\n", bp->b_blkno * 512,
				    bp->b_edev, bp->b_bcount);
			} else {
				LQFS_MSG(CE_WARN, "lqfs_read_strategy(): "
				    "bdev_strategy reading mof 0x%x "
				    "edev %ld nb %d\n", bp->b_blkno * 512,
				    bp->b_edev, bp->b_bcount);
			}
			(void) bdev_strategy(bp);
#ifdef LQFS_TODO_STATS
			lwp_stat_update(LWP_STAT_INBLK, 1);
#endif /* LQFS_TODO_STATS */
		}
		return;
	}

	va = bp_mapin_common(bp, VM_SLEEP);
	/*
	 * if necessary, sync read the data from master
	 *	errors are returned in bp
	 */
	if (!entire_range) {
		saviodone = bp->b_iodone;
		bp->b_iodone = trans_not_done;
		logstats.ls_mreads.value.ui64++;
		if ((bp->b_flags & B_READ) == 0) {
			LQFS_MSG(CE_WARN, "lqfs_read_strategy(): "
			    "bdev_strategy writing mof 0x%x edev %ld "
			    "nb %d\n", bp->b_blkno * 512, bp->b_edev,
			    bp->b_bcount);
		} else {
			LQFS_MSG(CE_WARN, "lqfs_read_strategy(): "
			    "bdev_strategy reading mof 0x%x edev %ld "
			    "nb %d\n", bp->b_blkno * 512, bp->b_edev,
			    bp->b_bcount);
		}
		(void) bdev_strategy(bp);
#ifdef LQFS_TODO_STATS
		lwp_stat_update(LWP_STAT_INBLK, 1);
#endif /* LQFS_TODO_STATS */
		if (trans_not_wait(bp)) {
			ldl_seterror(ul, "Error reading master");
		}
		bp->b_iodone = saviodone;
	}

	/*
	 * sync read the data from the log
	 *	errors are returned inline
	 */
	if (ldl_read(ul, va, mof, ord, nb, age)) {
		bp->b_flags |= B_ERROR;
		bp->b_error = EIO;
	}

	/*
	 * unlist the deltas
	 */
	logmap_list_put(logmap, age);

	/*
	 * all done
	 */
	if (ul->un_flags & LDL_ERROR) {
		bp->b_flags |= B_ERROR;
		bp->b_error = EIO;
	}
	biodone(bp);
}
/*
 * Set various fields of the dqblk according to the command.
 * Q_SETQUOTA - assign an entire dqblk structure.
 * Q_SETQLIM - assign a dqblk structure except for the usage.
 */
static int
setquota(int cmd, uid_t uid, struct ufsvfs *ufsvfsp,
    caddr_t addr, struct cred *cr)
{
	struct dquot *dqp;
	struct inode	*qip;
	struct dquot *xdqp;
	struct dqblk newlim;
	int error;
	int scan_type = SQD_TYPE_NONE;
	daddr_t bn;
	int contig;

	if (secpolicy_fs_quota(cr, ufsvfsp->vfs_vfs) != 0)
		return (EPERM);

	rw_enter(&ufsvfsp->vfs_dqrwlock, RW_WRITER);

	/*
	 * Quotas are not enabled on this file system so there is
	 * nothing more to do.
	 */
	if ((ufsvfsp->vfs_qflags & MQ_ENABLED) == 0) {
		rw_exit(&ufsvfsp->vfs_dqrwlock);
		return (ESRCH);
	}

	/*
	 * At this point, the quota subsystem is quiescent on this file
	 * system so we can do all the work necessary to modify the quota
	 * information for this user.
	 */

	if (copyin(addr, (caddr_t)&newlim, sizeof (struct dqblk)) != 0) {
		rw_exit(&ufsvfsp->vfs_dqrwlock);
		return (EFAULT);
	}
	error = getdiskquota(uid, ufsvfsp, 0, &xdqp);
	if (error) {
		rw_exit(&ufsvfsp->vfs_dqrwlock);
		return (error);
	}
	dqp = xdqp;
	/*
	 * Don't change disk usage on Q_SETQLIM
	 */
	mutex_enter(&dqp->dq_lock);
	if (cmd == Q_SETQLIM) {
		newlim.dqb_curblocks = dqp->dq_curblocks;
		newlim.dqb_curfiles = dqp->dq_curfiles;
	}
	if (uid == 0) {
		/*
		 * Timelimits for uid 0 set the relative time
		 * the other users can be over quota for this file system.
		 * If it is zero a default is used (see quota.h).
		 */
		ufsvfsp->vfs_btimelimit =
		    newlim.dqb_btimelimit? newlim.dqb_btimelimit: DQ_BTIMELIMIT;
		ufsvfsp->vfs_ftimelimit =
		    newlim.dqb_ftimelimit? newlim.dqb_ftimelimit: DQ_FTIMELIMIT;
	} else {
		if (newlim.dqb_bsoftlimit &&
		    newlim.dqb_curblocks >= newlim.dqb_bsoftlimit) {
			if (dqp->dq_bsoftlimit == 0 ||
			    dqp->dq_curblocks < dqp->dq_bsoftlimit) {
				/* If we're suddenly over the limit(s),	*/
				/* start the timer(s)			*/
				newlim.dqb_btimelimit =
				    (uint32_t)gethrestime_sec() +
				    ufsvfsp->vfs_btimelimit;
				dqp->dq_flags &= ~DQ_BLKS;
			} else {
				/* If we're currently over the soft	*/
				/* limit and were previously over the	*/
				/* soft limit then preserve the old	*/
				/* time limit but make sure the DQ_BLKS	*/
				/* flag is set since we must have been	*/
				/* previously warned.			*/
				newlim.dqb_btimelimit = dqp->dq_btimelimit;
				dqp->dq_flags |= DQ_BLKS;
			}
		} else {
			/* Either no quota or under quota, clear time limit */
			newlim.dqb_btimelimit = 0;
			dqp->dq_flags &= ~DQ_BLKS;
		}

		if (newlim.dqb_fsoftlimit &&
		    newlim.dqb_curfiles >= newlim.dqb_fsoftlimit) {
			if (dqp->dq_fsoftlimit == 0 ||
			    dqp->dq_curfiles < dqp->dq_fsoftlimit) {
				/* If we're suddenly over the limit(s),	*/
				/* start the timer(s)			*/
				newlim.dqb_ftimelimit =
				    (uint32_t)gethrestime_sec() +
				    ufsvfsp->vfs_ftimelimit;
				dqp->dq_flags &= ~DQ_FILES;
			} else {
				/* If we're currently over the soft	*/
				/* limit and were previously over the	*/
				/* soft limit then preserve the old	*/
				/* time limit but make sure the		*/
				/* DQ_FILES flag is set since we must	*/
				/* have been previously warned.		*/
				newlim.dqb_ftimelimit = dqp->dq_ftimelimit;
				dqp->dq_flags |= DQ_FILES;
			}
		} else {
			/* Either no quota or under quota, clear time limit */
			newlim.dqb_ftimelimit = 0;
			dqp->dq_flags &= ~DQ_FILES;
		}
	}

	/*
	 * If there was previously no limit and there is now at least
	 * one limit, then any inodes in the cache have NULL d_iquot
	 * fields (getinoquota() returns NULL when there are no limits).
	 */
	if ((dqp->dq_fhardlimit == 0 && dqp->dq_fsoftlimit == 0 &&
	    dqp->dq_bhardlimit == 0 && dqp->dq_bsoftlimit == 0) &&
	    (newlim.dqb_fhardlimit || newlim.dqb_fsoftlimit ||
	    newlim.dqb_bhardlimit || newlim.dqb_bsoftlimit)) {
		scan_type = SQD_TYPE_LIMIT;
	}

	/*
	 * If there was previously at least one limit and there is now
	 * no limit, then any inodes in the cache have non-NULL d_iquot
	 * fields need to be reset to NULL.
	 */
	else if ((dqp->dq_fhardlimit || dqp->dq_fsoftlimit ||
	    dqp->dq_bhardlimit || dqp->dq_bsoftlimit) &&
	    (newlim.dqb_fhardlimit == 0 && newlim.dqb_fsoftlimit == 0 &&
	    newlim.dqb_bhardlimit == 0 && newlim.dqb_bsoftlimit == 0)) {
		scan_type = SQD_TYPE_NO_LIMIT;
	}

	dqp->dq_dqb = newlim;
	dqp->dq_flags |= DQ_MOD;

	/*
	 *  push the new quota to disk now.  If this is a trans device
	 *  then force the page out with ufs_putpage so it will be deltaed
	 *  by ufs_startio.
	 */
	qip = ufsvfsp->vfs_qinod;
	rw_enter(&qip->i_contents, RW_WRITER);
	(void) ufs_rdwri(UIO_WRITE, FWRITE | FSYNC, qip, (caddr_t)&dqp->dq_dqb,
	    sizeof (struct dqblk), dqoff(uid), UIO_SYSSPACE,
	    (int *)NULL, kcred);
	rw_exit(&qip->i_contents);

	(void) VOP_PUTPAGE(ITOV(qip), dqoff(dqp->dq_uid) & ~qip->i_fs->fs_bmask,
	    qip->i_fs->fs_bsize, B_INVAL, kcred, NULL);

	/*
	 * We must set the dq_mof even if not we are not logging in case
	 * we are later remount to logging.
	 */
	contig = 0;
	rw_enter(&qip->i_contents, RW_WRITER);
	error = bmap_read(qip, dqoff(dqp->dq_uid), &bn, &contig);
	rw_exit(&qip->i_contents);
	if (error || (bn == UFS_HOLE)) {
		dqp->dq_mof = UFS_HOLE;
	} else {
		dqp->dq_mof = ldbtob(bn) +
		    (offset_t)((dqoff(dqp->dq_uid)) & (DEV_BSIZE - 1));
	}

	dqp->dq_flags &= ~DQ_MOD;
	dqput(dqp);
	mutex_exit(&dqp->dq_lock);
	if (scan_type) {
		struct setquota_data sqd;

		sqd.sqd_type = scan_type;
		sqd.sqd_ufsvfsp = ufsvfsp;
		sqd.sqd_uid = uid;
		(void) ufs_scan_inodes(0, setquota_scan_inode, &sqd, ufsvfsp);
	}
	rw_exit(&ufsvfsp->vfs_dqrwlock);
	return (0);
}
示例#10
0
static int
md_mapbuf(
	ms_unit_t	*un,
	diskaddr_t	blkno,
	u_longlong_t	bcount,
	buf_t		*bp,	/* if bp==NULL, skip bp updates */
	ms_comp_t	**mdc)	/* if bp==NULL, skip mdc update */
{
	struct ms_row	*mdr;
	struct ms_comp	*mdcomp;
	diskaddr_t	stripe_blk;
	diskaddr_t	fragment, blk_in_row, endblk;
	offset_t	interlace;
	size_t		dev_index;
	int		row_index, more;
	extern unsigned md_maxphys;
	/* Work var's when bp==NULL */
	u_longlong_t	wb_bcount;
	diskaddr_t	wb_blkno;
	md_dev64_t	wb_edev;
	ms_comp_t	*wmdc;

	/*
	 * Do a real calculation to derive the minor device of the
	 * Virtual Disk, which in turn will let us derive the
	 * device/minor of the underlying real device.
	 */


	for (row_index = 0; row_index < un->un_nrows; row_index++) {
		mdr = &un->un_row[row_index];
		if (blkno < mdr->un_cum_blocks)
			break;
	}
	ASSERT(row_index != un->un_nrows);

	mdcomp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]);

	blk_in_row = blkno - mdr->un_cum_blocks + mdr->un_blocks;
	endblk = (diskaddr_t)(blkno + howmany(bcount, DEV_BSIZE));
	if (mdr->un_ncomp == 1) { /* No striping */
		if (endblk > mdr->un_cum_blocks) {
			wb_bcount = ldbtob(mdr->un_cum_blocks - blkno);
			if ((row_index + 1) == un->un_nrows)
				more = 0;
			else
				more = 1;
		} else {
			wb_bcount = bcount;
			more = 0;
		}
		wmdc = &mdcomp[mdr->un_icomp];
		wb_blkno = blk_in_row;
	} else { /* Have striping */
		interlace = mdr->un_interlace;
		fragment = blk_in_row % interlace;
		if (bcount > ldbtob(interlace - fragment)) {
			more = 1;
			wb_bcount = ldbtob(interlace - fragment);
		} else {
			more = 0;
			wb_bcount = bcount;
		}

		stripe_blk = blk_in_row / interlace;
		dev_index = (size_t)(stripe_blk % mdr->un_ncomp);
		wmdc = &mdcomp[mdr->un_icomp + dev_index];
		wb_blkno = (diskaddr_t)(((stripe_blk / mdr->un_ncomp) *
		    interlace) + fragment);
	}

	wb_blkno += wmdc->un_start_block;
	wb_edev = wmdc->un_dev;

	/* only break up the I/O if we're not built on another metadevice */
	if ((md_getmajor(wb_edev) != md_major) && (wb_bcount > md_maxphys)) {
		wb_bcount = md_maxphys;
		more = 1;
	}
	if (bp != (buf_t *)NULL) {
		/*
		 * wb_bcount is limited by md_maxphys which is 'int'
		 */
		bp->b_bcount = (size_t)wb_bcount;
		bp->b_lblkno = wb_blkno;
		bp->b_edev = md_dev64_to_dev(wb_edev);
		*mdc = wmdc;
	}
	return (more);
}