void
_cedit_cmd_file_revert (GtkAction   *action,
		       CeditWindow *window)
{
	CeditTab       *tab;
	CeditDocument  *doc;
	GtkWidget      *dialog;
	GtkWindowGroup *wg;

	cedit_debug (DEBUG_COMMANDS);

	tab = cedit_window_get_active_tab (window);
	g_return_if_fail (tab != NULL);

	/* If we are already displaying a notification
	 * reverting will drop local modifications, do
	 * not bug the user further */
	if (cedit_tab_get_state (tab) == CEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
	{
		do_revert (window, tab);
		return;
	}

	doc = cedit_tab_get_document (tab);
	g_return_if_fail (doc != NULL);
	g_return_if_fail (!cedit_document_is_untitled (doc));

	dialog = revert_dialog (window, doc);

	wg = cedit_window_get_group (window);

	gtk_window_group_add_window (wg, GTK_WINDOW (dialog));

	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);

	g_signal_connect (dialog,
			  "response",
			  G_CALLBACK (revert_dialog_response_cb),
			  window);

	gtk_widget_show (dialog);
}
static void
revert_dialog_response_cb (GtkDialog   *dialog,
			   gint         response_id,
			   CeditWindow *window)
{
	CeditTab *tab;

	cedit_debug (DEBUG_COMMANDS);

	/* FIXME: we are relying on the fact that the dialog is
	   modal so the active tab can't be changed...
	   not very nice - Paolo (Oct 11, 2005) */
	tab = cedit_window_get_active_tab (window);
	if (tab == NULL)
		return;

	gtk_widget_destroy (GTK_WIDGET (dialog));

	if (response_id == GTK_RESPONSE_OK)
	{
		do_revert (window, tab);
	}
}
Exemple #3
0
int aufs_rmdir(struct inode *dir, struct dentry *dentry)
{
	int err, rmdir_later;
	aufs_bindex_t bwh, bindex, bstart;
	struct au_dtime dt;
	struct au_pin pin;
	struct inode *inode;
	struct dentry *parent, *wh_dentry, *h_dentry;
	struct au_whtmp_rmdir *args;

	IMustLock(dir);

	err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
	if (unlikely(err))
		goto out;
	err = au_alive_dir(dentry);
	if (unlikely(err))
		goto out_unlock;
	inode = dentry->d_inode;
	IMustLock(inode);
	err = -ENOTDIR;
	if (unlikely(!S_ISDIR(inode->i_mode)))
		goto out_unlock; /* possible? */

	err = -ENOMEM;
	args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
	if (unlikely(!args))
		goto out_unlock;

	parent = dentry->d_parent; /* dir inode is locked */
	di_write_lock_parent(parent);
	err = au_test_empty(dentry, &args->whlist);
	if (unlikely(err))
		goto out_parent;

	bstart = au_dbstart(dentry);
	bwh = au_dbwh(dentry);
	bindex = -1;
	wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
	err = PTR_ERR(wh_dentry);
	if (IS_ERR(wh_dentry))
		goto out_parent;

	h_dentry = au_h_dptr(dentry, bstart);
	dget(h_dentry);
	rmdir_later = 0;
	if (bindex == bstart) {
		err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
		if (err > 0) {
			rmdir_later = err;
			err = 0;
		}
	} else {
		/* stop monitoring */
		au_hn_free(au_hi(inode, bstart));

		/* dir inode is locked */
		IMustLock(wh_dentry->d_parent->d_inode);
		err = 0;
	}

	if (!err) {
		vfsub_dead_dir(inode);
		au_set_dbdiropq(dentry, -1);
		epilog(dir, dentry, bindex);

		if (rmdir_later) {
			au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
			args = NULL;
		}

		goto out_unpin; /* success */
	}

	/* revert */
	AuLabel(revert);
	if (wh_dentry) {
		int rerr;

		rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
		if (rerr)
			err = rerr;
	}

out_unpin:
	au_unpin(&pin);
	dput(wh_dentry);
	dput(h_dentry);
out_parent:
	di_write_unlock(parent);
	if (args)
		au_whtmp_rmdir_free(args);
out_unlock:
	aufs_read_unlock(dentry, AuLock_DW);
out:
	AuTraceErr(err);
	return err;
}
Exemple #4
0
/*
 * when an error happened, remove the created whiteout and revert everything.
 */
