* 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 <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/zfs_fuid.h>
#include <sys/spa.h>
#include <sys/zil.h>
+#include <sys/zfs_vnops.h>
#include <sys/byteorder.h>
#include <sys/stat.h>
#include <sys/mode.h>
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
/*
* 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.
*/
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:
(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:
/*
* 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.
*/
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:
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:
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:
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;
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));
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));
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));
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)) {
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);
}
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));
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));
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;
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));
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);
zfs_replay_create_acl, /* TX_MKDIR_ACL_ATTR */
zfs_replay_write2, /* TX_WRITE2 */
};
+#endif /* HAVE_ZPL */