summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ffs/ffs_extern.h7
-rw-r--r--sys/ufs/ffs/ffs_inode.c49
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c56
-rw-r--r--sys/ufs/ffs/ffs_softdep.c98
-rw-r--r--sys/ufs/ffs/ffs_vnops.c15
-rw-r--r--sys/ufs/ufs/inode.h1
6 files changed, 151 insertions, 75 deletions
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index bfc0256..258966c 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -167,6 +167,13 @@ void softdep_freework(struct workhead *);
#define FLUSH_INODES_WAIT 2
#define FLUSH_BLOCKS 3
#define FLUSH_BLOCKS_WAIT 4
+/*
+ * Flag to ffs_syncinode() to request flushing of data only,
+ * but skip the ffs_update() on the inode itself. Used to avoid
+ * deadlock when flushing snapshot inodes while holding snaplk.
+ * Avoid bit conflicts with MNT_WAIT values in sys/mount.h
+ */
+#define NO_INO_UPDT 0x10
int ffs_rdonly(struct inode *);
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c
index 101bdb4..2667e31 100644
--- a/sys/ufs/ffs/ffs_inode.c
+++ b/sys/ufs/ffs/ffs_inode.c
@@ -81,7 +81,7 @@ ffs_update(vp, waitfor)
struct fs *fs;
struct buf *bp;
struct inode *ip;
- int error;
+ int flags, error;
ASSERT_VOP_ELOCKED(vp, "ffs_update");
ufs_itimes(vp);
@@ -92,11 +92,36 @@ ffs_update(vp, waitfor)
fs = ip->i_fs;
if (fs->fs_ronly && ip->i_ump->um_fsckpid == 0)
return (0);
- error = bread(ip->i_devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
- (int)fs->fs_bsize, NOCRED, &bp);
- if (error) {
- brelse(bp);
- return (error);
+ /*
+ * If we are updating a snapshot and another process is currently
+ * writing the buffer containing the inode for this snapshot then
+ * a deadlock can occur when it tries to check the snapshot to see
+ * if that block needs to be copied. Thus when updating a snapshot
+ * we check to see if the buffer is already locked, and if it is
+ * we drop the snapshot lock until the buffer has been written
+ * and is available to us. We have to grab a reference to the
+ * snapshot vnode to prevent it from being removed while we are
+ * waiting for the buffer.
+ */
+ flags = 0;
+ if (IS_SNAPSHOT(ip))
+ flags = GB_LOCK_NOWAIT;
+ error = breadn_flags(ip->i_devvp,
+ fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
+ (int) fs->fs_bsize, 0, 0, 0, NOCRED, flags, &bp);
+ if (error != 0) {
+ if (error != EBUSY) {
+ brelse(bp);
+ return (error);
+ }
+ KASSERT((IS_SNAPSHOT(ip)), ("EBUSY from non-snapshot"));
+ vref(vp); /* Protect against ffs_snapgone() */
+ VOP_UNLOCK(vp, 0);
+ (void) bread(ip->i_devvp,
+ fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
+ (int) fs->fs_bsize, NOCRED, &bp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ vrele(vp);
}
if (DOINGSOFTDEP(vp))
softdep_update_inodeblock(ip, bp, waitfor);
@@ -108,16 +133,16 @@ ffs_update(vp, waitfor)
else
*((struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2;
- if (waitfor && !DOINGASYNC(vp)) {
- return (bwrite(bp));
- } else if (vm_page_count_severe() || buf_dirty_count_severe()) {
- return (bwrite(bp));
+ if ((waitfor && !DOINGASYNC(vp)) ||
+ (vm_page_count_severe() || buf_dirty_count_severe())) {
+ error = bwrite(bp);
} else {
if (bp->b_bufsize == fs->fs_bsize)
bp->b_flags |= B_CLUSTEROK;
bdwrite(bp);
- return (0);
+ error = 0;
}
+ return (error);
}
#define SINGLE 0 /* index of single indirect block */
@@ -253,7 +278,7 @@ ffs_truncate(vp, length, flags, cred, td)
}
if (fs->fs_ronly)
panic("ffs_truncate: read-only filesystem");
- if ((ip->i_flags & SF_SNAPSHOT) != 0)
+ if (IS_SNAPSHOT(ip))
ffs_snapremove(vp);
vp->v_lasta = vp->v_clen = vp->v_cstart = vp->v_lastw = 0;
osize = ip->i_size;
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index adc1d78..c930f5d 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -203,6 +203,7 @@ ffs_snapshot(mp, snapfile)
ufs2_daddr_t numblks, blkno, *blkp, *snapblklist;
int error, cg, snaploc;
int i, size, len, loc;
+ ufs2_daddr_t blockno;
uint64_t flag;
struct timespec starttime = {0, 0}, endtime;
char saved_nice = 0;
@@ -529,7 +530,7 @@ loop:
(xvp->v_usecount == 0 &&
(xvp->v_iflag & (VI_OWEINACT | VI_DOINGINACT)) == 0) ||
xvp->v_type == VNON ||
- (VTOI(xvp)->i_flags & SF_SNAPSHOT)) {
+ IS_SNAPSHOT(VTOI(xvp))) {
VI_UNLOCK(xvp);
MNT_ILOCK(mp);
continue;
@@ -815,21 +816,26 @@ out1:
if (space != NULL)
free(space, M_UFSMNT);
/*
- * If another process is currently writing the buffer containing
- * the inode for this snapshot then a deadlock can occur. Drop
- * the snapshot lock until the buffer has been written.
+ * Preallocate all the direct blocks in the snapshot inode so
+ * that we never have to write the inode itself to commit an
+ * update to the contents of the snapshot. Note that once
+ * created, the size of the snapshot will never change, so
+ * there will never be a need to write the inode except to
+ * update the non-integrity-critical time fields and
+ * allocated-block count.
*/
- VREF(vp); /* Protect against ffs_snapgone() */
- VOP_UNLOCK(vp, 0);
- (void) bread(ip->i_devvp,
- fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
- (int) fs->fs_bsize, NOCRED, &nbp);
- brelse(nbp);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- if (ip->i_effnlink == 0)
- error = ENOENT; /* Snapshot file unlinked */
- else
- vrele(vp); /* Drop extra reference */
+ for (blockno = 0; blockno < NDADDR; blockno++) {
+ if (DIP(ip, i_db[blockno]) != 0)
+ continue;
+ error = UFS_BALLOC(vp, lblktosize(fs, blockno),
+ fs->fs_bsize, KERNCRED, BA_CLRBUF, &bp);
+ if (error)
+ break;
+ error = readblock(vp, bp, blockno);
+ bawrite(bp);
+ if (error != 0)
+ break;
+ }
done:
free(copy_fs->fs_csp, M_UFSMNT);
free(copy_fs, M_UFSMNT);
@@ -1902,7 +1908,7 @@ retry:
bawrite(cbp);
if ((vtype == VDIR || dopersistence) &&
ip->i_effnlink > 0)
- (void) ffs_syncvnode(vp, MNT_WAIT);
+ (void) ffs_syncvnode(vp, MNT_WAIT|NO_INO_UPDT);
continue;
}
/*
@@ -1913,7 +1919,7 @@ retry:
bawrite(cbp);
if ((vtype == VDIR || dopersistence) &&
ip->i_effnlink > 0)
- (void) ffs_syncvnode(vp, MNT_WAIT);
+ (void) ffs_syncvnode(vp, MNT_WAIT|NO_INO_UPDT);
break;
}
savedcbp = cbp;
@@ -1931,7 +1937,7 @@ retry:
bawrite(savedcbp);
if ((vtype == VDIR || dopersistence) &&
VTOI(vp)->i_effnlink > 0)
- (void) ffs_syncvnode(vp, MNT_WAIT);
+ (void) ffs_syncvnode(vp, MNT_WAIT|NO_INO_UPDT);
}
/*
* If we have been unable to allocate a block in which to do
@@ -1987,9 +1993,9 @@ ffs_snapshot_mount(mp)
continue;
}
ip = VTOI(vp);
- if ((ip->i_flags & SF_SNAPSHOT) == 0 || ip->i_size ==
+ if (!IS_SNAPSHOT(ip) || ip->i_size ==
lblktosize(fs, howmany(fs->fs_size, fs->fs_frag))) {
- if ((ip->i_flags & SF_SNAPSHOT) == 0) {
+ if (!IS_SNAPSHOT(ip)) {
reason = "non-snapshot";
} else {
reason = "old format snapshot";
@@ -2250,7 +2256,7 @@ ffs_copyonwrite(devvp, bp)
int launched_async_io, prev_norunningbuf;
long saved_runningbufspace;
- if (devvp != bp->b_vp && (VTOI(bp->b_vp)->i_flags & SF_SNAPSHOT) != 0)
+ if (devvp != bp->b_vp && IS_SNAPSHOT(VTOI(bp->b_vp)))
return (0); /* Update on a snapshot file */
if (td->td_pflags & TDP_COWINPROGRESS)
panic("ffs_copyonwrite: recursive call");
@@ -2395,7 +2401,7 @@ ffs_copyonwrite(devvp, bp)
bawrite(cbp);
if ((devvp == bp->b_vp || bp->b_vp->v_type == VDIR ||
dopersistence) && ip->i_effnlink > 0)
- (void) ffs_syncvnode(vp, MNT_WAIT);
+ (void) ffs_syncvnode(vp, MNT_WAIT|NO_INO_UPDT);
else
launched_async_io = 1;
continue;
@@ -2408,7 +2414,7 @@ ffs_copyonwrite(devvp, bp)
bawrite(cbp);
if ((devvp == bp->b_vp || bp->b_vp->v_type == VDIR ||
dopersistence) && ip->i_effnlink > 0)
- (void) ffs_syncvnode(vp, MNT_WAIT);
+ (void) ffs_syncvnode(vp, MNT_WAIT|NO_INO_UPDT);
else
launched_async_io = 1;
break;
@@ -2428,7 +2434,7 @@ ffs_copyonwrite(devvp, bp)
bawrite(savedcbp);
if ((devvp == bp->b_vp || bp->b_vp->v_type == VDIR ||
dopersistence) && VTOI(vp)->i_effnlink > 0)
- (void) ffs_syncvnode(vp, MNT_WAIT);
+ (void) ffs_syncvnode(vp, MNT_WAIT|NO_INO_UPDT);
else
launched_async_io = 1;
}
@@ -2478,7 +2484,7 @@ ffs_sync_snap(mp, waitfor)
}
TAILQ_FOREACH(ip, &sn->sn_head, i_nextsnap) {
vp = ITOV(ip);
- ffs_syncvnode(vp, waitfor);
+ ffs_syncvnode(vp, waitfor|NO_INO_UPDT);
}
lockmgr(&sn->sn_lock, LK_RELEASE, NULL);
}
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 9639076..debb838 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -2827,7 +2827,12 @@ softdep_prealloc(vp, waitok)
{
struct ufsmount *ump;
- if (DOINGSUJ(vp) == 0)
+ /*
+ * Nothing to do if we are not running journaled soft updates.
+ * If we currently hold the snapshot lock, we must avoid handling
+ * other resources that could cause deadlock.
+ */
+ if (DOINGSUJ(vp) == 0 || IS_SNAPSHOT(VTOI(vp)))
return (0);
ump = VFSTOUFS(vp->v_mount);
ACQUIRE_LOCK(&lk);
@@ -2873,7 +2878,12 @@ softdep_prelink(dvp, vp)
ump = VFSTOUFS(dvp->v_mount);
mtx_assert(&lk, MA_OWNED);
- if (journal_space(ump, 0))
+ /*
+ * Nothing to do if we have sufficient journal space.
+ * If we currently hold the snapshot lock, we must avoid
+ * handling other resources that could cause deadlock.
+ */
+ if (journal_space(ump, 0) || (vp && IS_SNAPSHOT(VTOI(vp))))
return;
stat_journal_low++;
FREE_LOCK(&lk);
@@ -4304,11 +4314,15 @@ inodedep_lookup_ip(ip)
struct inode *ip;
{
struct inodedep *inodedep;
+ int dflags;
KASSERT(ip->i_nlink >= ip->i_effnlink,
("inodedep_lookup_ip: bad delta"));
- (void) inodedep_lookup(UFSTOVFS(ip->i_ump), ip->i_number,
- DEPALLOC, &inodedep);
+ dflags = DEPALLOC;
+ if (IS_SNAPSHOT(ip))
+ dflags |= NODELAY;
+ (void) inodedep_lookup(UFSTOVFS(ip->i_ump), ip->i_number, dflags,
+ &inodedep);
inodedep->id_nlinkdelta = ip->i_nlink - ip->i_effnlink;
return (inodedep);
@@ -4696,7 +4710,7 @@ softdep_setup_inomapdep(bp, ip, newinum, mode)
* the cylinder group map from which it was allocated.
*/
ACQUIRE_LOCK(&lk);
- if ((inodedep_lookup(mp, newinum, DEPALLOC|NODELAY, &inodedep)))
+ if ((inodedep_lookup(mp, newinum, DEPALLOC | NODELAY, &inodedep)))
panic("softdep_setup_inomapdep: dependency %p for new"
"inode already exists", inodedep);
bmsafemap = bmsafemap_lookup(mp, bp, ino_to_cg(fs, newinum));
@@ -5437,6 +5451,7 @@ softdep_setup_allocindir_page(ip, lbn, bp, ptrno, newblkno, oldblkno, nbp)
struct allocindir *aip;
struct pagedep *pagedep;
struct mount *mp;
+ int dflags;
if (lbn != nbp->b_lblkno)
panic("softdep_setup_allocindir_page: lbn %jd != lblkno %jd",
@@ -5444,7 +5459,10 @@ softdep_setup_allocindir_page(ip, lbn, bp, ptrno, newblkno, oldblkno, nbp)
ASSERT_VOP_LOCKED(ITOV(ip), "softdep_setup_allocindir_page");
mp = UFSTOVFS(ip->i_ump);
aip = newallocindir(ip, ptrno, newblkno, oldblkno, lbn);
- (void) inodedep_lookup(mp, ip->i_number, DEPALLOC, &inodedep);
+ dflags = DEPALLOC;
+ if (IS_SNAPSHOT(ip))
+ dflags |= NODELAY;
+ (void) inodedep_lookup(mp, ip->i_number, dflags, &inodedep);
/*
* If we are allocating a directory page, then we must
* allocate an associated pagedep to track additions and
@@ -5474,11 +5492,15 @@ softdep_setup_allocindir_meta(nbp, ip, bp, ptrno, newblkno)
struct inodedep *inodedep;
struct allocindir *aip;
ufs_lbn_t lbn;
+ int dflags;
lbn = nbp->b_lblkno;
ASSERT_VOP_LOCKED(ITOV(ip), "softdep_setup_allocindir_meta");
aip = newallocindir(ip, ptrno, newblkno, 0, lbn);
- inodedep_lookup(UFSTOVFS(ip->i_ump), ip->i_number, DEPALLOC, &inodedep);
+ dflags = DEPALLOC;
+ if (IS_SNAPSHOT(ip))
+ dflags |= NODELAY;
+ inodedep_lookup(UFSTOVFS(ip->i_ump), ip->i_number, dflags, &inodedep);
WORKLIST_INSERT(&nbp->b_dep, &aip->ai_block.nb_list);
if (setup_allocindir_phase2(bp, ip, inodedep, aip, lbn))
panic("softdep_setup_allocindir_meta: Block already existed");
@@ -6085,11 +6107,7 @@ softdep_journal_freeblocks(ip, cred, length, flags)
struct mount *mp;
ufs2_daddr_t extblocks, datablocks;
ufs_lbn_t tmpval, lbn, lastlbn;
- int frags;
- int lastoff, iboff;
- int allocblock;
- int error, i;
- int needj;
+ int frags, lastoff, iboff, allocblock, needj, dflags, error, i;
fs = ip->i_fs;
mp = UFSTOVFS(ip->i_ump);
@@ -6107,7 +6125,10 @@ softdep_journal_freeblocks(ip, cred, length, flags)
* we don't need to journal the block frees. The canceled journals
* for the allocations will suffice.
*/
- inodedep_lookup(mp, ip->i_number, DEPALLOC, &inodedep);
+ dflags = DEPALLOC;
+ if (IS_SNAPSHOT(ip))
+ dflags |= NODELAY;
+ inodedep_lookup(mp, ip->i_number, dflags, &inodedep);
if ((inodedep->id_state & (UNLINKED | DEPCOMPLETE)) == UNLINKED &&
length == 0)
needj = 0;
@@ -6232,7 +6253,7 @@ softdep_journal_freeblocks(ip, cred, length, flags)
*((struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2;
ACQUIRE_LOCK(&lk);
- (void) inodedep_lookup(mp, ip->i_number, DEPALLOC, &inodedep);
+ (void) inodedep_lookup(mp, ip->i_number, dflags, &inodedep);
if ((inodedep->id_state & IOSTARTED) != 0)
panic("softdep_setup_freeblocks: inode busy");
/*
@@ -6310,7 +6331,7 @@ softdep_journal_freeblocks(ip, cred, length, flags)
}
ACQUIRE_LOCK(&lk);
- inodedep_lookup(mp, ip->i_number, DEPALLOC, &inodedep);
+ inodedep_lookup(mp, ip->i_number, dflags, &inodedep);
TAILQ_INSERT_TAIL(&inodedep->id_freeblklst, freeblks, fb_next);
freeblks->fb_state |= DEPCOMPLETE | ONDEPLIST;
/*
@@ -6398,7 +6419,7 @@ softdep_setup_freeblocks(ip, length, flags)
struct fs *fs;
ufs2_daddr_t extblocks, datablocks;
struct mount *mp;
- int i, delay, error;
+ int i, delay, error, dflags;
ufs_lbn_t tmpval;
ufs_lbn_t lbn;
@@ -6463,7 +6484,10 @@ softdep_setup_freeblocks(ip, length, flags)
* Find and eliminate any inode dependencies.
*/
ACQUIRE_LOCK(&lk);
- (void) inodedep_lookup(mp, ip->i_number, DEPALLOC, &inodedep);
+ dflags = DEPALLOC;
+ if (IS_SNAPSHOT(ip))
+ dflags |= NODELAY;
+ (void) inodedep_lookup(mp, ip->i_number, dflags, &inodedep);
if ((inodedep->id_state & IOSTARTED) != 0)
panic("softdep_setup_freeblocks: inode busy");
/*
@@ -8029,7 +8053,7 @@ softdep_setup_directory_add(bp, dp, diroffset, newinum, newdirbp, isnewblk)
dap->da_pagedep = pagedep;
LIST_INSERT_HEAD(&pagedep->pd_diraddhd[DIRADDHASH(offset)], dap,
da_pdlist);
- inodedep_lookup(mp, newinum, DEPALLOC, &inodedep);
+ inodedep_lookup(mp, newinum, DEPALLOC | NODELAY, &inodedep);
/*
* If we're journaling, link the diradd into the jaddref so it
* may be completed after the journal entry is written. Otherwise,
@@ -8631,8 +8655,7 @@ newdirrem(bp, dp, ip, isrmdir, prevdirremp)
* the number of freefile and freeblks structures.
*/
ACQUIRE_LOCK(&lk);
- if (!(ip->i_flags & SF_SNAPSHOT) &&
- dep_current[D_DIRREM] > max_softdeps / 2)
+ if (!IS_SNAPSHOT(ip) && dep_current[D_DIRREM] > max_softdeps / 2)
(void) request_cleanup(ITOV(dp)->v_mount, FLUSH_BLOCKS);
FREE_LOCK(&lk);
dirrem = malloc(sizeof(struct dirrem),
@@ -8866,11 +8889,11 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir)
/*
* Lookup the jaddref for this journal entry. We must finish
* initializing it and make the diradd write dependent on it.
- * If we're not journaling Put it on the id_bufwait list if the inode
- * is not yet written. If it is written, do the post-inode write
- * processing to put it on the id_pendinghd list.
+ * If we're not journaling, put it on the id_bufwait list if the
+ * inode is not yet written. If it is written, do the post-inode
+ * write processing to put it on the id_pendinghd list.
*/
- inodedep_lookup(mp, newinum, DEPALLOC, &inodedep);
+ inodedep_lookup(mp, newinum, DEPALLOC | NODELAY, &inodedep);
if (MOUNTEDSUJ(mp)) {
jaddref = (struct jaddref *)TAILQ_LAST(&inodedep->id_inoreflst,
inoreflst);
@@ -8912,9 +8935,13 @@ softdep_change_linkcnt(ip)
struct inode *ip; /* the inode with the increased link count */
{
struct inodedep *inodedep;
+ int dflags;
ACQUIRE_LOCK(&lk);
- inodedep_lookup(UFSTOVFS(ip->i_ump), ip->i_number, DEPALLOC, &inodedep);
+ dflags = DEPALLOC;
+ if (IS_SNAPSHOT(ip))
+ dflags |= NODELAY;
+ inodedep_lookup(UFSTOVFS(ip->i_ump), ip->i_number, dflags, &inodedep);
if (ip->i_nlink < ip->i_effnlink)
panic("softdep_change_linkcnt: bad delta");
inodedep->id_nlinkdelta = ip->i_nlink - ip->i_effnlink;
@@ -12544,22 +12571,25 @@ softdep_request_cleanup(fs, vp, cred, resource)
ufs2_daddr_t needed;
int error;
- mp = vp->v_mount;
- ump = VFSTOUFS(mp);
- mtx_assert(UFS_MTX(ump), MA_OWNED);
- if (resource == FLUSH_BLOCKS_WAIT)
- stat_cleanup_blkrequests += 1;
- else
- stat_cleanup_inorequests += 1;
-
/*
* If we are being called because of a process doing a
* copy-on-write, then it is not safe to process any
* worklist items as we will recurse into the copyonwrite
* routine. This will result in an incoherent snapshot.
+ * If the vnode that we hold is a snapshot, we must avoid
+ * handling other resources that could cause deadlock.
*/
- if (curthread->td_pflags & TDP_COWINPROGRESS)
+ if ((curthread->td_pflags & TDP_COWINPROGRESS) || IS_SNAPSHOT(VTOI(vp)))
return (0);
+
+ if (resource == FLUSH_BLOCKS_WAIT)
+ stat_cleanup_blkrequests += 1;
+ else
+ stat_cleanup_inorequests += 1;
+
+ mp = vp->v_mount;
+ ump = VFSTOUFS(mp);
+ mtx_assert(UFS_MTX(ump), MA_OWNED);
UFS_UNLOCK(ump);
error = ffs_update(vp, 1);
if (error != 0) {
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index 4783f65..9e8648e 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -216,8 +216,10 @@ ffs_syncvnode(struct vnode *vp, int waitfor)
struct buf *bp;
struct buf *nbp;
ufs_lbn_t lbn;
- int error, wait, passes;
+ int error, wait, passes, noupdate;
+ noupdate = waitfor & NO_INO_UPDT;
+ waitfor &= ~NO_INO_UPDT;
ip = VTOI(vp);
ip->i_flag &= ~IN_NEEDSYNC;
bo = &vp->v_bufobj;
@@ -300,7 +302,10 @@ next:
}
if (waitfor != MNT_WAIT) {
BO_UNLOCK(bo);
- return (ffs_update(vp, waitfor));
+ if (noupdate)
+ return (0);
+ else
+ return (ffs_update(vp, waitfor));
}
/* Drain IO to see if we're done. */
bufobj_wwait(bo, 0, 0);
@@ -317,7 +322,7 @@ next:
*/
if (bo->bo_dirty.bv_cnt > 0) {
/* Write the inode after sync passes to flush deps. */
- if (wait && DOINGSOFTDEP(vp)) {
+ if (wait && DOINGSOFTDEP(vp) && noupdate == 0) {
BO_UNLOCK(bo);
ffs_update(vp, MNT_WAIT);
BO_LOCK(bo);
@@ -332,7 +337,9 @@ next:
#endif
}
BO_UNLOCK(bo);
- error = ffs_update(vp, MNT_WAIT);
+ error = 0;
+ if (noupdate == 0)
+ error = ffs_update(vp, MNT_WAIT);
if (DOINGSUJ(vp))
softdep_journal_fsync(VTOI(vp));
return (error);
diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h
index 3519ca2..2b02000 100644
--- a/sys/ufs/ufs/inode.h
+++ b/sys/ufs/ufs/inode.h
@@ -158,6 +158,7 @@ struct inode {
#define SHORTLINK(ip) \
(((ip)->i_ump->um_fstype == UFS1) ? \
(caddr_t)(ip)->i_din1->di_db : (caddr_t)(ip)->i_din2->di_db)
+#define IS_SNAPSHOT(ip) ((ip)->i_flags & SF_SNAPSHOT)
/*
* Structure used to pass around logical block paths generated by
OpenPOWER on IntegriCloud