static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
		     aufs_bindex_t bwh, struct dentry *wh_dentry,
		     struct dentry *dentry, struct au_dtime *dt)
{
	int rerr;
	struct path h_path = {
		.dentry	= wh_dentry,
		.mnt	= au_sbr_mnt(dir->i_sb, bindex)
	};

	rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
	if (!rerr) {
		au_set_dbwh(dentry, bwh);
		au_dtime_revert(dt);
		return 0;
	}

	AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
		AuDLNPair(dentry), err, rerr);
	return -EIO;
}

/* ---------------------------------------------------------------------- */

int aufs_unlink(struct inode *dir, struct dentry *dentry)
{
	int err;
	aufs_bindex_t bwh, bindex, bstart;
	struct au_dtime dt;
	struct au_pin pin;
	struct path h_path;
	struct inode *inode, *h_dir;
	struct dentry *parent, *wh_dentry;

	IMustLock(dir);

	err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
	if (unlikely(err))
		goto out;
	err = au_d_hashed_positive(dentry);
	if (unlikely(err))
		goto out_unlock;
	inode = dentry->d_inode;
	IMustLock(inode);
	err = -EISDIR;
	if (unlikely(S_ISDIR(inode->i_mode)))
		goto out_unlock; /* possible? */

	bstart = au_dbstart(dentry);
	bwh = au_dbwh(dentry);
	bindex = -1;
	parent = dentry->d_parent; /* dir inode is locked */
	di_write_lock_parent(parent);
	wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
	err = PTR_ERR(wh_dentry);
	if (IS_ERR(wh_dentry))
		goto out_parent;

	h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
	h_path.dentry = au_h_dptr(dentry, bstart);
	dget(h_path.dentry);
	if (bindex == bstart) {
		h_dir = au_pinned_h_dir(&pin);
		err = vfsub_unlink(h_dir, &h_path, /*force*/0);
	} else {
		/* dir inode is locked */
		h_dir = wh_dentry->d_parent->d_inode;
		IMustLock(h_dir);
		err = 0;
	}

	if (!err) {
		vfsub_drop_nlink(inode);
		epilog(dir, dentry, bindex);

		/* update target timestamps */
		if (bindex == bstart) {
			vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
			inode->i_ctime = h_path.dentry->d_inode->i_ctime;
		} else
			/* todo: this timestamp may be reverted later */
			inode->i_ctime = h_dir->i_ctime;
		goto out_unpin; /* success */
	}

	/* revert */
	if (wh_dentry) {
		int rerr;

		rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
		if (rerr)
			err = rerr;
	}

out_unpin:
	au_unpin(&pin);
	dput(wh_dentry);
	dput(h_path.dentry);
out_parent:
	di_write_unlock(parent);
out_unlock:
	aufs_read_unlock(dentry, AuLock_DW);
out:
	return err;
}
Exemple #5
0
/*
 * when an error happened, remove the created whiteout and revert everything.
 */
static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
		     aufs_bindex_t bwh, struct dentry *wh_dentry,
		     struct dentry *dentry, struct au_dtime *dt)
{
	int rerr;
	struct path h_path = {
		.dentry	= wh_dentry,
		.mnt	= au_sbr_mnt(dir->i_sb, bindex)
	};

	rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
	if (!rerr) {
		au_set_dbwh(dentry, bwh);
		au_dtime_revert(dt);
		return 0;
	}

	AuIOErr("%pd reverting whiteout failed(%d, %d)\n", dentry, err, rerr);
	return -EIO;
}

/* ---------------------------------------------------------------------- */

