Changeset View
Standalone View
sys/ufs/ffs/ffs_snapshot.c
Show First 20 Lines • Show All 295 Lines • ▼ Show 20 Lines | if (vn_start_write(NULL, &wrtmp, V_NOWAIT) != 0) { | ||||
goto restart; | goto restart; | ||||
} | } | ||||
error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vat); | error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vat); | ||||
VOP_UNLOCK(nd.ni_dvp); | VOP_UNLOCK(nd.ni_dvp); | ||||
if (error) { | if (error) { | ||||
NDFREE(&nd, NDF_ONLY_PNBUF); | NDFREE(&nd, NDF_ONLY_PNBUF); | ||||
vn_finished_write(wrtmp); | vn_finished_write(wrtmp); | ||||
vrele(nd.ni_dvp); | vrele(nd.ni_dvp); | ||||
if (error == ERELOOKUP) | |||||
goto restart; | |||||
return (error); | return (error); | ||||
} | } | ||||
vp = nd.ni_vp; | vp = nd.ni_vp; | ||||
vnode_create_vobject(nd.ni_vp, fs->fs_size, td); | vnode_create_vobject(nd.ni_vp, fs->fs_size, td); | ||||
vp->v_vflag |= VV_SYSTEM; | vp->v_vflag |= VV_SYSTEM; | ||||
ip = VTOI(vp); | ip = VTOI(vp); | ||||
devvp = ITODEVVP(ip); | devvp = ITODEVVP(ip); | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | restart: | ||||
* Allocate all cylinder group blocks. | * Allocate all cylinder group blocks. | ||||
*/ | */ | ||||
for (cg = 0; cg < fs->fs_ncg; cg++) { | for (cg = 0; cg < fs->fs_ncg; cg++) { | ||||
error = UFS_BALLOC(vp, lfragtosize(fs, cgtod(fs, cg)), | error = UFS_BALLOC(vp, lfragtosize(fs, cgtod(fs, cg)), | ||||
fs->fs_bsize, KERNCRED, 0, &nbp); | fs->fs_bsize, KERNCRED, 0, &nbp); | ||||
if (error) | if (error) | ||||
goto out; | goto out; | ||||
bawrite(nbp); | bawrite(nbp); | ||||
if (cg % 10 == 0) | if (cg % 10 == 0) { | ||||
ffs_syncvnode(vp, MNT_WAIT, 0); | error = ffs_syncvnode(vp, MNT_WAIT, 0); | ||||
mckusick: Unrelated to this patch, but the third argument should be DATA_ONLY.
The point here is to flush… | |||||
/* vp possibly reclaimed if unlocked */ | |||||
if (error != 0) | |||||
goto out; | |||||
} | } | ||||
} | |||||
/* | /* | ||||
* Copy all the cylinder group maps. Although the | * Copy all the cylinder group maps. Although the | ||||
* filesystem is still active, we hope that only a few | * filesystem is still active, we hope that only a few | ||||
* cylinder groups will change between now and when we | * cylinder groups will change between now and when we | ||||
* suspend operations. Thus, we will be able to quickly | * suspend operations. Thus, we will be able to quickly | ||||
* touch up the few cylinder groups that changed during | * touch up the few cylinder groups that changed during | ||||
* the suspension period. | * the suspension period. | ||||
*/ | */ | ||||
len = howmany(fs->fs_ncg, NBBY); | len = howmany(fs->fs_ncg, NBBY); | ||||
space = malloc(len, M_DEVBUF, M_WAITOK|M_ZERO); | space = malloc(len, M_DEVBUF, M_WAITOK|M_ZERO); | ||||
UFS_LOCK(ump); | UFS_LOCK(ump); | ||||
fs->fs_active = space; | fs->fs_active = space; | ||||
UFS_UNLOCK(ump); | UFS_UNLOCK(ump); | ||||
for (cg = 0; cg < fs->fs_ncg; cg++) { | for (cg = 0; cg < fs->fs_ncg; cg++) { | ||||
error = UFS_BALLOC(vp, lfragtosize(fs, cgtod(fs, cg)), | error = UFS_BALLOC(vp, lfragtosize(fs, cgtod(fs, cg)), | ||||
fs->fs_bsize, KERNCRED, 0, &nbp); | fs->fs_bsize, KERNCRED, 0, &nbp); | ||||
if (error) | if (error) | ||||
goto out; | goto out; | ||||
error = cgaccount(cg, vp, nbp, 1); | error = cgaccount(cg, vp, nbp, 1); | ||||
bawrite(nbp); | bawrite(nbp); | ||||
if (cg % 10 == 0) | if (cg % 10 == 0 && error == 0) | ||||
ffs_syncvnode(vp, MNT_WAIT, 0); | error = ffs_syncvnode(vp, MNT_WAIT, 0); | ||||
Done Inline ActionsIs this a logically unrelated change? markj: Is this a logically unrelated change? | |||||
Done Inline ActionsIt is related, there is no point of hiding error from cgaccount() by an error from ffs_syncvnode(), but also we do not want to ignore ffs_syncvnode() error. kib: It is related, there is no point of hiding error from cgaccount() by an error from… | |||||
Done Inline ActionsI mean, before we'd call ffs_syncvnode() even if cgaccount() returned an error. I can't tell if it is intentional or not. markj: I mean, before we'd call ffs_syncvnode() even if cgaccount() returned an error. I can't tell if… | |||||
Done Inline ActionsIt is safe to call ffs_syncvnode() in the sense that it would not destroy any state. What I wanted to avoid is to obliterate error from cgaccount(). If we get an error for any reason, the snapshot creation is aborted and the vnode is vput(). Syncing it before the abort is mostly a nop from the functional PoV. kib: It is safe to call ffs_syncvnode() in the sense that it would not destroy any state. What I… | |||||
Done Inline ActionsUnrelated to this patch, but the third argument should be DATA_ONLY. mckusick: Unrelated to this patch, but the third argument should be DATA_ONLY.
The point here is to flush… | |||||
if (error) | if (error) | ||||
goto out; | goto out; | ||||
} | } | ||||
/* | /* | ||||
* Change inode to snapshot type file. | * Change inode to snapshot type file. | ||||
*/ | */ | ||||
ip->i_flags |= SF_SNAPSHOT; | ip->i_flags |= SF_SNAPSHOT; | ||||
DIP_SET(ip, i_flags, ip->i_flags); | DIP_SET(ip, i_flags, ip->i_flags); | ||||
▲ Show 20 Lines • Show All 2,317 Lines • Show Last 20 Lines |
Unrelated to this patch, but the third argument should be DATA_ONLY.
The point here is to flush dirty data, not to get it coherent on disk (that happens below).
Indeed we are doing unnecessary extra writes because we are flushing an indirect block that we are still filling with block pointers.