Changeset View
Changeset View
Standalone View
Standalone View
sys/ufs/ffs/ffs_softdep.c
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 615 Lines • ▼ Show 20 Lines | softdep_prerename(fdvp, fvp, tdvp, tvp) | ||||
struct vnode *tdvp; | struct vnode *tdvp; | ||||
struct vnode *tvp; | struct vnode *tvp; | ||||
{ | { | ||||
panic("softdep_prerename called"); | panic("softdep_prerename called"); | ||||
} | } | ||||
int | int | ||||
softdep_prelink(dvp, vp) | softdep_prelink(dvp, vp, cnp) | ||||
struct vnode *dvp; | struct vnode *dvp; | ||||
struct vnode *vp; | struct vnode *vp; | ||||
struct componentname *cnp; | |||||
{ | { | ||||
panic("softdep_prelink called"); | panic("softdep_prelink called"); | ||||
} | } | ||||
#else | #else | ||||
FEATURE(softupdates, "FFS soft-updates support"); | FEATURE(softupdates, "FFS soft-updates support"); | ||||
▲ Show 20 Lines • Show All 2,744 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* Returns 0 if all owned locks are still valid and were not dropped | * Returns 0 if all owned locks are still valid and were not dropped | ||||
* in the process, in other case it returns either an error from sync, | * in the process, in other case it returns either an error from sync, | ||||
* or ERELOOKUP if any of the locks were re-acquired. In the later | * or ERELOOKUP if any of the locks were re-acquired. In the later | ||||
* case, the state of the vnodes cannot be relied upon and our VFS | * case, the state of the vnodes cannot be relied upon and our VFS | ||||
* syscall must be restarted at top level from the lookup. | * syscall must be restarted at top level from the lookup. | ||||
*/ | */ | ||||
int | int | ||||
softdep_prelink(dvp, vp) | softdep_prelink(dvp, vp, cnp) | ||||
struct vnode *dvp; | struct vnode *dvp; | ||||
struct vnode *vp; | struct vnode *vp; | ||||
struct componentname *cnp; | |||||
{ | { | ||||
struct ufsmount *ump; | struct ufsmount *ump; | ||||
struct nameidata *ndp; | |||||
ASSERT_VOP_ELOCKED(dvp, "prelink dvp"); | ASSERT_VOP_ELOCKED(dvp, "prelink dvp"); | ||||
if (vp != NULL) | if (vp != NULL) | ||||
ASSERT_VOP_ELOCKED(vp, "prelink vp"); | ASSERT_VOP_ELOCKED(vp, "prelink vp"); | ||||
ump = VFSTOUFS(dvp->v_mount); | ump = VFSTOUFS(dvp->v_mount); | ||||
/* | /* | ||||
* Nothing to do if we have sufficient journal space. We skip | * Nothing to do if we have sufficient journal space. We skip | ||||
* flushing when vp is a snapshot to avoid deadlock where | * flushing when vp is a snapshot to avoid deadlock where | ||||
* another thread is trying to update the inodeblock for dvp | * another thread is trying to update the inodeblock for dvp | ||||
* and is waiting on snaplk that vp holds. | * and is waiting on snaplk that vp holds. | ||||
*/ | */ | ||||
if (journal_space(ump, 0) || (vp != NULL && IS_SNAPSHOT(VTOI(vp)))) | if (journal_space(ump, 0) || (vp != NULL && IS_SNAPSHOT(VTOI(vp)))) | ||||
return (0); | return (0); | ||||
/* | |||||
markj: unionfs does not pass a full nameidata to VOP_MKDIR in unionfs_mkshadowdir(). There is a… | |||||
* Check if the journal space consumption can in theory be | |||||
* accounted on dvp and vp. If the vnodes metadata was not | |||||
* changed comparing with the previous round-trip into | |||||
* softdep_prelink(), as indicated by the seqc generation | |||||
Done Inline ActionsI think it is worth adding a comment explaining the problem solved by this check. markj: I think it is worth adding a comment explaining the problem solved by this check. | |||||
* recorded in the nameidata, then there is no point in | |||||
* starting the sync. | |||||
*/ | |||||
ndp = __containerof(cnp, struct nameidata, ni_cnd); | |||||
if (!seqc_in_modify(ndp->ni_dvp_seqc) && | |||||
vn_seqc_consistent(dvp, ndp->ni_dvp_seqc) && | |||||
(vp == NULL || (!seqc_in_modify(ndp->ni_vp_seqc) && | |||||
vn_seqc_consistent(vp, ndp->ni_vp_seqc)))) | |||||
return (0); | |||||
stat_journal_low++; | stat_journal_low++; | ||||
if (vp != NULL) { | if (vp != NULL) { | ||||
VOP_UNLOCK(dvp); | VOP_UNLOCK(dvp); | ||||
ffs_syncvnode(vp, MNT_NOWAIT, 0); | ffs_syncvnode(vp, MNT_NOWAIT, 0); | ||||
vn_lock_pair(dvp, false, vp, true); | vn_lock_pair(dvp, false, vp, true); | ||||
if (dvp->v_data == NULL) | if (dvp->v_data == NULL) | ||||
return (ERELOOKUP); | goto out; | ||||
} | } | ||||
if (vp != NULL) | if (vp != NULL) | ||||
VOP_UNLOCK(vp); | VOP_UNLOCK(vp); | ||||
ffs_syncvnode(dvp, MNT_WAIT, 0); | ffs_syncvnode(dvp, MNT_WAIT, 0); | ||||
VOP_UNLOCK(dvp); | |||||
/* Process vp before dvp as it may create .. removes. */ | /* Process vp before dvp as it may create .. removes. */ | ||||
if (vp != NULL) { | if (vp != NULL) { | ||||
VOP_UNLOCK(dvp); | |||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); | ||||
if (vp->v_data == NULL) { | if (vp->v_data == NULL) { | ||||
vn_lock_pair(dvp, false, vp, true); | vn_lock_pair(dvp, false, vp, true); | ||||
return (ERELOOKUP); | goto out; | ||||
} | } | ||||
ACQUIRE_LOCK(ump); | ACQUIRE_LOCK(ump); | ||||
process_removes(vp); | process_removes(vp); | ||||
process_truncates(vp); | process_truncates(vp); | ||||
FREE_LOCK(ump); | FREE_LOCK(ump); | ||||
VOP_UNLOCK(vp); | VOP_UNLOCK(vp); | ||||
} | |||||
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); | vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); | ||||
if (dvp->v_data == NULL) { | if (dvp->v_data == NULL) { | ||||
vn_lock_pair(dvp, true, vp, false); | vn_lock_pair(dvp, true, vp, false); | ||||
return (ERELOOKUP); | goto out; | ||||
} | } | ||||
} | |||||
ACQUIRE_LOCK(ump); | ACQUIRE_LOCK(ump); | ||||
process_removes(dvp); | process_removes(dvp); | ||||
process_truncates(dvp); | process_truncates(dvp); | ||||
VOP_UNLOCK(dvp); | VOP_UNLOCK(dvp); | ||||
softdep_speedup(ump); | softdep_speedup(ump); | ||||
process_worklist_item(UFSTOVFS(ump), 2, LK_NOWAIT); | process_worklist_item(UFSTOVFS(ump), 2, LK_NOWAIT); | ||||
if (journal_space(ump, 0) == 0) { | if (journal_space(ump, 0) == 0) { | ||||
softdep_speedup(ump); | softdep_speedup(ump); | ||||
mckusickUnsubmitted Done Inline ActionsI suggest that you add FREE_LOCK(ump); VFS_SYNC(mp, MNT_NOWAIT); ffs_sbupdate(ump, MNT_WAIT, 0); ACQUIRE_LOCK(ump); As I suggested in my comment this will likely clear the oldest entries in the journal which will avoid causing us to suspend the filesystem. Note that you you will need to save mp above. mckusick: I suggest that you add
```
FREE_LOCK(ump);
VFS_SYNC(mp… | |||||
if (journal_space(ump, 1) == 0) | if (journal_space(ump, 1) == 0) | ||||
journal_suspend(ump); | journal_suspend(ump); | ||||
} | } | ||||
FREE_LOCK(ump); | FREE_LOCK(ump); | ||||
vn_lock_pair(dvp, false, vp, false); | vn_lock_pair(dvp, false, vp, false); | ||||
out: | |||||
ndp->ni_dvp_seqc = vn_seqc_read_any(dvp); | |||||
if (vp != NULL) | |||||
ndp->ni_vp_seqc = vn_seqc_read_any(vp); | |||||
return (ERELOOKUP); | return (ERELOOKUP); | ||||
} | } | ||||
static void | static void | ||||
jseg_write(ump, jseg, data) | jseg_write(ump, jseg, data) | ||||
struct ufsmount *ump; | struct ufsmount *ump; | ||||
struct jseg *jseg; | struct jseg *jseg; | ||||
uint8_t *data; | uint8_t *data; | ||||
▲ Show 20 Lines • Show All 11,722 Lines • Show Last 20 Lines |
unionfs does not pass a full nameidata to VOP_MKDIR in unionfs_mkshadowdir(). There is a similar problem with unionfs_mkwhiteout() and unionfs_vn_create_on_upper().