int aufs_unlink(struct inode *dir, struct dentry *dentry)
{
	int err;
	aufs_bindex_t bwh, bindex, bstart;
	struct inode *inode, *h_dir, *delegated;
	struct dentry *parent, *wh_dentry;
	/* to reuduce stack size */
	struct {
		struct au_dtime dt;
		struct au_pin pin;
		struct path h_path;
	} *a;

	IMustLock(dir);

	err = -ENOMEM;
	a = kmalloc(sizeof(*a), GFP_NOFS);
	if (unlikely(!a))
		goto out;

	err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
	if (unlikely(err))
		goto out_free;
	err = au_d_hashed_positive(dentry);
	if (unlikely(err))
		goto out_unlock;
	inode = d_inode(dentry);
	IMustLock(inode);
	err = -EISDIR;
	if (unlikely(d_is_dir(dentry)))
		goto out_unlock; /* possible? */

	bstart = au_dbstart(dentry);
	bwh = au_dbwh(dentry);
	bindex = -1;
	parent = dentry->d_parent; /* dir inode is locked */
	di_write_lock_parent(parent);
	wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &a->dt,
					&a->pin);
	err = PTR_ERR(wh_dentry);
	if (IS_ERR(wh_dentry))
		goto out_parent;

	a->h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
	a->h_path.dentry = au_h_dptr(dentry, bstart);
	dget(a->h_path.dentry);
	if (bindex == bstart) {
		h_dir = au_pinned_h_dir(&a->pin);
		delegated = NULL;
		err = vfsub_unlink(h_dir, &a->h_path, &delegated, /*force*/0);
		if (unlikely(err == -EWOULDBLOCK)) {
			pr_warn("cannot retry for NFSv4 delegation"
				" for an internal unlink\n");
			iput(delegated);
		}
	} else {
		/* dir inode is locked */
		h_dir = d_inode(wh_dentry->d_parent);
		IMustLock(h_dir);
		err = 0;
	}

	if (!err) {
		vfsub_drop_nlink(inode);
		epilog(dir, dentry, bindex);

		/* update target timestamps */
		if (bindex == bstart) {
			vfsub_update_h_iattr(&a->h_path, /*did*/NULL);
			/*ignore*/
			inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
		} else
			/* todo: this timestamp may be reverted later */
			inode->i_ctime = h_dir->i_ctime;
		goto out_unpin; /* success */
	}

	/* revert */
	if (wh_dentry) {
		int rerr;

		rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
				 &a->dt);
		if (rerr)
			err = rerr;
	}

out_unpin:
	au_unpin(&a->pin);
	dput(wh_dentry);
	dput(a->h_path.dentry);
out_parent:
	di_write_unlock(parent);
out_unlock:
	aufs_read_unlock(dentry, AuLock_DW);
out_free:
	kfree(a);
