1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00

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 commit is contained in:
Andrew Tridgell 2004-11-24 06:09:14 +00:00 committed by Gerald (Jerry) Carter
parent f280770c81
commit 4a52fae82d
8 changed files with 116 additions and 43 deletions

View File

@ -518,7 +518,6 @@ typedef uint64_t HYPER_T;
#define NEGOTIATE_SECURITY_SIGNATURES_REQUIRED 0x08
/* NT Flags2 bits - cifs6.txt section 3.1.2 */
#define FLAGS2_LONG_PATH_COMPONENTS 0x0001
#define FLAGS2_EXTENDED_ATTRIBUTES 0x0002
#define FLAGS2_SMB_SECURITY_SIGNATURES 0x0004
@ -529,10 +528,8 @@ typedef uint64_t HYPER_T;
#define FLAGS2_32_BIT_ERROR_CODES 0x4000
#define FLAGS2_UNICODE_STRINGS 0x8000
#define FLAGS2_WIN2K_SIGNATURE 0xC852 /* Hack alert ! For now... JRA. */
/* Capabilities. see ftp.microsoft.com/developr/drg/cifs/cifs/cifs4.txt */
/* CIFS protocol capabilities */
#define CAP_RAW_MODE 0x00000001
#define CAP_MPX_MODE 0x00000002
#define CAP_UNICODE 0x00000004
@ -551,7 +548,7 @@ typedef uint64_t HYPER_T;
#define CAP_EXTENDED_SECURITY 0x80000000
/*
* Global value meaing that the smb_uid field should be
* Global value meaning that the smb_uid field should be
* ingored (in share level security and protocol level == CORE)
*/
@ -559,24 +556,20 @@ typedef uint64_t HYPER_T;
#define VUID_OFFSET 100 /* Amount to bias returned vuid numbers */
/* Lock types. */
#define LOCKING_ANDX_SHARED_LOCK 0x1
#define LOCKING_ANDX_OPLOCK_RELEASE 0x2
#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x4
#define LOCKING_ANDX_CANCEL_LOCK 0x8
#define LOCKING_ANDX_LARGE_FILES 0x10
/* Oplock levels */
#define OPLOCKLEVEL_NONE 0
#define OPLOCKLEVEL_II 1
#define LOCKING_ANDX_SHARED_LOCK 0x01
#define LOCKING_ANDX_OPLOCK_RELEASE 0x02
#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04
#define LOCKING_ANDX_CANCEL_LOCK 0x08
#define LOCKING_ANDX_LARGE_FILES 0x10
/*
* Bits we test with.
*/
#define NO_OPLOCK 0
#define EXCLUSIVE_OPLOCK 1
#define BATCH_OPLOCK 2
#define LEVEL_II_OPLOCK 4
#define OPLOCK_NONE 0
#define OPLOCK_EXCLUSIVE 1
#define OPLOCK_BATCH 2
#define OPLOCK_LEVEL_II 4
#define CORE_OPLOCK_GRANTED (1<<5)
#define EXTENDED_OPLOCK_GRANTED (1<<15)

View File

@ -19,6 +19,7 @@ interface xattr
/* we store basic dos attributes in a DosAttrib xattr. By
using a union we can cope with new version of this
structure more easily */
typedef struct {
uint32 attrib;
uint32 ea_size;
@ -28,8 +29,23 @@ interface xattr
NTTIME change_time;
} xattr_DosInfo1;
const int XATTR_ATTRIB_FLAG_STICKY_WRITE_TIME = 0x1;
typedef struct {
uint32 flags;
uint32 attrib;
uint32 ea_size;
uint64 size;
uint64 alloc_size;
NTTIME create_time;
NTTIME change_time;
NTTIME write_time; /* only used when sticky write time is set */
utf8string name; /* will be used for case-insensitive speedup */
} xattr_DosInfo2;
typedef union {
[case(1)] xattr_DosInfo1 info1;
[case(2)] xattr_DosInfo2 info2;
} xattr_DosInfo;
typedef [public] struct {
@ -77,7 +93,7 @@ interface xattr
} xattr_DosStreams;
/* we store the NT ACL a NTAcl xattr. It is versioned so we
/* we store the NT ACL a NTACL xattr. It is versioned so we
can later add other acl attribs (such as posix acl mapping)
we put this xattr in the security namespace to ensure that

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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;