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:
parent
f280770c81
commit
4a52fae82d
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user