Exemplo n.º 1
0
/* ARGSUSED */
static int
zfsctl_snapdir_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t  **vpp,
    cred_t *cr, caller_context_t *cc, int flags, vsecattr_t *vsecp)
{
	zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data;
	char name[MAXNAMELEN];
	int err;
	static enum symfollow follow = NO_FOLLOW;
	static enum uio_seg seg = UIO_SYSSPACE;

	if (snapshot_namecheck(dirname, NULL, NULL) != 0)
		return (EILSEQ);

	dmu_objset_name(zfsvfs->z_os, name);

	*vpp = NULL;

	err = zfs_secpolicy_snapshot_perms(name, cr);
	if (err)
		return (err);

	if (err == 0) {
		err = dmu_objset_snapshot(name, dirname, NULL, B_FALSE);
		if (err)
			return (err);
		err = lookupnameat(dirname, seg, follow, NULL, vpp, dvp);
	}

	return (err);
}
Exemplo n.º 2
0
Arquivo: zfs_ctldir.c Projeto: EW1/zfs
/* ARGSUSED */
int
zfsctl_snapdir_mkdir(struct inode *dip, char *dirname, vattr_t *vap,
	struct inode **ipp, cred_t *cr, int flags)
{
	zfs_sb_t *zsb = ITOZSB(dip);
	char *dsname;
	int error;

	dsname = kmem_alloc(MAXNAMELEN, KM_SLEEP);

	if (snapshot_namecheck(dirname, NULL, NULL) != 0) {
		error = EILSEQ;
		goto out;
	}

	dmu_objset_name(zsb->z_os, dsname);

	error = zfs_secpolicy_snapshot_perms(dsname, cr);
	if (error)
		goto out;

	if (error == 0) {
		error = dmu_objset_snapshot(dsname, dirname,
		    NULL, NULL, B_FALSE, B_FALSE, -1);
		if (error)
			goto out;

		error = zfsctl_snapdir_lookup(dip, dirname, ipp,
		    0, cr, NULL, NULL);
	}
out:
	kmem_free(dsname, MAXNAMELEN);

	return (error);
}
Exemplo n.º 3
0
static int
dmu_objset_snapshot_one(char *name, void *arg)
{
	struct snaparg *sn = arg;
	objset_t *os;
	int err;

	(void) strcpy(sn->failed, name);

	/*
	 * Check permissions only when requested.  This only applies when
	 * doing a recursive snapshot.  The permission checks for the starting
	 * dataset have already been performed in zfs_secpolicy_snapshot()
	 */
	if (sn->checkperms == B_TRUE &&
	    (err = zfs_secpolicy_snapshot_perms(name, CRED())))
		return (err);

	err = dmu_objset_open(name, DMU_OST_ANY, DS_MODE_USER, &os);
	if (err != 0)
		return (err);

	/* If the objset is in an inconsistent state, return busy */
	if (os->os->os_dsl_dataset->ds_phys->ds_flags & DS_FLAG_INCONSISTENT) {
		dmu_objset_close(os);
		return (EBUSY);
	}

	/*
	 * NB: we need to wait for all in-flight changes to get to disk,
	 * so that we snapshot those changes.  zil_suspend does this as
	 * a side effect.
	 */
	err = zil_suspend(dmu_objset_zil(os));
	if (err == 0) {
		struct osnode *osn;
		dsl_sync_task_create(sn->dstg, dsl_dataset_snapshot_check,
		    dsl_dataset_snapshot_sync, os->os->os_dsl_dataset,
		    sn->snapname, 3);
		osn = kmem_alloc(sizeof (struct osnode), KM_SLEEP);
		osn->os = os;
		list_insert_tail(&sn->objsets, osn);
	} else {
		dmu_objset_close(os);
	}

	return (err);
}