From aa7a680a4097933eaabe95c7753ca80d6a2158d4 Mon Sep 17 00:00:00 2001 From: Olga Kornievskaia Date: Wed, 8 Feb 2012 16:29:25 -0500 Subject: [PATCH] propagating file change attr on writes --- daemon/nfs41_ops.c | 39 +++++++++++++++++++++++---------------- daemon/nfs41_ops.h | 9 ++++++--- daemon/pnfs.h | 3 ++- daemon/pnfs_io.c | 20 +++++++++++--------- daemon/readwrite.c | 17 +++++++++++++---- daemon/setattr.c | 3 ++- daemon/upcall.h | 1 + sys/nfs41_driver.c | 6 +++++- 8 files changed, 63 insertions(+), 35 deletions(-) diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c index 2141564..268ef4d 100644 --- a/daemon/nfs41_ops.c +++ b/daemon/nfs41_ops.c @@ -700,7 +700,8 @@ int nfs41_write( IN uint64_t offset, IN enum stable_how4 stable, OUT uint32_t *bytes_written, - OUT nfs41_write_verf *verf) + OUT nfs41_write_verf *verf, + OUT nfs41_file_info *cinfo) { int status; nfs41_compound compound; @@ -715,7 +716,7 @@ int nfs41_write( nfs41_getattr_args getattr_args; nfs41_getattr_res getattr_res = {0}; bitmap4 attr_request; - nfs41_file_info info = { 0 }; + nfs41_file_info info = { 0 }, *pinfo; init_getattr_request(&attr_request); @@ -739,13 +740,16 @@ int nfs41_write( write_args.data = data; write_res.resok4.verf = verf; + if (cinfo) pinfo = cinfo; + else pinfo = &info; + if (stable != UNSTABLE4) { /* if the write is stable, we can't rely on COMMIT to update * the attribute cache, so we do the GETATTR here */ compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res); getattr_args.attr_request = &attr_request; getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT; - getattr_res.info = &info; + getattr_res.info = pinfo; } status = compound_encode_send_decode(session, &compound, TRUE); @@ -757,10 +761,10 @@ int nfs41_write( if (stable != UNSTABLE4) { /* update the attribute cache */ - memcpy(&info.attrmask, &getattr_res.obj_attributes.attrmask, + memcpy(&pinfo->attrmask, &getattr_res.obj_attributes.attrmask, sizeof(bitmap4)); nfs41_attr_cache_update(session_name_cache(session), - file->fh.fileid, &info); + file->fh.fileid, pinfo); } *bytes_written = write_res.resok4.count; @@ -773,7 +777,7 @@ int nfs41_write( nfs_error_string(status)); } - if (info.type == NF4NAMEDATTR) + if (pinfo->type == NF4NAMEDATTR) goto out; nfs41_superblock_space_changed(file->fh.superblock); @@ -848,7 +852,8 @@ int nfs41_commit( IN uint64_t offset, IN uint32_t count, IN bool_t do_getattr, - OUT nfs41_write_verf *verf) + OUT nfs41_write_verf *verf, + OUT nfs41_file_info *cinfo) { int status; nfs41_compound compound; @@ -863,7 +868,7 @@ int nfs41_commit( nfs41_getattr_args getattr_args; nfs41_getattr_res getattr_res = {0}; bitmap4 attr_request; - nfs41_file_info info; + nfs41_file_info info, *pinfo; compound_init(&compound, argops, resops, do_getattr ? "commit" : "ds commit"); @@ -884,13 +889,15 @@ int nfs41_commit( /* send a GETATTR request to update the attribute cache, * but not if we're talking to a data server! */ + if (cinfo) pinfo = cinfo; + else pinfo = &info; if (do_getattr) { init_getattr_request(&attr_request); compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res); getattr_args.attr_request = &attr_request; getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT; - getattr_res.info = &info; + getattr_res.info = pinfo; } status = compound_encode_send_decode(session, &compound, TRUE); @@ -902,10 +909,10 @@ int nfs41_commit( if (do_getattr) { /* update the attribute cache */ - memcpy(&info.attrmask, &getattr_res.obj_attributes.attrmask, + memcpy(&pinfo->attrmask, &getattr_res.obj_attributes.attrmask, sizeof(bitmap4)); nfs41_attr_cache_update(session_name_cache(session), - file->fh.fileid, &info); + file->fh.fileid, pinfo); } nfs41_superblock_space_changed(file->fh.superblock); out: @@ -2001,7 +2008,8 @@ enum nfsstat4 pnfs_rpc_layoutcommit( IN uint64_t offset, IN uint64_t length, IN OPTIONAL uint64_t *new_last_offset, - IN OPTIONAL nfstime4 *new_time_modify) + IN OPTIONAL nfstime4 *new_time_modify, + OUT nfs41_file_info *info) { enum nfsstat4 status; nfs41_compound compound; @@ -2015,7 +2023,6 @@ enum nfsstat4 pnfs_rpc_layoutcommit( pnfs_layoutcommit_res lc_res; nfs41_getattr_args getattr_args; nfs41_getattr_res getattr_res; - nfs41_file_info info; bitmap4 attr_request; init_getattr_request(&attr_request); @@ -2041,7 +2048,7 @@ enum nfsstat4 pnfs_rpc_layoutcommit( compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res); getattr_args.attr_request = &attr_request; getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT; - getattr_res.info = &info; + getattr_res.info = info; status = compound_encode_send_decode(session, &compound, TRUE); if (status) @@ -2051,10 +2058,10 @@ enum nfsstat4 pnfs_rpc_layoutcommit( goto out; /* update the attribute cache */ - memcpy(&info.attrmask, &getattr_res.obj_attributes.attrmask, + memcpy(&info->attrmask, &getattr_res.obj_attributes.attrmask, sizeof(bitmap4)); nfs41_attr_cache_update(session_name_cache(session), - file->fh.fileid, &info); + file->fh.fileid, info); out: return status; } diff --git a/daemon/nfs41_ops.h b/daemon/nfs41_ops.h index 89e56b3..ca2204f 100644 --- a/daemon/nfs41_ops.h +++ b/daemon/nfs41_ops.h @@ -1078,7 +1078,8 @@ int nfs41_write( IN uint64_t offset, IN enum stable_how4 stable, OUT uint32_t *bytes_written, - OUT nfs41_write_verf *verf); + OUT nfs41_write_verf *verf, + OUT nfs41_file_info *cinfo); int nfs41_read( IN nfs41_session *session, @@ -1096,7 +1097,8 @@ int nfs41_commit( IN uint64_t offset, IN uint32_t count, IN bool_t do_getattr, - OUT nfs41_write_verf *verf); + OUT nfs41_write_verf *verf, + OUT nfs41_file_info *cinfo); int nfs41_lock( IN nfs41_session *session, @@ -1257,7 +1259,8 @@ enum nfsstat4 pnfs_rpc_layoutcommit( IN uint64_t offset, IN uint64_t length, IN OPTIONAL uint64_t *new_last_offset, - IN OPTIONAL nfstime4 *new_time_modify); + IN OPTIONAL nfstime4 *new_time_modify, + OUT nfs41_file_info *info); enum nfsstat4 pnfs_rpc_layoutreturn( IN nfs41_session *session, diff --git a/daemon/pnfs.h b/daemon/pnfs.h index e79df25..eb20c6f 100644 --- a/daemon/pnfs.h +++ b/daemon/pnfs.h @@ -381,6 +381,7 @@ enum pnfs_status pnfs_write( IN uint64_t offset, IN uint64_t length, IN unsigned char *buffer, - OUT ULONG *len_out); + OUT ULONG *len_out, + OUT nfs41_file_info *cinfo); #endif /* !__PNFS_H__ */ diff --git a/daemon/pnfs_io.c b/daemon/pnfs_io.c index 1b63e32..647ef9e 100644 --- a/daemon/pnfs_io.c +++ b/daemon/pnfs_io.c @@ -371,7 +371,8 @@ retry_write: io.length = maxwritesize; nfsstat = nfs41_write(client->session, io.file, &stateid, io.buffer, - (uint32_t)io.length, io.offset, UNSTABLE4, &bytes_written, &verf); + (uint32_t)io.length, io.offset, UNSTABLE4, &bytes_written, + &verf, NULL); if (nfsstat) { eprintf("nfs41_write() failed with %s\n", nfs_error_string(nfsstat)); @@ -409,7 +410,7 @@ retry_write: dprintf(1, "sending COMMIT to data server for offset=%lld len=%lld\n", commit_min, commit_max - commit_min); nfsstat = nfs41_commit(client->session, commit_file, - commit_min, (uint32_t)(commit_max - commit_min), 0, &verf); + commit_min, (uint32_t)(commit_max - commit_min), 0, &verf, NULL); if (nfsstat) status = map_ds_error(nfsstat, pattern->state); @@ -473,7 +474,8 @@ static enum pnfs_status layout_commit( IN nfs41_open_state *state, IN pnfs_layout_state *layout, IN uint64_t offset, - IN uint64_t length) + IN uint64_t length, + OUT nfs41_file_info *info) { stateid4 layout_stateid; uint64_t last_offset = offset + length - 1; @@ -498,7 +500,7 @@ static enum pnfs_status layout_commit( dprintf(1, "LAYOUTCOMMIT for offset=%lld len=%lld new_last_offset=%u\n", offset, length, new_last_offset ? 1 : 0); nfsstat = pnfs_rpc_layoutcommit(state->session, &state->file, - &layout_stateid, offset, length, new_last_offset, NULL); + &layout_stateid, offset, length, new_last_offset, NULL, info); if (nfsstat) { dprintf(IOLVL, "pnfs_rpc_layoutcommit() failed with %s\n", nfs_error_string(nfsstat)); @@ -515,7 +517,8 @@ enum pnfs_status pnfs_write( IN uint64_t offset, IN uint64_t length, IN unsigned char *buffer, - OUT ULONG *len_out) + OUT ULONG *len_out, + OUT nfs41_file_info *info) { pnfs_io_pattern pattern; enum stable_how4 stable; @@ -550,7 +553,7 @@ enum pnfs_status pnfs_write( dprintf(1, "sending COMMIT to meta server for offset=%lld len=%lld\n", offset, *len_out); nfsstat = nfs41_commit(state->session, &state->file, - offset, *len_out, 1, &ignored); + offset, *len_out, 1, &ignored, info); if (nfsstat) { dprintf(IOLVL, "nfs41_commit() failed with %s\n", nfs_error_string(nfsstat)); @@ -558,13 +561,12 @@ enum pnfs_status pnfs_write( } } else if (stable == DATA_SYNC4) { /* send LAYOUTCOMMIT to sync the metadata */ - status = layout_commit(state, layout, offset, *len_out); + status = layout_commit(state, layout, offset, *len_out, info); } else { /* send a GETATTR to update the cached size */ - nfs41_file_info info = { 0 }; bitmap4 attr_request; init_getattr_request(&attr_request); - nfs41_getattr(state->session, &state->file, &attr_request, &info); + nfs41_getattr(state->session, &state->file, &attr_request, info); } out_free_pattern: pattern_free(&pattern); diff --git a/daemon/readwrite.c b/daemon/readwrite.c index 6420e28..b30ba90 100644 --- a/daemon/readwrite.c +++ b/daemon/readwrite.c @@ -190,6 +190,7 @@ static int write_to_mds( int status = 0; /* on write verifier mismatch, retry N times before failing */ uint32_t retries = MAX_WRITE_RETRIES; + nfs41_file_info info = { 0 }; retry_write: p = args->buffer; @@ -207,7 +208,7 @@ retry_write: uint32_t bytes_written = 0, chunk = min(to_send, maxwritesize); status = nfs41_write(session, file, stateid, p, chunk, - args->offset + reloffset, stable, &bytes_written, &verf); + args->offset + reloffset, stable, &bytes_written, &verf, &info); if (status && !len) goto out; p += bytes_written; @@ -225,7 +226,7 @@ retry_write: } if (committed != FILE_SYNC4) { dprintf(1, "sending COMMIT for offset=%d and len=%d\n", args->offset, len); - status = nfs41_commit(session, file, args->offset, len, 1, &verf); + status = nfs41_commit(session, file, args->offset, len, 1, &verf, &info); if (status) goto out; @@ -234,6 +235,7 @@ retry_write: goto out_verify_failed; } } + args->ctime = info.change; out: args->out_len = len; return nfs_to_windows_error(status, ERROR_NET_WRITE_FAULT); @@ -251,6 +253,7 @@ static int write_to_pnfs( readwrite_upcall_args *args = &upcall->args.rw; pnfs_layout_state *layout; int status = NO_ERROR; + nfs41_file_info info = { 0 }; if (pnfs_layout_state_open(upcall->state_ref, PNFS_IOMODE_RW, args->offset, args->len, &layout)) { @@ -259,10 +262,11 @@ static int write_to_pnfs( } if (pnfs_write(upcall->root_ref, upcall->state_ref, stateid, layout, - args->offset, args->len, args->buffer, &args->out_len)) { + args->offset, args->len, args->buffer, &args->out_len, &info)) { status = ERROR_WRITE_FAULT; goto out; } + args->ctime = info.change; out: return status; } @@ -301,7 +305,12 @@ out: static int marshall_rw(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall) { readwrite_upcall_args *args = &upcall->args.rw; - return safe_write(&buffer, length, &args->out_len, sizeof(args->out_len)); + int status; + status = safe_write(&buffer, length, &args->out_len, sizeof(args->out_len)); + if (status) goto out; + status = safe_write(&buffer, length, &args->ctime, sizeof(args->ctime)); +out: + return status; } diff --git a/daemon/setattr.c b/daemon/setattr.c index 26d62ce..b6df221 100644 --- a/daemon/setattr.c +++ b/daemon/setattr.c @@ -584,7 +584,8 @@ static int handle_setexattr(nfs41_upcall *upcall) stateid.stateid.seqid = 0; buf = (UCHAR *) eainfo->EaName + eainfo->EaNameLength + 1; status = nfs41_write(state->session, &file, &stateid, buf, - eainfo->EaValueLength, 0, FILE_SYNC4, &bytes_written, &verf); + eainfo->EaValueLength, 0, FILE_SYNC4, &bytes_written, + &verf, NULL); if (status) { dprintf(1, "handle_setexattr: nfs41_write() failed w/error %s.\n", nfs_error_string(status)); diff --git a/daemon/upcall.h b/daemon/upcall.h index a1d6fd9..12fe3ee 100644 --- a/daemon/upcall.h +++ b/daemon/upcall.h @@ -72,6 +72,7 @@ typedef struct __readwrite_upcall_args { LONGLONG offset; ULONG len; ULONG out_len; + ULONGLONG ctime; } readwrite_upcall_args; typedef struct __lock_upcall_args { diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c index fa27152..21548b5 100644 --- a/sys/nfs41_driver.c +++ b/sys/nfs41_driver.c @@ -149,6 +149,7 @@ typedef struct _updowncall_entry { LONGLONG offset; ULONG len; PRX_CONTEXT rxcontext; + ULONGLONG ChangeTime; } ReadWrite; struct { LONGLONG offset; @@ -1540,7 +1541,10 @@ NTSTATUS unmarshal_nfs41_rw( NTSTATUS status = STATUS_SUCCESS; RtlCopyMemory(&cur->u.ReadWrite.len, *buf, sizeof(cur->u.ReadWrite.len)); - DbgP("[read/write] returned len %ld\n", cur->u.ReadWrite.len); + *buf += sizeof(cur->u.ReadWrite.len); + RtlCopyMemory(&cur->u.ReadWrite.ChangeTime, *buf, sizeof(ULONGLONG)); + DbgP("[read/write] returned len %lu ChangeTime %llu\n", + cur->u.ReadWrite.len, cur->u.ReadWrite.ChangeTime); #if 1 /* 08/27/2010: it looks like we really don't need to call * MmUnmapLockedPages() eventhough we called