out:
	return err;
}
Exemple #6
0
int aufs_rmdir(struct inode *dir, struct dentry *dentry)
{
	int err, rmdir_later;
	struct inode *inode, *hidden_dir;
	struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent;
	struct dtime dt;
	aufs_bindex_t bwh, bindex, bstart;
	struct rmdir_whtmp_arg *arg;
	struct aufs_nhash *whlist;

	LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
	IMustLock(dir);
	inode = dentry->d_inode;
	if (unlikely(!inode))
		return -ENOENT; // possible?
	IMustLock(inode);

	whlist = nhash_new(GFP_KERNEL);
	err = PTR_ERR(whlist);
	if (IS_ERR(whlist))
		goto out;

	err = -ENOMEM;
	arg = kmalloc(sizeof(*arg), GFP_KERNEL);
	//arg = NULL;
	if (unlikely(!arg))
		goto out_whlist;

	aufs_read_lock(dentry, AUFS_D_WLOCK);
	parent = dentry->d_parent;
	di_write_lock_parent(parent);
	err = test_empty(dentry, whlist);
	//err = -1;
	if (unlikely(err))
		goto out_arg;

	bstart = dbstart(dentry);
	bwh = dbwh(dentry);
	bindex = -1;
	wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/ 1, &bindex, &dt);
	//wh_dentry = ERR_PTR(-1);
	err = PTR_ERR(wh_dentry);
	if (IS_ERR(wh_dentry))
		goto out_arg;

	hidden_dentry = au_h_dptr(dentry);
	dget(hidden_dentry);
	hidden_parent = hidden_dentry->d_parent;
	hidden_dir = hidden_parent->d_inode;

	rmdir_later = 0;
	if (bindex == bstart) {
		IMustLock(hidden_dir);
		err = renwh_and_rmdir(dentry, bstart, whlist, dir);
		//err = -1;
		if (err > 0) {
			rmdir_later = err;
			err = 0;
		}
	} else {
		DEBUG_ON(!wh_dentry);
		hidden_parent = wh_dentry->d_parent;
		DEBUG_ON(hidden_parent != au_h_dptr_i(parent, bindex));
		hidden_dir = hidden_parent->d_inode;
		IMustLock(hidden_dir);
		err = 0;
	}

	if (!err) {
		au_reset_hinotify(inode, /*flags*/0);
		inode->i_nlink = 0;
		set_dbdiropq(dentry, -1);
		epilog(dir, dentry, bindex);

		if (rmdir_later) {
			kick_rmdir_whtmp(hidden_dentry, whlist, bstart, dir,
					 inode, arg);
			arg = NULL;
		}

		goto out_unlock; /* success */
	}

	/* revert */
	LKTRLabel(revert);
	if (wh_dentry) {
		int rerr;
		rerr = do_revert(err, wh_dentry, dentry, bwh, &dt,
				 need_dlgt(dir->i_sb));
		if (rerr)
			err = rerr;
	}

 out_unlock:
	hdir_unlock(hidden_dir, dir, bindex);
	dput(wh_dentry);
	dput(hidden_dentry);
 out_arg:
	di_write_unlock(parent);
	aufs_read_unlock(dentry, AUFS_D_WLOCK);
	kfree(arg);
 out_whlist:
	nhash_del(whlist);
 out:
	TraceErr(err);
	return err;
}
Exemple #7
0
int aufs_unlink(struct inode *dir, struct dentry *dentry)
{
	int err, dlgt;
	struct inode *inode, *hidden_dir;
	struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent;
	struct dtime dt;
	aufs_bindex_t bwh, bindex, bstart;

	LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
	IMustLock(dir);
	inode = dentry->d_inode;
	if (unlikely(!inode))
		return -ENOENT; // possible?
	IMustLock(inode);

	aufs_read_lock(dentry, AUFS_D_WLOCK);
	parent = dentry->d_parent;
	di_write_lock_parent(parent);

	bstart = dbstart(dentry);
	bwh = dbwh(dentry);
	bindex = -1;
	wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt);
	//wh_dentry = ERR_PTR(-1);
	err = PTR_ERR(wh_dentry);
	if (IS_ERR(wh_dentry))
		goto out;

	dlgt = need_dlgt(dir->i_sb);
	hidden_dentry = au_h_dptr(dentry);
	dget(hidden_dentry);
	hidden_parent = hidden_dentry->d_parent;
	hidden_dir = hidden_parent->d_inode;

	if (bindex == bstart) {
		err = vfsub_unlink(hidden_dir, hidden_dentry, dlgt);
		//err = -1;
	} else {
		DEBUG_ON(!wh_dentry);
		hidden_parent = wh_dentry->d_parent;
		DEBUG_ON(hidden_parent != au_h_dptr_i(parent, bindex));
		hidden_dir = hidden_parent->d_inode;
		IMustLock(hidden_dir);
		err = 0;
	}

	if (!err) {
		inode->i_nlink--;
		epilog(dir, dentry, bindex);
		goto out_unlock; /* success */
	}

	/* revert */
	if (wh_dentry) {
		int rerr;
		rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, dlgt);
		if (rerr)
			err = rerr;
	}

 out_unlock:
	hdir_unlock(hidden_dir, dir, bindex);
	dput(wh_dentry);
	dput(hidden_dentry);
 out:
	di_write_unlock(parent);
	aufs_read_unlock(dentry, AUFS_D_WLOCK);
	TraceErr(err);
	return err;
}