diff --git a/module/zfs/zfs_sa.c b/module/zfs/zfs_sa.c index 7d9970cb8..6eb7e0999 100644 --- a/module/zfs/zfs_sa.c +++ b/module/zfs/zfs_sa.c @@ -248,8 +248,17 @@ zfs_sa_set_xattr(znode_t *zp) if (error) { dmu_tx_abort(tx); } else { - VERIFY0(sa_update(zp->z_sa_hdl, SA_ZPL_DXATTR(zfsvfs), - obj, size, tx)); + int count = 0; + sa_bulk_attr_t bulk[2]; + uint64_t ctime[2]; + + zfs_tstamp_update_setup(zp, STATE_CHANGED, NULL, ctime); + SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_DXATTR(zfsvfs), + NULL, obj, size); + SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), + NULL, &ctime, 16); + VERIFY0(sa_bulk_update(zp->z_sa_hdl, bulk, count, tx)); + dmu_tx_commit(tx); } out_free: diff --git a/module/zfs/zpl_xattr.c b/module/zfs/zpl_xattr.c index d3bb4bbf8..0c626b122 100644 --- a/module/zfs/zpl_xattr.c +++ b/module/zfs/zpl_xattr.c @@ -495,6 +495,12 @@ zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value, error = wrote; out: + + if (error == 0) { + ip->i_ctime = current_time(ip); + zfs_mark_inode_dirty(ip); + } + if (vap) kmem_free(vap, sizeof (vattr_t)); diff --git a/tests/zfs-tests/tests/functional/ctime/Makefile.am b/tests/zfs-tests/tests/functional/ctime/Makefile.am index 1c7c26d99..e7479ae81 100644 --- a/tests/zfs-tests/tests/functional/ctime/Makefile.am +++ b/tests/zfs-tests/tests/functional/ctime/Makefile.am @@ -3,10 +3,11 @@ include $(top_srcdir)/config/Rules.am pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/ctime dist_pkgdata_SCRIPTS = \ + ctime_001_pos.ksh \ cleanup.ksh \ setup.ksh pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/ctime -pkgexec_PROGRAMS = ctime_001_pos -ctime_001_pos_SOURCES = ctime_001_pos.c +pkgexec_PROGRAMS = ctime +ctime_SOURCES = ctime.c diff --git a/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.c b/tests/zfs-tests/tests/functional/ctime/ctime.c similarity index 94% rename from tests/zfs-tests/tests/functional/ctime/ctime_001_pos.c rename to tests/zfs-tests/tests/functional/ctime/ctime.c index 73528d21d..ba8af15fe 100644 --- a/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.c +++ b/tests/zfs-tests/tests/functional/ctime/ctime.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -250,6 +251,24 @@ do_chown(const char *pfile) return (ret); } +static int +do_xattr(const char *pfile) +{ + int ret = 0; + char *value = "user.value"; + + if (pfile == NULL) { + return (-1); + } + + if (setxattr(pfile, "user.x", value, strlen(value), 0) == -1) { + (void) fprintf(stderr, "setxattr(%s, %d, %d) failed with errno " + "%d\n", pfile, (int)getuid(), (int)getgid(), errno); + return (1); + } + return (ret); +} + static void cleanup(void) { @@ -270,6 +289,7 @@ static timetest_t timetest_table[] = { { ST_CTIME, "st_ctime", do_chown }, { ST_CTIME, "st_ctime", do_link }, { ST_CTIME, "st_ctime", do_utime }, + { ST_CTIME, "st_ctime", do_xattr }, }; #define NCOMMAND (sizeof (timetest_table) / sizeof (timetest_table[0])) @@ -281,7 +301,6 @@ main(int argc, char *argv[]) int i, ret, fd; char *penv[] = {"TESTDIR", "TESTFILE0"}; - (void) fprintf(stdout, "Verify [acm]time is modified appropriately.\n"); (void) atexit(cleanup); /* @@ -347,6 +366,5 @@ main(int argc, char *argv[]) } } - (void) fprintf(stdout, "PASS\n"); return (0); } diff --git a/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.ksh b/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.ksh new file mode 100644 index 000000000..de12efe46 --- /dev/null +++ b/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.ksh @@ -0,0 +1,44 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +. $STF_SUITE/include/libtest.shlib +# . $STF_SUITE/tests/functional/xattr/xattr_common.kshlib + +# +# DESCRIPTION: +# +# Verify [acm]time is modified appropriately with xattr=on|sa + +set -A args "sa" "on" + +log_note "Verify [acm]time is modified appropriately." + +for arg in ${args[*]}; do + log_note "Testing with xattr set to $arg" + log_must zfs set xattr=$arg $TESTPOOL + log_must $STF_SUITE/tests/functional/ctime/ctime +done + +log_pass "PASS"