Create struct snapdata which contains the snapshot fields from cdev
and the previously malloc'ed snapshot lock. Malloc struct snapdata instead of just the lock. Replace snapshot fields in cdev with pointer to snapdata (saves 16 bytes). While here, give the private readblock() function a vnode argument in preparation for moving UFS to access GEOM directly.
This commit is contained in:
parent
883d3c0c07
commit
67673e6677
@ -293,7 +293,6 @@ allocdev(void)
|
||||
si->__si_namebuf[0] = '\0';
|
||||
si->si_name = si->__si_namebuf;
|
||||
LIST_INIT(&si->si_children);
|
||||
TAILQ_INIT(&si->si_snapshots);
|
||||
return (si);
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ struct tty;
|
||||
struct disk;
|
||||
struct vnode;
|
||||
struct buf;
|
||||
TAILQ_HEAD(snaphead, inode);
|
||||
struct snapdata;
|
||||
|
||||
struct cdev {
|
||||
u_int si_flags;
|
||||
@ -93,9 +93,7 @@ struct cdev {
|
||||
struct mount *__sid_mountpoint;
|
||||
int __sid_bsize_phys; /* min physical block size */
|
||||
int __sid_bsize_best; /* optimal block size */
|
||||
struct snaphead __sid_snapshots;
|
||||
daddr_t __sid_snaplistsize; /* size of snapblklist. */
|
||||
daddr_t *__sid_snapblklist; /* known snapshot blocks. */
|
||||
struct snapdata *__sid_snapdata;
|
||||
int (*__sid_copyonwrite)(struct vnode *, struct buf *);
|
||||
} __si_disk;
|
||||
} __si_u;
|
||||
@ -106,9 +104,7 @@ struct cdev {
|
||||
#define si_mountpoint __si_u.__si_disk.__sid_mountpoint
|
||||
#define si_bsize_phys __si_u.__si_disk.__sid_bsize_phys
|
||||
#define si_bsize_best __si_u.__si_disk.__sid_bsize_best
|
||||
#define si_snapshots __si_u.__si_disk.__sid_snapshots
|
||||
#define si_snaplistsize __si_u.__si_disk.__sid_snaplistsize
|
||||
#define si_snapblklist __si_u.__si_disk.__sid_snapblklist
|
||||
#define si_snapdata __si_u.__si_disk.__sid_snapdata
|
||||
#define si_copyonwrite __si_u.__si_disk.__sid_copyonwrite
|
||||
|
||||
/*
|
||||
|
@ -64,6 +64,15 @@ __FBSDID("$FreeBSD$");
|
||||
#define KERNCRED thread0.td_ucred
|
||||
#define DEBUG 1
|
||||
|
||||
TAILQ_HEAD(snaphead, inode);
|
||||
|
||||
struct snapdata {
|
||||
struct snaphead sn_head;
|
||||
daddr_t sn_listsize;
|
||||
daddr_t *sn_blklist;
|
||||
struct lock sn_lock;
|
||||
};
|
||||
|
||||
static int cgaccount(int, struct vnode *, struct buf *, int);
|
||||
static int expunge_ufs1(struct vnode *, struct inode *, struct fs *,
|
||||
int (*)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *, struct fs *,
|
||||
@ -92,7 +101,7 @@ static int snapacct_ufs2(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,
|
||||
static int mapacct_ufs2(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,
|
||||
struct fs *, ufs_lbn_t, int);
|
||||
static int ffs_copyonwrite(struct vnode *, struct buf *);
|
||||
static int readblock(struct buf *, ufs2_daddr_t);
|
||||
static int readblock(struct vnode *vp, struct buf *, ufs2_daddr_t);
|
||||
|
||||
/*
|
||||
* To ensure the consistency of snapshots across crashes, we must
|
||||
@ -131,7 +140,6 @@ ffs_snapshot(mp, snapfile)
|
||||
int32_t *lp;
|
||||
void *space;
|
||||
struct fs *copy_fs = NULL, *fs = VFSTOUFS(mp)->um_fs;
|
||||
struct snaphead *snaphead;
|
||||
struct thread *td = curthread;
|
||||
struct inode *ip, *xp;
|
||||
struct buf *bp, *nbp, *ibp, *sbp = NULL;
|
||||
@ -141,6 +149,12 @@ ffs_snapshot(mp, snapfile)
|
||||
struct vnode *vp, *xvp, *nvp, *devvp;
|
||||
struct uio auio;
|
||||
struct iovec aiov;
|
||||
struct snapdata *sn;
|
||||
|
||||
/*
|
||||
* XXX: make sure we don't go to out1 before we setup sn
|
||||
*/
|
||||
sn = (void *)0xdeadbeef;
|
||||
|
||||
/*
|
||||
* Need to serialize access to snapshot code per filesystem.
|
||||
@ -213,7 +227,7 @@ ffs_snapshot(mp, snapfile)
|
||||
ip->i_size = lblktosize(fs, (off_t)numblks);
|
||||
DIP_SET(ip, i_size, ip->i_size);
|
||||
ip->i_flag |= IN_CHANGE | IN_UPDATE;
|
||||
if ((error = readblock(bp, numblks - 1)) != 0)
|
||||
if ((error = readblock(vp, bp, numblks - 1)) != 0)
|
||||
goto out;
|
||||
bawrite(bp);
|
||||
/*
|
||||
@ -488,24 +502,22 @@ ffs_snapshot(mp, snapfile)
|
||||
* up our original private lock.
|
||||
*/
|
||||
VI_LOCK(devvp);
|
||||
snaphead = &devvp->v_rdev->si_snapshots;
|
||||
if ((xp = TAILQ_FIRST(snaphead)) != NULL) {
|
||||
struct lock *lkp;
|
||||
|
||||
lkp = ITOV(xp)->v_vnlock;
|
||||
sn = devvp->v_rdev->si_snapdata;
|
||||
if (sn != NULL) {
|
||||
xp = TAILQ_FIRST(&sn->sn_head);
|
||||
VI_UNLOCK(devvp);
|
||||
VI_LOCK(vp);
|
||||
vp->v_vnlock = lkp;
|
||||
vp->v_vnlock = &sn->sn_lock;
|
||||
} else {
|
||||
struct lock *lkp;
|
||||
|
||||
VI_UNLOCK(devvp);
|
||||
MALLOC(lkp, struct lock *, sizeof(struct lock), M_UFSMNT,
|
||||
M_WAITOK);
|
||||
lockinit(lkp, PVFS, "snaplk", VLKTIMEOUT,
|
||||
sn = malloc(sizeof *sn, M_UFSMNT, M_WAITOK | M_ZERO);
|
||||
TAILQ_INIT(&sn->sn_head);
|
||||
lockinit(&sn->sn_lock, PVFS, "snaplk", VLKTIMEOUT,
|
||||
LK_CANRECURSE | LK_NOPAUSE);
|
||||
VI_LOCK(vp);
|
||||
vp->v_vnlock = lkp;
|
||||
vp->v_vnlock = &sn->sn_lock;
|
||||
devvp->v_rdev->si_snapdata = sn;
|
||||
xp = NULL;
|
||||
}
|
||||
vn_lock(vp, LK_INTERLOCK | LK_EXCLUSIVE | LK_RETRY, td);
|
||||
transferlockers(&vp->v_lock, vp->v_vnlock);
|
||||
@ -534,10 +546,10 @@ ffs_snapshot(mp, snapfile)
|
||||
*blkp++ = fragstoblks(fs, cgtod(fs, cg));
|
||||
snapblklist[0] = blkp - snapblklist;
|
||||
VI_LOCK(devvp);
|
||||
if (devvp->v_rdev->si_snapblklist != NULL)
|
||||
if (sn->sn_blklist != NULL)
|
||||
panic("ffs_snapshot: non-empty list");
|
||||
devvp->v_rdev->si_snapblklist = snapblklist;
|
||||
devvp->v_rdev->si_snaplistsize = blkp - snapblklist;
|
||||
sn->sn_blklist = snapblklist;
|
||||
sn->sn_listsize = blkp - snapblklist;
|
||||
VI_UNLOCK(devvp);
|
||||
}
|
||||
/*
|
||||
@ -548,13 +560,14 @@ ffs_snapshot(mp, snapfile)
|
||||
fs->fs_snapinum[snaploc] = ip->i_number;
|
||||
if (ip->i_nextsnap.tqe_prev != 0)
|
||||
panic("ffs_snapshot: %d already on list", ip->i_number);
|
||||
TAILQ_INSERT_TAIL(snaphead, ip, i_nextsnap);
|
||||
TAILQ_INSERT_TAIL(&sn->sn_head, ip, i_nextsnap);
|
||||
devvp->v_rdev->si_copyonwrite = ffs_copyonwrite;
|
||||
devvp->v_vflag |= VV_COPYONWRITE;
|
||||
VI_UNLOCK(devvp);
|
||||
ASSERT_VOP_LOCKED(vp, "ffs_snapshot vp");
|
||||
vp->v_vflag |= VV_SYSTEM;
|
||||
out1:
|
||||
KASSERT(sn != (void *)0xdeadbeef, ("email phk@ and mckusick@"));
|
||||
/*
|
||||
* Resume operation on filesystem.
|
||||
*/
|
||||
@ -573,8 +586,7 @@ ffs_snapshot(mp, snapfile)
|
||||
* Copy allocation information from all the snapshots in
|
||||
* this snapshot and then expunge them from its view.
|
||||
*/
|
||||
snaphead = &devvp->v_rdev->si_snapshots;
|
||||
TAILQ_FOREACH(xp, snaphead, i_nextsnap) {
|
||||
TAILQ_FOREACH(xp, &sn->sn_head, i_nextsnap) {
|
||||
if (xp == ip)
|
||||
break;
|
||||
if (xp->i_ump->um_fstype == UFS1)
|
||||
@ -654,14 +666,14 @@ ffs_snapshot(mp, snapfile)
|
||||
* should replace the previous list.
|
||||
*/
|
||||
VI_LOCK(devvp);
|
||||
space = devvp->v_rdev->si_snapblklist;
|
||||
devvp->v_rdev->si_snapblklist = snapblklist;
|
||||
devvp->v_rdev->si_snaplistsize = snaplistsize;
|
||||
space = sn->sn_blklist;
|
||||
sn->sn_blklist = snapblklist;
|
||||
sn->sn_listsize = snaplistsize;
|
||||
VI_UNLOCK(devvp);
|
||||
if (space != NULL)
|
||||
FREE(space, M_UFSMNT);
|
||||
done:
|
||||
free(copy_fs->fs_csp, M_UFSMNT);
|
||||
FREE(copy_fs->fs_csp, M_UFSMNT);
|
||||
bawrite(sbp);
|
||||
out:
|
||||
if (saved_nice > 0) {
|
||||
@ -845,7 +857,7 @@ expunge_ufs1(snapvp, cancelip, fs, acctfunc, expungetype)
|
||||
fs->fs_bsize, KERNCRED, 0, &bp);
|
||||
if (error)
|
||||
return (error);
|
||||
if ((error = readblock(bp, lbn)) != 0)
|
||||
if ((error = readblock(snapvp, bp, lbn)) != 0)
|
||||
return (error);
|
||||
}
|
||||
/*
|
||||
@ -932,7 +944,7 @@ indiracct_ufs1(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks,
|
||||
bp = getblk(cancelvp, lbn, fs->fs_bsize, 0, 0, 0);
|
||||
bp->b_blkno = fsbtodb(fs, blkno);
|
||||
if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0 &&
|
||||
(error = readblock(bp, fragstoblks(fs, blkno)))) {
|
||||
(error = readblock(cancelvp, bp, fragstoblks(fs, blkno)))) {
|
||||
brelse(bp);
|
||||
return (error);
|
||||
}
|
||||
@ -1125,7 +1137,7 @@ expunge_ufs2(snapvp, cancelip, fs, acctfunc, expungetype)
|
||||
fs->fs_bsize, KERNCRED, 0, &bp);
|
||||
if (error)
|
||||
return (error);
|
||||
if ((error = readblock(bp, lbn)) != 0)
|
||||
if ((error = readblock(snapvp, bp, lbn)) != 0)
|
||||
return (error);
|
||||
}
|
||||
/*
|
||||
@ -1212,7 +1224,7 @@ indiracct_ufs2(snapvp, cancelvp, level, blkno, lbn, rlbn, remblks,
|
||||
bp = getblk(cancelvp, lbn, fs->fs_bsize, 0, 0, 0);
|
||||
bp->b_blkno = fsbtodb(fs, blkno);
|
||||
if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0 &&
|
||||
(error = readblock(bp, fragstoblks(fs, blkno)))) {
|
||||
(error = readblock(cancelvp, bp, fragstoblks(fs, blkno)))) {
|
||||
brelse(bp);
|
||||
return (error);
|
||||
}
|
||||
@ -1365,13 +1377,17 @@ ffs_snapgone(ip)
|
||||
struct inode *xp;
|
||||
struct fs *fs;
|
||||
int snaploc;
|
||||
struct snapdata *sn;
|
||||
|
||||
/*
|
||||
* Find snapshot in incore list.
|
||||
*/
|
||||
TAILQ_FOREACH(xp, &ip->i_devvp->v_rdev->si_snapshots, i_nextsnap)
|
||||
if (xp == ip)
|
||||
break;
|
||||
xp = NULL;
|
||||
sn = ip->i_devvp->v_rdev->si_snapdata;
|
||||
if (sn != NULL)
|
||||
TAILQ_FOREACH(xp, &sn->sn_head, i_nextsnap)
|
||||
if (xp == ip)
|
||||
break;
|
||||
if (xp != NULL)
|
||||
vrele(ITOV(ip));
|
||||
else if (snapdebug)
|
||||
@ -1409,10 +1425,12 @@ ffs_snapremove(vp)
|
||||
struct thread *td = curthread;
|
||||
ufs2_daddr_t numblks, blkno, dblk, *snapblklist;
|
||||
int error, loc, last;
|
||||
struct snapdata *sn;
|
||||
|
||||
ip = VTOI(vp);
|
||||
fs = ip->i_fs;
|
||||
devvp = ip->i_devvp;
|
||||
sn = devvp->v_rdev->si_snapdata;
|
||||
/*
|
||||
* If active, delete from incore list (this snapshot may
|
||||
* already have been in the process of being deleted, so
|
||||
@ -1425,23 +1443,24 @@ ffs_snapremove(vp)
|
||||
lockmgr(&vp->v_lock, LK_INTERLOCK | LK_EXCLUSIVE,
|
||||
VI_MTX(devvp), td);
|
||||
VI_LOCK(devvp);
|
||||
TAILQ_REMOVE(&devvp->v_rdev->si_snapshots, ip, i_nextsnap);
|
||||
TAILQ_REMOVE(&sn->sn_head, ip, i_nextsnap);
|
||||
ip->i_nextsnap.tqe_prev = 0;
|
||||
lkp = vp->v_vnlock;
|
||||
vp->v_vnlock = &vp->v_lock;
|
||||
lockmgr(lkp, LK_RELEASE, NULL, td);
|
||||
if (TAILQ_FIRST(&devvp->v_rdev->si_snapshots) != 0) {
|
||||
if (TAILQ_FIRST(&sn->sn_head) != 0) {
|
||||
VI_UNLOCK(devvp);
|
||||
} else {
|
||||
snapblklist = devvp->v_rdev->si_snapblklist;
|
||||
devvp->v_rdev->si_snapblklist = 0;
|
||||
devvp->v_rdev->si_snaplistsize = 0;
|
||||
devvp->v_rdev->si_copyonwrite = 0;
|
||||
snapblklist = sn->sn_blklist;
|
||||
sn->sn_blklist = 0;
|
||||
sn->sn_listsize = 0;
|
||||
devvp->v_rdev->si_snapdata = NULL;
|
||||
devvp->v_vflag &= ~VV_COPYONWRITE;
|
||||
lockmgr(lkp, LK_DRAIN|LK_INTERLOCK, VI_MTX(devvp), td);
|
||||
lockmgr(lkp, LK_RELEASE, NULL, td);
|
||||
lockdestroy(lkp);
|
||||
FREE(lkp, M_UFSMNT);
|
||||
free(sn, M_UFSMNT);
|
||||
FREE(snapblklist, M_UFSMNT);
|
||||
}
|
||||
}
|
||||
@ -1538,13 +1557,13 @@ ffs_snapblkfree(fs, devvp, bno, size, inum)
|
||||
ufs_lbn_t lbn;
|
||||
ufs2_daddr_t blkno;
|
||||
int indiroff = 0, snapshot_locked = 0, error = 0, claimedblk = 0;
|
||||
struct snaphead *snaphead;
|
||||
struct snapdata *sn;
|
||||
|
||||
lbn = fragstoblks(fs, bno);
|
||||
retry:
|
||||
VI_LOCK(devvp);
|
||||
snaphead = &devvp->v_rdev->si_snapshots;
|
||||
TAILQ_FOREACH(ip, snaphead, i_nextsnap) {
|
||||
sn = devvp->v_rdev->si_snapdata;
|
||||
TAILQ_FOREACH(ip, &sn->sn_head, i_nextsnap) {
|
||||
vp = ITOV(ip);
|
||||
/*
|
||||
* Lookup block being written.
|
||||
@ -1695,7 +1714,7 @@ ffs_snapblkfree(fs, devvp, bno, size, inum)
|
||||
/*
|
||||
* Otherwise, read the old block contents into the buffer.
|
||||
*/
|
||||
if ((error = readblock(cbp, lbn)) != 0) {
|
||||
if ((error = readblock(vp, cbp, lbn)) != 0) {
|
||||
bzero(cbp->b_data, fs->fs_bsize);
|
||||
bawrite(cbp);
|
||||
if (dopersistence && ip->i_effnlink > 0)
|
||||
@ -1739,7 +1758,7 @@ ffs_snapshot_mount(mp)
|
||||
struct vnode *devvp = ump->um_devvp;
|
||||
struct fs *fs = ump->um_fs;
|
||||
struct thread *td = curthread;
|
||||
struct snaphead *snaphead;
|
||||
struct snapdata *sn;
|
||||
struct vnode *vp;
|
||||
struct inode *ip, *xp;
|
||||
struct uio auio;
|
||||
@ -1758,7 +1777,7 @@ ffs_snapshot_mount(mp)
|
||||
* Process each snapshot listed in the superblock.
|
||||
*/
|
||||
vp = NULL;
|
||||
snaphead = &devvp->v_rdev->si_snapshots;
|
||||
sn = devvp->v_rdev->si_snapdata;
|
||||
for (snaploc = 0; snaploc < FSMAXSNAP; snaploc++) {
|
||||
if (fs->fs_snapinum[snaploc] == 0)
|
||||
break;
|
||||
@ -1798,7 +1817,7 @@ ffs_snapshot_mount(mp)
|
||||
* lock and give up our original private lock.
|
||||
*/
|
||||
VI_LOCK(devvp);
|
||||
if ((xp = TAILQ_FIRST(snaphead)) != NULL) {
|
||||
if ((xp = TAILQ_FIRST(&sn->sn_head)) != NULL) {
|
||||
struct lock *lkp;
|
||||
|
||||
lkp = ITOV(xp)->v_vnlock;
|
||||
@ -1827,7 +1846,7 @@ ffs_snapshot_mount(mp)
|
||||
panic("ffs_snapshot_mount: %d already on list",
|
||||
ip->i_number);
|
||||
else
|
||||
TAILQ_INSERT_TAIL(snaphead, ip, i_nextsnap);
|
||||
TAILQ_INSERT_TAIL(&sn->sn_head, ip, i_nextsnap);
|
||||
vp->v_vflag |= VV_SYSTEM;
|
||||
VI_UNLOCK(devvp);
|
||||
VOP_UNLOCK(vp, 0, td);
|
||||
@ -1873,9 +1892,9 @@ ffs_snapshot_mount(mp)
|
||||
VOP_UNLOCK(vp, 0, td);
|
||||
VI_LOCK(devvp);
|
||||
ASSERT_VOP_LOCKED(devvp, "ffs_snapshot_mount");
|
||||
devvp->v_rdev->si_snaplistsize = snaplistsize;
|
||||
devvp->v_rdev->si_snapblklist = (daddr_t *)snapblklist;
|
||||
devvp->v_rdev->si_copyonwrite = ffs_copyonwrite;
|
||||
sn->sn_listsize = snaplistsize;
|
||||
sn->sn_blklist = (daddr_t *)snapblklist;
|
||||
devvp->v_vflag |= VV_COPYONWRITE;
|
||||
VI_UNLOCK(devvp);
|
||||
}
|
||||
@ -1888,17 +1907,16 @@ ffs_snapshot_unmount(mp)
|
||||
struct mount *mp;
|
||||
{
|
||||
struct vnode *devvp = VFSTOUFS(mp)->um_devvp;
|
||||
struct snaphead *snaphead = &devvp->v_rdev->si_snapshots;
|
||||
struct lock *lkp = NULL;
|
||||
struct snapdata *sn;
|
||||
struct inode *xp;
|
||||
struct vnode *vp;
|
||||
|
||||
sn = devvp->v_rdev->si_snapdata;
|
||||
VI_LOCK(devvp);
|
||||
while ((xp = TAILQ_FIRST(snaphead)) != 0) {
|
||||
while ((xp = TAILQ_FIRST(&sn->sn_head)) != 0) {
|
||||
vp = ITOV(xp);
|
||||
lkp = vp->v_vnlock;
|
||||
vp->v_vnlock = &vp->v_lock;
|
||||
TAILQ_REMOVE(snaphead, xp, i_nextsnap);
|
||||
TAILQ_REMOVE(&sn->sn_head, xp, i_nextsnap);
|
||||
xp->i_nextsnap.tqe_prev = 0;
|
||||
if (xp->i_effnlink > 0) {
|
||||
VI_UNLOCK(devvp);
|
||||
@ -1906,17 +1924,16 @@ ffs_snapshot_unmount(mp)
|
||||
VI_LOCK(devvp);
|
||||
}
|
||||
}
|
||||
if (devvp->v_rdev->si_snapblklist != NULL) {
|
||||
FREE(devvp->v_rdev->si_snapblklist, M_UFSMNT);
|
||||
devvp->v_rdev->si_snapblklist = NULL;
|
||||
devvp->v_rdev->si_snaplistsize = 0;
|
||||
}
|
||||
if (lkp != NULL) {
|
||||
lockdestroy(lkp);
|
||||
FREE(lkp, M_UFSMNT);
|
||||
if (sn->sn_blklist != NULL) {
|
||||
FREE(sn->sn_blklist, M_UFSMNT);
|
||||
sn->sn_blklist = NULL;
|
||||
sn->sn_listsize = 0;
|
||||
}
|
||||
lockdestroy(&sn->sn_lock);
|
||||
free(sn, M_UFSMNT);
|
||||
ASSERT_VOP_LOCKED(devvp, "ffs_snapshot_unmount");
|
||||
devvp->v_rdev->si_copyonwrite = 0;
|
||||
devvp->v_rdev->si_snapdata = NULL;
|
||||
devvp->v_vflag &= ~VV_COPYONWRITE;
|
||||
VI_UNLOCK(devvp);
|
||||
}
|
||||
@ -1930,7 +1947,7 @@ ffs_copyonwrite(devvp, bp)
|
||||
struct vnode *devvp;
|
||||
struct buf *bp;
|
||||
{
|
||||
struct snaphead *snaphead;
|
||||
struct snapdata *sn;
|
||||
struct buf *ibp, *cbp, *savedcbp = 0;
|
||||
struct thread *td = curthread;
|
||||
struct fs *fs;
|
||||
@ -1946,12 +1963,12 @@ ffs_copyonwrite(devvp, bp)
|
||||
* By doing this check we avoid several potential deadlocks.
|
||||
*/
|
||||
VI_LOCK(devvp);
|
||||
snaphead = &devvp->v_rdev->si_snapshots;
|
||||
ip = TAILQ_FIRST(snaphead);
|
||||
sn = devvp->v_rdev->si_snapdata;
|
||||
ip = TAILQ_FIRST(&sn->sn_head);
|
||||
fs = ip->i_fs;
|
||||
lbn = fragstoblks(fs, dbtofsb(fs, bp->b_blkno));
|
||||
snapblklist = devvp->v_rdev->si_snapblklist;
|
||||
upper = devvp->v_rdev->si_snaplistsize - 1;
|
||||
snapblklist = sn->sn_blklist;
|
||||
upper = sn->sn_listsize - 1;
|
||||
lower = 1;
|
||||
while (lower <= upper) {
|
||||
mid = (lower + upper) / 2;
|
||||
@ -1970,7 +1987,7 @@ ffs_copyonwrite(devvp, bp)
|
||||
* Not in the precomputed list, so check the snapshots.
|
||||
*/
|
||||
retry:
|
||||
TAILQ_FOREACH(ip, snaphead, i_nextsnap) {
|
||||
TAILQ_FOREACH(ip, &sn->sn_head, i_nextsnap) {
|
||||
vp = ITOV(ip);
|
||||
/*
|
||||
* We ensure that everything of our own that needs to be
|
||||
@ -2069,7 +2086,7 @@ ffs_copyonwrite(devvp, bp)
|
||||
/*
|
||||
* Otherwise, read the old block contents into the buffer.
|
||||
*/
|
||||
if ((error = readblock(cbp, lbn)) != 0) {
|
||||
if ((error = readblock(vp, cbp, lbn)) != 0) {
|
||||
bzero(cbp->b_data, fs->fs_bsize);
|
||||
bawrite(cbp);
|
||||
if (dopersistence && ip->i_effnlink > 0)
|
||||
@ -2101,14 +2118,15 @@ ffs_copyonwrite(devvp, bp)
|
||||
* Much of this boiler-plate comes from bwrite().
|
||||
*/
|
||||
static int
|
||||
readblock(bp, lbn)
|
||||
readblock(vp, bp, lbn)
|
||||
struct vnode *vp;
|
||||
struct buf *bp;
|
||||
ufs2_daddr_t lbn;
|
||||
{
|
||||
struct uio auio;
|
||||
struct iovec aiov;
|
||||
struct thread *td = curthread;
|
||||
struct inode *ip = VTOI(bp->b_vp);
|
||||
struct inode *ip = VTOI(vp);
|
||||
|
||||
aiov.iov_base = bp->b_data;
|
||||
aiov.iov_len = bp->b_bcount;
|
||||
|
Loading…
Reference in New Issue
Block a user