diff options
-rw-r--r-- | source4/include/smb.h | 2 | ||||
-rw-r--r-- | source4/include/smb_interfaces.h | 4 | ||||
-rw-r--r-- | source4/ntvfs/common/brlock.c | 418 | ||||
-rw-r--r-- | source4/ntvfs/posix/config.mk | 4 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_lock.c | 151 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_open.c | 19 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_read.c | 9 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_write.c | 17 | ||||
-rw-r--r-- | source4/ntvfs/posix/vfs_posix.c | 28 | ||||
-rw-r--r-- | source4/ntvfs/posix/vfs_posix.h | 21 | ||||
-rw-r--r-- | source4/smbd/process_model.h | 2 | ||||
-rw-r--r-- | source4/smbd/process_single.c | 2 | ||||
-rw-r--r-- | source4/smbd/process_standard.c | 2 | ||||
-rw-r--r-- | source4/smbd/process_thread.c | 2 | ||||
-rw-r--r-- | source4/smbd/service.c | 6 | ||||
-rw-r--r-- | source4/smbd/service.h | 15 |
16 files changed, 671 insertions, 31 deletions
diff --git a/source4/include/smb.h b/source4/include/smb.h index 46b2dd03ca..745e90e4ff 100644 --- a/source4/include/smb.h +++ b/source4/include/smb.h @@ -611,6 +611,6 @@ typedef struct nt_user_token { #define REQ_CONTROL_ASYNC (1<<2) /* the backend will answer this one later */ /* passed to br lock code */ -enum brl_type {READ_LOCK, WRITE_LOCK, PENDING_LOCK}; +enum brl_type {READ_LOCK, WRITE_LOCK}; #endif /* _SMB_H */ diff --git a/source4/include/smb_interfaces.h b/source4/include/smb_interfaces.h index 4acdf51b56..e9f51ba4d1 100644 --- a/source4/include/smb_interfaces.h +++ b/source4/include/smb_interfaces.h @@ -1450,7 +1450,9 @@ union smb_lock { /* generic interface */ struct { enum smb_lock_level level; - + struct { + uint16_t fnum; + } in; } generic; /* SMBlock interface */ diff --git a/source4/ntvfs/common/brlock.c b/source4/ntvfs/common/brlock.c new file mode 100644 index 0000000000..0eb644e943 --- /dev/null +++ b/source4/ntvfs/common/brlock.c @@ -0,0 +1,418 @@ +/* + Unix SMB/CIFS implementation. + + generic byte range locking code + + Copyright (C) Andrew Tridgell 1992-2004 + Copyright (C) Jeremy Allison 1992-2000 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This module implements a tdb based byte range locking service, + replacing the fcntl() based byte range locking previously + used. This allows us to provide the same semantics as NT */ + +#include "includes.h" + +struct brl_context { + struct tdb_wrap *w; + servid_t server; + uint16_t tid; +}; + +/* + in this module a "DATA_BLOB *file_key" is a blob that uniquely identifies + a file. For a local posix filesystem this will usually be a combination + of the device and inode numbers of the file, but it can be anything + that uniquely idetifies a file for locking purposes, as long + as it is applied consistently. +*/ + +/* + the lock context contains the elements that define whether one + lock is the same as another lock +*/ +struct lock_context { + servid_t server; + uint16_t smbpid; + uint16_t tid; +}; + +/* The data in brlock records is an unsorted linear array of these + records. It is unnecessary to store the count as tdb provides the + size of the record */ +struct lock_struct { + struct lock_context context; + uint64_t start; + uint64_t size; + uint16_t fnum; + enum brl_type lock_type; +}; + +/* + Open up the brlock.tdb database. Close it down using + talloc_free() +*/ +void *brl_init(TALLOC_CTX *mem_ctx, servid_t server, uint16_t tid) +{ + char *path; + struct brl_context *brl; + + brl = talloc_p(mem_ctx, struct brl_context); + if (brl == NULL) { + return NULL; + } + + path = lock_path(brl, "brlock.tdb"); + brl->w = tdb_wrap_open(brl, path, 0, + TDB_DEFAULT|TDB_CLEAR_IF_FIRST, + O_RDWR|O_CREAT, 0600); + talloc_free(path); + if (brl->w == NULL) { + talloc_free(brl); + return NULL; + } + + brl->server = server; + brl->tid = tid; + + return (void *)brl; +} + + +/* + see if two locking contexts are equal +*/ +static BOOL brl_same_context(struct lock_context *ctx1, struct lock_context *ctx2) +{ + return (ctx1->server == ctx2->server && + ctx1->smbpid == ctx2->smbpid && + ctx1->tid == ctx2->tid); +} + +/* + See if lock2 can be added when lock1 is in place. +*/ +static BOOL brl_conflict(struct lock_struct *lck1, + struct lock_struct *lck2) +{ + if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) { + return False; + } + + if (brl_same_context(&lck1->context, &lck2->context) && + lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) { + return False; + } + + if (lck1->start >= (lck2->start + lck2->size) || + lck2->start >= (lck1->start + lck1->size)) { + return False; + } + + return True; +} + + +/* + Check to see if this lock conflicts, but ignore our own locks on the + same fnum only. +*/ +static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck2) +{ + if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) + return False; + + if (brl_same_context(&lck1->context, &lck2->context) && + lck1->fnum == lck2->fnum) { + return False; + } + + if (lck1->start >= (lck2->start + lck2->size) || + lck2->start >= (lck1->start + lck1->size)) + return False; + + return True; +} + + + +/* + Lock a range of bytes. +*/ +NTSTATUS brl_lock(void *brl_ctx, + DATA_BLOB *file_key, + uint16_t smbpid, + uint16_t fnum, + uint64_t start, uint64_t size, + enum brl_type lock_type) +{ + struct brl_context *brl = brl_ctx; + TDB_DATA kbuf, dbuf; + int count, i; + struct lock_struct lock, *locks; + char *tp; + NTSTATUS status; + + kbuf.dptr = file_key->data; + kbuf.dsize = file_key->length; + + if (tdb_chainlock(brl->w->tdb, kbuf) != 0) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + dbuf = tdb_fetch(brl->w->tdb, kbuf); + + lock.context.smbpid = smbpid; + lock.context.server = brl->server; + lock.context.tid = brl->tid; + lock.start = start; + lock.size = size; + lock.fnum = fnum; + lock.lock_type = lock_type; + + if (dbuf.dptr) { + /* there are existing locks - make sure they don't conflict */ + locks = (struct lock_struct *)dbuf.dptr; + count = dbuf.dsize / sizeof(*locks); + for (i=0; i<count; i++) { + if (brl_conflict(&locks[i], &lock)) { + status = NT_STATUS_LOCK_NOT_GRANTED; + goto fail; + } + } + } + + /* no conflicts - add it to the list of locks */ + tp = Realloc(dbuf.dptr, dbuf.dsize + sizeof(*locks)); + if (!tp) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } else { + dbuf.dptr = tp; + } + memcpy(dbuf.dptr + dbuf.dsize, &lock, sizeof(lock)); + dbuf.dsize += sizeof(lock); + + if (tdb_store(brl->w->tdb, kbuf, dbuf, TDB_REPLACE) != 0) { + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto fail; + } + + free(dbuf.dptr); + tdb_chainunlock(brl->w->tdb, kbuf); + return NT_STATUS_OK; + + fail: + + free(dbuf.dptr); + tdb_chainunlock(brl->w->tdb, kbuf); + return status; +} + + +/* + Unlock a range of bytes. +*/ +NTSTATUS brl_unlock(void *brl_ctx, + DATA_BLOB *file_key, + uint16_t smbpid, + uint16_t fnum, + uint64_t start, uint64_t size) +{ + struct brl_context *brl = brl_ctx; + TDB_DATA kbuf, dbuf; + int count, i; + struct lock_struct *locks; + struct lock_context context; + NTSTATUS status; + + kbuf.dptr = file_key->data; + kbuf.dsize = file_key->length; + + if (tdb_chainlock(brl->w->tdb, kbuf) != 0) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + dbuf = tdb_fetch(brl->w->tdb, kbuf); + if (!dbuf.dptr) { + tdb_chainunlock(brl->w->tdb, kbuf); + return NT_STATUS_RANGE_NOT_LOCKED; + } + + context.smbpid = smbpid; + context.server = brl->server; + context.tid = brl->tid; + + /* there are existing locks - find a match */ + locks = (struct lock_struct *)dbuf.dptr; + count = dbuf.dsize / sizeof(*locks); + + locks = (struct lock_struct *)dbuf.dptr; + count = dbuf.dsize / sizeof(*locks); + for (i=0; i<count; i++) { + struct lock_struct *lock = &locks[i]; + + if (brl_same_context(&lock->context, &context) && + lock->fnum == fnum && + lock->start == start && + lock->size == size) { + /* found it - delete it */ + if (count == 1) { + if (tdb_delete(brl->w->tdb, kbuf) != 0) { + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto fail; + } + } else { + if (i < count-1) { + memmove(&locks[i], &locks[i+1], + sizeof(*locks)*((count-1) - i)); + } + dbuf.dsize -= sizeof(*locks); + if (tdb_store(brl->w->tdb, kbuf, dbuf, TDB_REPLACE) != 0) { + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto fail; + } + } + + free(dbuf.dptr); + tdb_chainunlock(brl->w->tdb, kbuf); + return NT_STATUS_OK; + } + } + + /* we didn't find it */ + status = NT_STATUS_RANGE_NOT_LOCKED; + + fail: + free(dbuf.dptr); + tdb_chainunlock(brl->w->tdb, kbuf); + return status; +} + + +/* + Test if we are allowed to perform IO on a region of an open file +*/ +NTSTATUS brl_locktest(void *brl_ctx, + DATA_BLOB *file_key, + uint16_t fnum, + uint16 smbpid, + uint64_t start, uint64_t size, + enum brl_type lock_type) +{ + struct brl_context *brl = brl_ctx; + TDB_DATA kbuf, dbuf; + int count, i; + struct lock_struct lock, *locks; + + kbuf.dptr = file_key->data; + kbuf.dsize = file_key->length; + + dbuf = tdb_fetch(brl->w->tdb, kbuf); + if (dbuf.dptr == NULL) { + return NT_STATUS_OK; + } + + lock.context.smbpid = smbpid; + lock.context.server = brl->server; + lock.context.tid = brl->tid; + lock.start = start; + lock.size = size; + lock.fnum = fnum; + lock.lock_type = lock_type; + + /* there are existing locks - make sure they don't conflict */ + locks = (struct lock_struct *)dbuf.dptr; + count = dbuf.dsize / sizeof(*locks); + + for (i=0; i<count; i++) { + if (brl_conflict_other(&locks[i], &lock)) { + free(dbuf.dptr); + return NT_STATUS_FILE_LOCK_CONFLICT; + } + } + + free(dbuf.dptr); + return NT_STATUS_OK; +} + + +/* + Remove any locks associated with a open file. +*/ +NTSTATUS brl_close(void *brl_ctx, + DATA_BLOB *file_key, int fnum) +{ + struct brl_context *brl = brl_ctx; + TDB_DATA kbuf, dbuf; + int count, i, dcount=0; + struct lock_struct *locks; + NTSTATUS status; + + kbuf.dptr = file_key->data; + kbuf.dsize = file_key->length; + + if (tdb_chainlock(brl->w->tdb, kbuf) != 0) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + dbuf = tdb_fetch(brl->w->tdb, kbuf); + if (!dbuf.dptr) { + tdb_chainunlock(brl->w->tdb, kbuf); + return NT_STATUS_OK; + } + + /* there are existing locks - remove any for this fnum */ + locks = (struct lock_struct *)dbuf.dptr; + count = dbuf.dsize / sizeof(*locks); + + for (i=0; i<count; i++) { + struct lock_struct *lock = &locks[i]; + + if (lock->context.tid == brl->tid && + lock->context.server == brl->server && + lock->fnum == fnum) { + /* found it - delete it */ + if (count > 1 && i < count-1) { + memmove(&locks[i], &locks[i+1], + sizeof(*locks)*((count-1) - i)); + } + count--; + i--; + dcount++; + } + } + + status = NT_STATUS_OK; + + if (count == 0) { + if (tdb_delete(brl->w->tdb, kbuf) != 0) { + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + } + } else if (dcount != 0) { + dbuf.dsize -= dcount * sizeof(*locks); + if (tdb_store(brl->w->tdb, kbuf, dbuf, TDB_REPLACE) != 0) { + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + } + } + + free(dbuf.dptr); + tdb_chainunlock(brl->w->tdb, kbuf); + + return status; +} + diff --git a/source4/ntvfs/posix/config.mk b/source4/ntvfs/posix/config.mk index 019288faaa..8ca5ad7b0b 100644 --- a/source4/ntvfs/posix/config.mk +++ b/source4/ntvfs/posix/config.mk @@ -19,6 +19,8 @@ ADD_OBJ_FILES = \ ntvfs/posix/pvfs_setfileinfo.o \ ntvfs/posix/pvfs_rename.o \ ntvfs/posix/pvfs_resolve.o \ - ntvfs/posix/pvfs_shortname.o + ntvfs/posix/pvfs_shortname.o \ + ntvfs/posix/pvfs_lock.o \ + ntvfs/common/brlock.o # End MODULE ntvfs_posix ################################################ diff --git a/source4/ntvfs/posix/pvfs_lock.c b/source4/ntvfs/posix/pvfs_lock.c new file mode 100644 index 0000000000..d7aca9df8b --- /dev/null +++ b/source4/ntvfs/posix/pvfs_lock.c @@ -0,0 +1,151 @@ +/* + Unix SMB/CIFS implementation. + + POSIX NTVFS backend - locking + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "include/includes.h" +#include "vfs_posix.h" + + +/* + check if we can perform IO on a range that might be locked +*/ +NTSTATUS pvfs_check_lock(struct pvfs_state *pvfs, + struct pvfs_file *f, + uint16_t smbpid, + uint64_t offset, uint64_t count, + enum brl_type rw) +{ + if (!(pvfs->flags & PVFS_FLAG_STRICT_LOCKING)) { + return NT_STATUS_OK; + } + + return brl_locktest(pvfs->brl_context, + &f->locking_key, + f->fnum, + smbpid, + offset, count, rw); +} + +/* + lock or unlock a byte range +*/ +NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs, + struct smbsrv_request *req, union smb_lock *lck) +{ + struct pvfs_state *pvfs = ntvfs->private_data; + struct pvfs_file *f; + struct smb_lock_entry *locks; + int i; + enum brl_type rw; + + f = pvfs_find_fd(pvfs, req, lck->generic.in.fnum); + if (!f) { + return NT_STATUS_INVALID_HANDLE; + } + + switch (lck->generic.level) { + case RAW_LOCK_LOCK: + return brl_lock(pvfs->brl_context, + &f->locking_key, + req->smbpid, + f->fnum, + lck->lock.in.offset, + lck->lock.in.count, + WRITE_LOCK); + + case RAW_LOCK_UNLOCK: + return brl_unlock(pvfs->brl_context, + &f->locking_key, + req->smbpid, + f->fnum, + lck->lock.in.offset, + lck->lock.in.count); + + case RAW_LOCK_GENERIC: + return NT_STATUS_INVALID_LEVEL; + + case RAW_LOCK_LOCKX: + /* fall through to the most complex case */ + break; + } + + /* now the lockingX case, most common and also most complex */ + + if (lck->lockx.in.mode & LOCKING_ANDX_SHARED_LOCK) { + rw = READ_LOCK; + } else { + rw = WRITE_LOCK; + } + + if (lck->lockx.in.mode & + (LOCKING_ANDX_OPLOCK_RELEASE | + LOCKING_ANDX_CHANGE_LOCKTYPE | + LOCKING_ANDX_CANCEL_LOCK)) { + /* todo: need to add support for these */ + return NT_STATUS_NOT_IMPLEMENTED; + } + + + /* the unlocks happen first */ + locks = lck->lockx.in.locks; + + for (i=0;i<lck->lockx.in.ulock_cnt;i++) { + NTSTATUS status; + status = brl_unlock(pvfs->brl_context, + &f->locking_key, + locks[i].pid, + f->fnum, + locks[i].offset, + locks[i].count); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + locks += i; + + for (i=0;i<lck->lockx.in.lock_cnt;i++) { + NTSTATUS status; + + status = brl_lock(pvfs->brl_context, + &f->locking_key, + locks[i].pid, + f->fnum, + locks[i].offset, + locks[i].count, + rw); + if (!NT_STATUS_IS_OK(status)) { + /* undo the locks we just did */ + for (i=i-1;i>=0;i--) { + brl_unlock(pvfs->brl_context, + &f->locking_key, + locks[i].pid, + f->fnum, + locks[i].offset, + locks[i].count); + } + return status; + } + } + + return NT_STATUS_OK; +} + diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 29e57e5a08..51526461e0 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -51,6 +51,9 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, static int pvfs_fd_destructor(void *p) { struct pvfs_file *f = p; + + brl_close(f->pvfs->brl_context, &f->locking_key, f->fnum); + if (f->fd != -1) { close(f->fd); f->fd = -1; @@ -71,6 +74,10 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, struct pvfs_filename *name; struct pvfs_file *f; NTSTATUS status; + struct { + dev_t device; + ino_t inode; + } lock_context; if (io->generic.level != RAW_OPEN_GENERIC) { return ntvfs_map_open(req, io, ntvfs); @@ -161,6 +168,13 @@ do_open: f->name = talloc_steal(f, name); f->session = req->session; f->smbpid = req->smbpid; + f->pvfs = pvfs; + + /* we must zero here to take account of padding */ + ZERO_STRUCT(lock_context); + lock_context.device = name->st.st_dev; + lock_context.inode = name->st.st_ino; + f->locking_key = data_blob_talloc(f, &lock_context, sizeof(lock_context)); /* setup a destructor to avoid file descriptor leaks on abnormal termination */ @@ -204,6 +218,11 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_HANDLE; } + status = brl_close(pvfs->brl_context, &f->locking_key, f->fnum); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (close(f->fd) != 0) { status = pvfs_map_errno(pvfs, errno); } else { diff --git a/source4/ntvfs/posix/pvfs_read.c b/source4/ntvfs/posix/pvfs_read.c index e0c7e0b1f2..24142a81ee 100644 --- a/source4/ntvfs/posix/pvfs_read.c +++ b/source4/ntvfs/posix/pvfs_read.c @@ -32,6 +32,7 @@ NTSTATUS pvfs_read(struct ntvfs_module_context *ntvfs, struct pvfs_state *pvfs = ntvfs->private_data; ssize_t ret; struct pvfs_file *f; + NTSTATUS status; if (rd->generic.level != RAW_READ_READX) { return NT_STATUS_NOT_SUPPORTED; @@ -43,6 +44,14 @@ NTSTATUS pvfs_read(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_HANDLE; } + status = pvfs_check_lock(pvfs, f, req->smbpid, + rd->readx.in.offset, + rd->readx.in.maxcnt, + READ_LOCK); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + ret = pread(f->fd, rd->readx.out.data, rd->readx.in.maxcnt, diff --git a/source4/ntvfs/posix/pvfs_write.c b/source4/ntvfs/posix/pvfs_write.c index a49f4fe947..80a3dae3a7 100644 --- a/source4/ntvfs/posix/pvfs_write.c +++ b/source4/ntvfs/posix/pvfs_write.c @@ -33,6 +33,7 @@ NTSTATUS pvfs_write(struct ntvfs_module_context *ntvfs, struct pvfs_state *pvfs = ntvfs->private_data; ssize_t ret; struct pvfs_file *f; + NTSTATUS status; switch (wr->generic.level) { case RAW_WRITE_WRITEX: @@ -40,6 +41,14 @@ NTSTATUS pvfs_write(struct ntvfs_module_context *ntvfs, if (!f) { return NT_STATUS_INVALID_HANDLE; } + status = pvfs_check_lock(pvfs, f, req->smbpid, + wr->writex.in.offset, + wr->writex.in.count, + WRITE_LOCK); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + ret = pwrite(f->fd, wr->writex.in.data, wr->writex.in.count, @@ -62,6 +71,14 @@ NTSTATUS pvfs_write(struct ntvfs_module_context *ntvfs, /* a truncate! */ ret = ftruncate(f->fd, wr->write.in.offset); } else { + status = pvfs_check_lock(pvfs, f, req->smbpid, + wr->write.in.offset, + wr->write.in.count, + WRITE_LOCK); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + ret = pwrite(f->fd, wr->write.in.data, wr->write.in.count, diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c index a17b90e369..5e7a605c9f 100644 --- a/source4/ntvfs/posix/vfs_posix.c +++ b/source4/ntvfs/posix/vfs_posix.c @@ -35,11 +35,12 @@ static void pvfs_setup_options(struct pvfs_state *pvfs) { int snum = pvfs->tcon->service; - if (lp_map_hidden(snum)) pvfs->flags |= PVFS_FLAG_MAP_HIDDEN; - if (lp_map_archive(snum)) pvfs->flags |= PVFS_FLAG_MAP_ARCHIVE; - if (lp_map_system(snum)) pvfs->flags |= PVFS_FLAG_MAP_SYSTEM; - if (lp_readonly(snum)) pvfs->flags |= PVFS_FLAG_READONLY; - if (lp_strict_sync(snum)) pvfs->flags |= PVFS_FLAG_STRICT_SYNC; + if (lp_map_hidden(snum)) pvfs->flags |= PVFS_FLAG_MAP_HIDDEN; + if (lp_map_archive(snum)) pvfs->flags |= PVFS_FLAG_MAP_ARCHIVE; + if (lp_map_system(snum)) pvfs->flags |= PVFS_FLAG_MAP_SYSTEM; + if (lp_readonly(snum)) pvfs->flags |= PVFS_FLAG_READONLY; + if (lp_strict_sync(snum)) pvfs->flags |= PVFS_FLAG_STRICT_SYNC; + if (lp_strict_locking(snum)) pvfs->flags |= PVFS_FLAG_STRICT_LOCKING; pvfs->share_name = talloc_strdup(pvfs, lp_servicename(snum)); } @@ -86,6 +87,13 @@ static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs, ntvfs->private_data = pvfs; + pvfs->brl_context = brl_init(pvfs, + pvfs->tcon->smb_conn->connection->server_id, + pvfs->tcon->service); + if (pvfs->brl_context == NULL) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + status = pvfs_mangle_init(pvfs); if (!NT_STATUS_IS_OK(status)) { return status; @@ -162,16 +170,6 @@ static NTSTATUS pvfs_seek(struct ntvfs_module_context *ntvfs, } /* - lock a byte range -*/ -static NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs, - struct smbsrv_request *req, union smb_lock *lck) -{ - DEBUG(0,("pvfs_lock not implemented\n")); - return NT_STATUS_NOT_IMPLEMENTED; -} - -/* set info on a pathname */ static NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs, diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index 6819d01529..e83f0479a9 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -51,6 +51,8 @@ struct pvfs_state { struct pvfs_file *open_files; struct pvfs_mangle_context *mangle_ctx; + + void *brl_context; }; @@ -115,6 +117,12 @@ struct pvfs_file { /* we need to remember the client pid that opened the file so SMBexit works */ uint16_t smbpid; + + /* a unique file key to be used for file locking */ + DATA_BLOB locking_key; + + /* we need this hook back to our parent for lock destruction */ + struct pvfs_state *pvfs; }; struct pvfs_mangle_context { @@ -147,11 +155,12 @@ struct pvfs_mangle_context { #define PVFS_RESOLVE_STREAMS (1<<1) /* flags in pvfs->flags */ -#define PVFS_FLAG_CI_FILESYSTEM (1<<0) /* the filesystem is case insensitive */ -#define PVFS_FLAG_MAP_ARCHIVE (1<<1) -#define PVFS_FLAG_MAP_SYSTEM (1<<2) -#define PVFS_FLAG_MAP_HIDDEN (1<<3) -#define PVFS_FLAG_READONLY (1<<4) -#define PVFS_FLAG_STRICT_SYNC (1<<5) +#define PVFS_FLAG_CI_FILESYSTEM (1<<0) /* the filesystem is case insensitive */ +#define PVFS_FLAG_MAP_ARCHIVE (1<<1) +#define PVFS_FLAG_MAP_SYSTEM (1<<2) +#define PVFS_FLAG_MAP_HIDDEN (1<<3) +#define PVFS_FLAG_READONLY (1<<4) +#define PVFS_FLAG_STRICT_SYNC (1<<5) +#define PVFS_FLAG_STRICT_LOCKING (1<<6) #endif /* _VFS_POSIX_H_ */ diff --git a/source4/smbd/process_model.h b/source4/smbd/process_model.h index 376b9a8ef8..79373d8a39 100644 --- a/source4/smbd/process_model.h +++ b/source4/smbd/process_model.h @@ -23,8 +23,6 @@ #ifndef SAMBA_PROCESS_MODEL_H #define SAMBA_PROCESS_MODEL_H -struct server_service_connection; - /* modules can use the following to determine if the interface has changed * please increment the version number after each interface change * with a comment and maybe update struct process_model_critical_sizes. diff --git a/source4/smbd/process_single.c b/source4/smbd/process_single.c index 12a265b62f..b96a1d0b2c 100644 --- a/source4/smbd/process_single.c +++ b/source4/smbd/process_single.c @@ -49,7 +49,7 @@ static void single_accept_connection(struct event_context *ev, struct fd_event * return; } - conn = server_setup_connection(ev, server_socket, sock, t); + conn = server_setup_connection(ev, server_socket, sock, t, socket_get_fd(sock)); if (!conn) { DEBUG(0,("server_setup_connection(ev, server_socket, sock, t) failed\n")); return; diff --git a/source4/smbd/process_standard.c b/source4/smbd/process_standard.c index 122c6581b0..d70cfa676b 100644 --- a/source4/smbd/process_standard.c +++ b/source4/smbd/process_standard.c @@ -74,7 +74,7 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event set_need_random_reseed(); - conn = server_setup_connection(ev, server_socket, sock, t); + conn = server_setup_connection(ev, server_socket, sock, t, getpid()); if (!conn) { DEBUG(0,("server_setup_connection(ev, server_socket, sock, t) failed\n")); return; diff --git a/source4/smbd/process_thread.c b/source4/smbd/process_thread.c index 55688f85e8..85f30c9ddd 100644 --- a/source4/smbd/process_thread.c +++ b/source4/smbd/process_thread.c @@ -79,7 +79,7 @@ static void thread_accept_connection(struct event_context *ev, struct fd_event * return; } - conn = server_setup_connection(ev, server_socket, sock, t); + conn = server_setup_connection(ev, server_socket, sock, t, pthread_self()); if (!conn) { DEBUG(0,("server_setup_connection(ev, server_socket, sock, t) failed\n")); event_context_destroy(ev); diff --git a/source4/smbd/service.c b/source4/smbd/service.c index 5aae84b2c9..9a7ac73559 100644 --- a/source4/smbd/service.c +++ b/source4/smbd/service.c @@ -198,7 +198,8 @@ static int server_destructor(void *ptr) struct server_connection *server_setup_connection(struct event_context *ev, struct server_socket *server_socket, struct socket_context *sock, - time_t t) + time_t t, + servid_t server_id) { struct fd_event fde; struct timed_event idle; @@ -206,7 +207,7 @@ struct server_connection *server_setup_connection(struct event_context *ev, srv_conn = talloc_p(server_socket, struct server_connection); if (!srv_conn) { - DEBUG(0,("talloc_p(mem_ctx, struct server_service_connection) failed\n")); + DEBUG(0,("talloc_p(mem_ctx, struct server_connection) failed\n")); return NULL; } @@ -229,6 +230,7 @@ struct server_connection *server_setup_connection(struct event_context *ev, srv_conn->server_socket = server_socket; srv_conn->service = server_socket->service; srv_conn->socket = sock; + srv_conn->server_id = server_id; /* create a smb server context and add it to out event handling */ diff --git a/source4/smbd/service.h b/source4/smbd/service.h index 88618964ce..e9ef0bff06 100644 --- a/source4/smbd/service.h +++ b/source4/smbd/service.h @@ -93,6 +93,19 @@ struct server_service { struct server_context *srv_ctx; }; +/* the concept of whether two operations are on the same server + connection or different connections is an important one in SMB, especially + for locking and share modes. We will use a servid_t to distinguish different + connections + + this means that (for example) a unique open file is distinguished by the triple + of + servid_t server; + uint16 tid; + uint16 fnum; +*/ +typedef uint32_t servid_t; + struct server_connection { struct server_connection *next,*prev; void *private_data; @@ -104,6 +117,8 @@ struct server_connection { time_t idle_time; } event; + servid_t server_id; + struct socket_context *socket; struct server_socket *server_socket; |