From f2a605eeab5752e4884987496f2661368f85b271 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 24 Nov 2004 06:09:14 +0000 Subject: r3939: - added "posix:fakeoplocks" option for testing with oplocks forced on - added support for sticky write times after a setfileinfo, by using a write_time field in the DosAttrib xattr structure. (This used to be commit 4a52fae82d8305e999f94f1947daa21dab54cdfd) --- source4/ntvfs/posix/pvfs_fileinfo.c | 1 + source4/ntvfs/posix/pvfs_open.c | 56 +++++++++++++++++++++++++--------- source4/ntvfs/posix/pvfs_setfileinfo.c | 2 ++ source4/ntvfs/posix/pvfs_xattr.c | 43 ++++++++++++++++++++------ source4/ntvfs/posix/vfs_posix.c | 4 +++ source4/ntvfs/posix/vfs_posix.h | 6 +++- 6 files changed, 88 insertions(+), 24 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_fileinfo.c b/source4/ntvfs/posix/pvfs_fileinfo.c index 32c7ae34fa..fa45444159 100644 --- a/source4/ntvfs/posix/pvfs_fileinfo.c +++ b/source4/ntvfs/posix/pvfs_fileinfo.c @@ -97,6 +97,7 @@ NTSTATUS pvfs_fill_dos_info(struct pvfs_state *pvfs, struct pvfs_filename *name, name->dos.nlink = name->st.st_nlink; name->dos.ea_size = 0; name->dos.file_id = (((uint64_t)name->st.st_dev)<<32) | name->st.st_ino; + name->dos.flags = 0; return pvfs_dosattrib_load(pvfs, name, fd); } diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 5a23ffaa67..3d0e444d29 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -26,6 +26,7 @@ #include "system/filesys.h" #include "dlinklist.h" #include "messages.h" +#include "librpc/gen_ndr/ndr_xattr.h" /* create file handles with convenient numbers for sniffers @@ -160,15 +161,16 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->share_access = io->generic.in.share_access; f->impersonation = io->generic.in.impersonation; - f->handle->pvfs = pvfs; - f->handle->name = talloc_steal(f->handle, name); - f->handle->fd = -1; - f->handle->odb_locking_key = data_blob(NULL, 0); - f->handle->brl_locking_key = data_blob(NULL, 0); - f->handle->create_options = io->generic.in.create_options; - f->handle->seek_offset = 0; - f->handle->position = 0; - f->handle->mode = 0; + f->handle->pvfs = pvfs; + f->handle->name = talloc_steal(f->handle, name); + f->handle->fd = -1; + f->handle->odb_locking_key = data_blob(NULL, 0); + f->handle->brl_locking_key = data_blob(NULL, 0); + f->handle->create_options = io->generic.in.create_options; + f->handle->seek_offset = 0; + f->handle->position = 0; + f->handle->mode = 0; + f->handle->sticky_write_time = False; DLIST_ADD(pvfs->open_files, f); @@ -201,7 +203,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* the open succeeded, keep this handle permanently */ talloc_steal(pvfs, f); - io->generic.out.oplock_level = NO_OPLOCK; + io->generic.out.oplock_level = OPLOCK_NONE; io->generic.out.fnum = f->fnum; io->generic.out.create_action = create_action; io->generic.out.create_time = name->dos.create_time; @@ -225,6 +227,16 @@ static int pvfs_handle_destructor(void *p) { struct pvfs_file_handle *h = p; + /* the write time is no longer sticky */ + if (h->sticky_write_time) { + NTSTATUS status; + status = pvfs_dosattrib_load(h->pvfs, h->name, h->fd); + if (NT_STATUS_IS_OK(status)) { + h->name->dos.flags &= ~XATTR_ATTRIB_FLAG_STICKY_WRITE_TIME; + pvfs_dosattrib_save(h->pvfs, h->name, h->fd); + } + } + if ((h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && h->name->stream_name) { NTSTATUS status; @@ -515,6 +527,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->handle->position = 0; f->handle->mode = 0; f->handle->have_opendb_entry = True; + f->handle->sticky_write_time = False; DLIST_ADD(pvfs->open_files, f); @@ -523,7 +536,12 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, talloc_set_destructor(f, pvfs_fnum_destructor); talloc_set_destructor(f->handle, pvfs_handle_destructor); - io->generic.out.oplock_level = NO_OPLOCK; + + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { + io->generic.out.oplock_level = OPLOCK_EXCLUSIVE; + } else { + io->generic.out.oplock_level = OPLOCK_NONE; + } io->generic.out.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_CREATED; io->generic.out.create_time = name->dos.create_time; @@ -685,7 +703,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, name = f->handle->name; - io->generic.out.oplock_level = NO_OPLOCK; + io->generic.out.oplock_level = OPLOCK_NONE; io->generic.out.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; io->generic.out.create_time = name->dos.create_time; @@ -963,7 +981,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->handle->create_options = io->generic.in.create_options; f->handle->seek_offset = 0; f->handle->position = 0; + f->handle->mode = 0; f->handle->have_opendb_entry = False; + f->handle->sticky_write_time = False; /* form the lock context used for byte range locking and opendb locking */ @@ -1063,7 +1083,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, talloc_free(lck); - io->generic.out.oplock_level = NO_OPLOCK; + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { + io->generic.out.oplock_level = OPLOCK_EXCLUSIVE; + } else { + io->generic.out.oplock_level = OPLOCK_NONE; + } io->generic.out.fnum = f->fnum; io->generic.out.create_action = stream_existed? NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED; @@ -1112,8 +1136,12 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, unix_times.actime = 0; unix_times.modtime = io->close.in.write_time; utime(f->handle->name->full_name, &unix_times); + } else if (f->handle->sticky_write_time) { + unix_times.actime = 0; + unix_times.modtime = nt_time_to_unix(f->handle->name->dos.write_time); + utime(f->handle->name->full_name, &unix_times); } - + talloc_free(f); return NT_STATUS_OK; diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c index cc1b69b8ea..5a758a6b70 100644 --- a/source4/ntvfs/posix/pvfs_setfileinfo.c +++ b/source4/ntvfs/posix/pvfs_setfileinfo.c @@ -245,6 +245,8 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs, } if (info->basic_info.in.write_time) { newstats.dos.write_time = info->basic_info.in.write_time; + newstats.dos.flags |= XATTR_ATTRIB_FLAG_STICKY_WRITE_TIME; + h->sticky_write_time = True; } if (info->basic_info.in.change_time) { newstats.dos.change_time = info->basic_info.in.change_time; diff --git a/source4/ntvfs/posix/pvfs_xattr.c b/source4/ntvfs/posix/pvfs_xattr.c index fda15a2e92..47549499e6 100644 --- a/source4/ntvfs/posix/pvfs_xattr.c +++ b/source4/ntvfs/posix/pvfs_xattr.c @@ -183,6 +183,7 @@ NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name struct xattr_DosAttrib attrib; TALLOC_CTX *mem_ctx = talloc(name, 0); struct xattr_DosInfo1 *info1; + struct xattr_DosInfo2 *info2; if (name->stream_name != NULL) { name->stream_exists = False; @@ -233,6 +234,27 @@ NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name if (info1->change_time != 0) { name->dos.change_time = info1->change_time; } + name->dos.flags = 0; + break; + + case 2: + info2 = &attrib.info.info2; + name->dos.attrib = pvfs_attrib_normalise(info2->attrib); + name->dos.ea_size = info2->ea_size; + if (name->st.st_size == info2->size) { + name->dos.alloc_size = + pvfs_round_alloc_size(pvfs, info2->alloc_size); + } + if (info2->create_time != 0) { + name->dos.create_time = info2->create_time; + } + if (info2->change_time != 0) { + name->dos.change_time = info2->change_time; + } + name->dos.flags = info2->flags; + if (name->dos.flags & XATTR_ATTRIB_FLAG_STICKY_WRITE_TIME) { + name->dos.write_time = info2->write_time; + } break; default: @@ -255,23 +277,26 @@ NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name NTSTATUS pvfs_dosattrib_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd) { struct xattr_DosAttrib attrib; - struct xattr_DosInfo1 *info1; + struct xattr_DosInfo2 *info2; if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) { return NT_STATUS_OK; } - attrib.version = 1; - info1 = &attrib.info.info1; + attrib.version = 2; + info2 = &attrib.info.info2; name->dos.attrib = pvfs_attrib_normalise(name->dos.attrib); - info1->attrib = name->dos.attrib; - info1->ea_size = name->dos.ea_size; - info1->size = name->st.st_size; - info1->alloc_size = name->dos.alloc_size; - info1->create_time = name->dos.create_time; - info1->change_time = name->dos.change_time; + info2->attrib = name->dos.attrib; + info2->ea_size = name->dos.ea_size; + info2->size = name->st.st_size; + info2->alloc_size = name->dos.alloc_size; + info2->create_time = name->dos.create_time; + info2->change_time = name->dos.change_time; + info2->write_time = name->dos.write_time; + info2->flags = name->dos.flags; + info2->name = ""; return pvfs_xattr_ndr_save(pvfs, name->full_name, fd, XATTR_DOSATTRIB_NAME, &attrib, diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c index e19b0739c7..95b4c20551 100644 --- a/source4/ntvfs/posix/vfs_posix.c +++ b/source4/ntvfs/posix/vfs_posix.c @@ -44,6 +44,10 @@ static void pvfs_setup_options(struct pvfs_state *pvfs) if (lp_strict_locking(snum)) pvfs->flags |= PVFS_FLAG_STRICT_LOCKING; if (lp_ci_filesystem(snum)) pvfs->flags |= PVFS_FLAG_CI_FILESYSTEM; + if (lp_parm_bool(snum, "posix", "fakeoplocks", True)) { + pvfs->flags |= PVFS_FLAG_FAKE_OPLOCKS; + } + #if HAVE_XATTR_SUPPORT if (lp_parm_bool(snum, "posix", "xattr", True)) pvfs->flags |= PVFS_FLAG_XATTR_ENABLE; #endif diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index a79c53ca2e..1ae552b116 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -58,7 +58,6 @@ struct pvfs_state { uint32_t fs_attribs; }; - /* this is the basic information needed about a file from the filesystem */ struct pvfs_dos_fileinfo { NTTIME create_time; @@ -70,6 +69,7 @@ struct pvfs_dos_fileinfo { uint32_t nlink; uint32_t ea_size; uint64_t file_id; + uint32_t flags; }; /* @@ -120,6 +120,9 @@ struct pvfs_file_handle { /* we need this hook back to our parent for lock destruction */ struct pvfs_state *pvfs; + + /* have we set a sticky write time that we should remove on close */ + BOOL sticky_write_time; }; /* open file state */ @@ -189,6 +192,7 @@ struct pvfs_mangle_context { #define PVFS_FLAG_STRICT_SYNC (1<<5) #define PVFS_FLAG_STRICT_LOCKING (1<<6) #define PVFS_FLAG_XATTR_ENABLE (1<<7) +#define PVFS_FLAG_FAKE_OPLOCKS (1<<8) /* forward declare some anonymous structures */ struct pvfs_dir; -- cgit