X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Fzfs_replay.c;h=2c258948b3fdf7ec00d8c9368f53cdd558266f8e;hb=a405c8a665bf7d96880c97bcb783cf84d04e3e76;hp=f26009b02c59bad32d324663d5f9705a63f889cf;hpb=428870ff734fdaccc342b33fc53cf94724409a46;p=zfs.git diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c index f26009b..2c25894 100644 --- a/module/zfs/zfs_replay.c +++ b/module/zfs/zfs_replay.c @@ -19,10 +19,11 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ +#ifdef HAVE_ZPL + #include #include #include @@ -40,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -129,6 +131,10 @@ zfs_replay_xvattr(lr_attr_t *lrattr, xvattr_t *xvap) bcopy(scanstamp, xoap->xoa_av_scanstamp, AV_SCANSTAMP_SZ); if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) xoap->xoa_reparse = ((*attrs & XAT0_REPARSE) != 0); + if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) + xoap->xoa_offline = ((*attrs & XAT0_OFFLINE) != 0); + if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) + xoap->xoa_sparse = ((*attrs & XAT0_SPARSE) != 0); } static int @@ -305,7 +311,7 @@ zfs_replay_create_acl(zfsvfs_t *zfsvfs, /* * All forms of zfs create (create, mkdir, mkxattrdir, symlink) * eventually end up in zfs_mknode(), which assigns the object's - * creation time and generation number. The generic VOP_CREATE() + * creation time and generation number. The generic zfs_create() * doesn't have either concept, so we smuggle the values inside * the vattr's otherwise unused va_ctime and va_nblocks fields. */ @@ -348,7 +354,7 @@ zfs_replay_create_acl(zfsvfs_t *zfsvfs, lr->lr_uid, lr->lr_gid); } - error = VOP_CREATE(ZTOV(dzp), name, &xva.xva_vattr, + error = zfs_create(ZTOV(dzp), name, &xva.xva_vattr, 0, 0, &vp, kcred, vflg, NULL, &vsec); break; case TX_MKDIR_ACL: @@ -378,7 +384,7 @@ zfs_replay_create_acl(zfsvfs_t *zfsvfs, (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, lr->lr_uid, lr->lr_gid); } - error = VOP_MKDIR(ZTOV(dzp), name, &xva.xva_vattr, + error = zfs_mkdir(ZTOV(dzp), name, &xva.xva_vattr, &vp, kcred, NULL, vflg, &vsec); break; default: @@ -432,7 +438,7 @@ zfs_replay_create(zfsvfs_t *zfsvfs, lr_create_t *lr, boolean_t byteswap) /* * All forms of zfs create (create, mkdir, mkxattrdir, symlink) * eventually end up in zfs_mknode(), which assigns the object's - * creation time and generation number. The generic VOP_CREATE() + * creation time and generation number. The generic zfs_create() * doesn't have either concept, so we smuggle the values inside * the vattr's otherwise unused va_ctime and va_nblocks fields. */ @@ -477,7 +483,7 @@ zfs_replay_create(zfsvfs_t *zfsvfs, lr_create_t *lr, boolean_t byteswap) if (name == NULL) name = (char *)start; - error = VOP_CREATE(ZTOV(dzp), name, &xva.xva_vattr, + error = zfs_create(ZTOV(dzp), name, &xva.xva_vattr, 0, 0, &vp, kcred, vflg, NULL, NULL); break; case TX_MKDIR_ATTR: @@ -495,7 +501,7 @@ zfs_replay_create(zfsvfs_t *zfsvfs, lr_create_t *lr, boolean_t byteswap) if (name == NULL) name = (char *)(lr + 1); - error = VOP_MKDIR(ZTOV(dzp), name, &xva.xva_vattr, + error = zfs_mkdir(ZTOV(dzp), name, &xva.xva_vattr, &vp, kcred, NULL, vflg, NULL); break; case TX_MKXATTR: @@ -504,7 +510,7 @@ zfs_replay_create(zfsvfs_t *zfsvfs, lr_create_t *lr, boolean_t byteswap) case TX_SYMLINK: name = (char *)(lr + 1); link = name + strlen(name) + 1; - error = VOP_SYMLINK(ZTOV(dzp), name, &xva.xva_vattr, + error = zfs_symlink(ZTOV(dzp), name, &xva.xva_vattr, link, kcred, NULL, vflg); break; default: @@ -542,10 +548,10 @@ zfs_replay_remove(zfsvfs_t *zfsvfs, lr_remove_t *lr, boolean_t byteswap) switch ((int)lr->lr_common.lrc_txtype) { case TX_REMOVE: - error = VOP_REMOVE(ZTOV(dzp), name, kcred, NULL, vflg); + error = zfs_remove(ZTOV(dzp), name, kcred, NULL, vflg); break; case TX_RMDIR: - error = VOP_RMDIR(ZTOV(dzp), name, NULL, kcred, NULL, vflg); + error = zfs_rmdir(ZTOV(dzp), name, NULL, kcred, NULL, vflg); break; default: error = ENOTSUP; @@ -578,7 +584,7 @@ zfs_replay_link(zfsvfs_t *zfsvfs, lr_link_t *lr, boolean_t byteswap) if (lr->lr_common.lrc_txtype & TX_CI) vflg |= FIGNORECASE; - error = VOP_LINK(ZTOV(dzp), ZTOV(zp), name, kcred, NULL, vflg); + error = zfs_link(ZTOV(dzp), ZTOV(zp), name, kcred, NULL, vflg); VN_RELE(ZTOV(zp)); VN_RELE(ZTOV(dzp)); @@ -609,7 +615,7 @@ zfs_replay_rename(zfsvfs_t *zfsvfs, lr_rename_t *lr, boolean_t byteswap) if (lr->lr_common.lrc_txtype & TX_CI) vflg |= FIGNORECASE; - error = VOP_RENAME(ZTOV(sdzp), sname, ZTOV(tdzp), tname, kcred, + error = zfs_rename(ZTOV(sdzp), sname, ZTOV(tdzp), tname, kcred, NULL, vflg); VN_RELE(ZTOV(tdzp)); @@ -625,7 +631,7 @@ zfs_replay_write(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap) znode_t *zp; int error; ssize_t resid; - uint64_t orig_eof, eod, offset, length; + uint64_t eod, offset, length; if (byteswap) byteswap_uint64_array(lr, sizeof (*lr)); @@ -643,9 +649,20 @@ zfs_replay_write(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap) offset = lr->lr_offset; length = lr->lr_length; - eod = offset + length; /* end of data for this write */ + eod = offset + length; /* end of data for this write */ - orig_eof = zp->z_size; + /* + * This may be a write from a dmu_sync() for a whole block, + * and may extend beyond the current end of the file. + * We can't just replay what was written for this TX_WRITE as + * a future TX_WRITE2 may extend the eof and the data for that + * write needs to be there. So we write the whole block and + * reduce the eof. This needs to be done within the single dmu + * transaction created within vn_rdwr -> zfs_write. So a possible + * new end of file is passed through in zfsvfs->z_replay_eof + */ + + zfsvfs->z_replay_eof = 0; /* 0 means don't change end of file */ /* If it's a dmu_sync() block, write the whole block */ if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) { @@ -654,23 +671,15 @@ zfs_replay_write(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap) offset -= offset % blocksize; length = blocksize; } + if (zp->z_size < eod) + zfsvfs->z_replay_eof = eod; } error = vn_rdwr(UIO_WRITE, ZTOV(zp), data, length, offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid); - /* - * This may be a write from a dmu_sync() for a whole block, - * and may extend beyond the current end of the file. - * We can't just replay what was written for this TX_WRITE as - * a future TX_WRITE2 may extend the eof and the data for that - * write needs to be there. So we write the whole block and - * reduce the eof. - */ - if (orig_eof < zp->z_size) /* file length grew ? */ - zp->z_size = eod; - VN_RELE(ZTOV(zp)); + zfsvfs->z_replay_eof = 0; /* safety */ return (error); } @@ -694,10 +703,31 @@ zfs_replay_write2(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap) if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) return (error); +top: end = lr->lr_offset + lr->lr_length; if (end > zp->z_size) { - ASSERT3U(end - zp->z_size, <, zp->z_blksz); + dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os); + zp->z_size = end; + dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); + error = dmu_tx_assign(tx, TXG_WAIT); + if (error) { + VN_RELE(ZTOV(zp)); + if (error == ERESTART) { + dmu_tx_wait(tx); + dmu_tx_abort(tx); + goto top; + } + dmu_tx_abort(tx); + return (error); + } + (void) sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zfsvfs), + (void *)&zp->z_size, sizeof (uint64_t), tx); + + /* Ensure the replayed seq is updated */ + (void) zil_replaying(zfsvfs->z_log, tx); + + dmu_tx_commit(tx); } VN_RELE(ZTOV(zp)); @@ -724,7 +754,7 @@ zfs_replay_truncate(zfsvfs_t *zfsvfs, lr_truncate_t *lr, boolean_t byteswap) fl.l_start = lr->lr_offset; fl.l_len = lr->lr_length; - error = VOP_SPACE(ZTOV(zp), F_FREESP, &fl, FWRITE | FOFFMAX, + error = zfs_space(ZTOV(zp), F_FREESP, &fl, FWRITE | FOFFMAX, lr->lr_offset, kcred, NULL); VN_RELE(ZTOV(zp)); @@ -775,7 +805,7 @@ zfs_replay_setattr(zfsvfs_t *zfsvfs, lr_setattr_t *lr, boolean_t byteswap) zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, lr->lr_uid, lr->lr_gid); - error = VOP_SETATTR(ZTOV(zp), vap, 0, kcred, NULL); + error = zfs_setattr(ZTOV(zp), vap, 0, kcred, NULL); zfs_fuid_info_free(zfsvfs->z_fuid_replay); zfsvfs->z_fuid_replay = NULL; @@ -807,7 +837,7 @@ zfs_replay_acl_v0(zfsvfs_t *zfsvfs, lr_acl_v0_t *lr, boolean_t byteswap) vsa.vsa_aclflags = 0; vsa.vsa_aclentp = ace; - error = VOP_SETSECATTR(ZTOV(zp), &vsa, 0, kcred, NULL); + error = zfs_setsecattr(ZTOV(zp), &vsa, 0, kcred, NULL); VN_RELE(ZTOV(zp)); @@ -865,7 +895,7 @@ zfs_replay_acl(zfsvfs_t *zfsvfs, lr_acl_t *lr, boolean_t byteswap) lr->lr_fuidcnt, lr->lr_domcnt, 0, 0); } - error = VOP_SETSECATTR(ZTOV(zp), &vsa, 0, kcred, NULL); + error = zfs_setsecattr(ZTOV(zp), &vsa, 0, kcred, NULL); if (zfsvfs->z_fuid_replay) zfs_fuid_info_free(zfsvfs->z_fuid_replay); @@ -902,3 +932,4 @@ zil_replay_func_t *zfs_replay_vector[TX_MAX_TYPE] = { zfs_replay_create_acl, /* TX_MKDIR_ACL_ATTR */ zfs_replay_write2, /* TX_WRITE2 */ }; +#endif /* HAVE_ZPL */