kprintf(ARGS(rename, "%s, %s"), from, to);
#endif
get_mplock();
- error = nlookup_init(&fromnd, from, UIO_SYSSPACE, 0);
- if (error == 0) {
- error = nlookup_init(&tond, to, UIO_SYSSPACE, 0);
- if (error == 0)
- error = kern_rename(&fromnd, &tond);
- nlookup_done(&tond);
- }
- nlookup_done(&fromnd);
+ do {
+ error = nlookup_init(&fromnd, from, UIO_SYSSPACE, 0);
+ if (error == 0) {
+ error = nlookup_init(&tond, to, UIO_SYSSPACE, 0);
+ if (error == 0)
+ error = kern_rename(&fromnd, &tond);
+ nlookup_done(&tond);
+ }
+ nlookup_done(&fromnd);
+ } while (error == EAGAIN);
rel_mplock();
linux_free_path(&from);
linux_free_path(&to);
fromnd->nl_flags |= NLC_NCPISLOCKED;
/*
+ * If either fromnd or tond are marked destroyed a ripout occured
+ * out from under us and we must retry.
+ */
+ if ((fromnd->nl_nch.ncp->nc_flag & (NCF_DESTROYED | NCF_UNRESOLVED)) ||
+ fromnd->nl_nch.ncp->nc_vp == NULL ||
+ (tond->nl_nch.ncp->nc_flag & NCF_DESTROYED)) {
+ kprintf("kern_rename: retry due to ripout on: "
+ "\"%s\" -> \"%s\"\n",
+ fromnd->nl_nch.ncp->nc_name,
+ tond->nl_nch.ncp->nc_name);
+ cache_drop(&fnchd);
+ cache_drop(&tnchd);
+ return (EAGAIN);
+ }
+
+ /*
* make sure the parent directories linkages are the same
*/
if (fnchd.ncp != fromnd->nl_nch.ncp->nc_parent ||
struct nlookupdata fromnd, tond;
int error;
- error = nlookup_init(&fromnd, uap->from, UIO_USERSPACE, 0);
- if (error == 0) {
- error = nlookup_init(&tond, uap->to, UIO_USERSPACE, 0);
- if (error == 0)
- error = kern_rename(&fromnd, &tond);
- nlookup_done(&tond);
- }
- nlookup_done(&fromnd);
+ do {
+ error = nlookup_init(&fromnd, uap->from, UIO_USERSPACE, 0);
+ if (error == 0) {
+ error = nlookup_init(&tond, uap->to, UIO_USERSPACE, 0);
+ if (error == 0)
+ error = kern_rename(&fromnd, &tond);
+ nlookup_done(&tond);
+ }
+ nlookup_done(&fromnd);
+ } while (error == EAGAIN);
return (error);
}
struct file *oldfp, *newfp;
int error;
- error = nlookup_init_at(&oldnd, &oldfp, uap->oldfd, uap->old,
- UIO_USERSPACE, 0);
- if (error == 0) {
- error = nlookup_init_at(&newnd, &newfp, uap->newfd, uap->new,
- UIO_USERSPACE, 0);
- if (error == 0)
- error = kern_rename(&oldnd, &newnd);
- nlookup_done_at(&newnd, newfp);
- }
- nlookup_done_at(&oldnd, oldfp);
+ do {
+ error = nlookup_init_at(&oldnd, &oldfp,
+ uap->oldfd, uap->old,
+ UIO_USERSPACE, 0);
+ if (error == 0) {
+ error = nlookup_init_at(&newnd, &newfp,
+ uap->newfd, uap->new,
+ UIO_USERSPACE, 0);
+ if (error == 0)
+ error = kern_rename(&oldnd, &newnd);
+ nlookup_done_at(&newnd, newfp);
+ }
+ nlookup_done_at(&oldnd, oldfp);
+ } while (error == EAGAIN);
return (error);
}