enum brl_type lock_type)
{
int strict_locking = lp_strict_locking(fsp->conn->params);
- enum brl_flavour lock_flav = lp_posix_cifsu_locktype();
+ enum brl_flavour lock_flav = lp_posix_cifsu_locktype(fsp);
BOOL ret = True;
if (count == 0) {
Utility function called by locking requests.
****************************************************************************/
-struct byte_range_lock *do_lock(files_struct *fsp,
+struct byte_range_lock *do_lock(struct messaging_context *msg_ctx,
+ files_struct *fsp,
uint32 lock_pid,
SMB_BIG_UINT count,
SMB_BIG_UINT offset,
enum brl_type lock_type,
enum brl_flavour lock_flav,
BOOL blocking_lock,
- NTSTATUS *perr)
+ NTSTATUS *perr,
+ uint32 *plock_pid)
{
struct byte_range_lock *br_lck = NULL;
return NULL;
}
- *perr = brl_lock(br_lck,
+ *perr = brl_lock(msg_ctx,
+ br_lck,
lock_pid,
procid_self(),
offset,
count,
lock_type,
lock_flav,
- blocking_lock);
+ blocking_lock,
+ plock_pid);
+
+ /* blocking ie. pending, locks also count here,
+ * as this is an efficiency counter to avoid checking
+ * the lock db. on close. JRA. */
+
+ fsp->current_lock_count++;
return br_lck;
}
Utility function called by unlocking requests.
****************************************************************************/
-NTSTATUS do_unlock(files_struct *fsp,
+NTSTATUS do_unlock(struct messaging_context *msg_ctx,
+ files_struct *fsp,
uint32 lock_pid,
SMB_BIG_UINT count,
SMB_BIG_UINT offset,
return NT_STATUS_NO_MEMORY;
}
- ok = brl_unlock(br_lck,
+ ok = brl_unlock(msg_ctx,
+ br_lck,
lock_pid,
procid_self(),
offset,
return NT_STATUS_RANGE_NOT_LOCKED;
}
+ SMB_ASSERT(fsp->current_lock_count > 0);
+ fsp->current_lock_count--;
+
return NT_STATUS_OK;
}
return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
}
+ SMB_ASSERT(fsp->current_lock_count > 0);
+ fsp->current_lock_count--;
+
return NT_STATUS_OK;
}
Remove any locks on this fd. Called from file_close().
****************************************************************************/
-void locking_close_file(files_struct *fsp)
+void locking_close_file(struct messaging_context *msg_ctx,
+ files_struct *fsp)
{
struct byte_range_lock *br_lck;
return;
}
+ /* If we have not outstanding locks or pending
+ * locks then we don't need to look in the lock db.
+ */
+
+ if (fsp->current_lock_count == 0) {
+ return;
+ }
+
br_lck = brl_get_locks(NULL,fsp);
if (br_lck) {
cancel_pending_lock_requests_by_fid(fsp, br_lck);
- brl_close_fnum(br_lck);
+ brl_close_fnum(msg_ctx, br_lck);
TALLOC_FREE(br_lck);
}
}
return False;
}
+ /* Activate the per-hashchain freelist */
+ tdb_set_max_dead(tdb, 5);
+
if (!posix_locking_init(read_only))
return False;
memset(&key, '\0', sizeof(key));
key.dev = dev;
key.ino = inode;
- kbuf.dptr = (char *)&key;
+ kbuf.dptr = (uint8 *)&key;
kbuf.dsize = sizeof(key);
return kbuf;
}
slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: %s "
"pid = %s, share_access = 0x%x, private_options = 0x%x, "
"access_mask = 0x%x, mid = 0x%x, type= 0x%x, file_id = %lu, "
- "uid = %u, dev = 0x%x, inode = %.0f",
+ "uid = %u, flags = %u, dev = 0x%x, inode = %.0f",
num,
e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "",
procid_str_static(&e->pid),
e->share_access, e->private_options,
e->access_mask, e->op_mid, e->op_type, e->share_file_id,
- (unsigned int)e->uid, (unsigned int)e->dev, (double)e->inode );
+ (unsigned int)e->uid, (unsigned int)e->flags,
+ (unsigned int)e->dev, (double)e->inode );
return share_str;
}
}
lck->share_modes = (struct share_mode_entry *)
- talloc_memdup(lck, dbuf.dptr+sizeof(*data),
+ TALLOC_MEMDUP(lck, dbuf.dptr+sizeof(*data),
lck->num_share_modes *
sizeof(struct share_mode_entry));
/* Get any delete token. */
if (data->u.s.delete_token_size) {
- char *p = dbuf.dptr + sizeof(*data) +
+ uint8 *p = dbuf.dptr + sizeof(*data) +
(lck->num_share_modes *
sizeof(struct share_mode_entry));
}
/* Save off the associated service path and filename. */
- lck->servicepath = talloc_strdup(lck, dbuf.dptr + sizeof(*data) +
+ lck->servicepath = talloc_strdup(lck, (const char *)dbuf.dptr + sizeof(*data) +
(lck->num_share_modes *
sizeof(struct share_mode_entry)) +
data->u.s.delete_token_size );
smb_panic("talloc_strdup failed\n");
}
- lck->filename = talloc_strdup(lck, dbuf.dptr + sizeof(*data) +
+ lck->filename = talloc_strdup(lck, (const char *)dbuf.dptr + sizeof(*data) +
(lck->num_share_modes *
sizeof(struct share_mode_entry)) +
data->u.s.delete_token_size +
delete_token_size +
sp_len + 1 +
strlen(lck->filename) + 1;
- result.dptr = TALLOC_ARRAY(lck, char, result.dsize);
+ result.dptr = TALLOC_ARRAY(lck, uint8, result.dsize);
if (result.dptr == NULL) {
smb_panic("talloc failed\n");
/* Store any delete on close token. */
if (lck->delete_token) {
- char *p = result.dptr + offset;
+ uint8 *p = result.dptr + offset;
memcpy(p, &lck->delete_token->uid, sizeof(uid_t));
p += sizeof(uid_t);
offset = p - result.dptr;
}
- safe_strcpy(result.dptr + offset, lck->servicepath,
+ safe_strcpy((char *)result.dptr + offset, lck->servicepath,
result.dsize - offset - 1);
offset += sp_len + 1;
- safe_strcpy(result.dptr + offset, lck->filename,
+ safe_strcpy((char *)result.dptr + offset, lck->filename,
result.dsize - offset - 1);
if (DEBUGLEVEL >= 10) {
Based on an initial code idea from SATOH Fumiyasu <fumiya@samba.gr.jp>
********************************************************************/
-BOOL rename_share_filename(struct share_mode_lock *lck,
+BOOL rename_share_filename(struct messaging_context *msg_ctx,
+ struct share_mode_lock *lck,
const char *servicepath,
const char *newname)
{
size_t msg_len;
char *frm = NULL;
int i;
+ DATA_BLOB msg;
if (!lck) {
return False;
safe_strcpy(&frm[16], lck->servicepath, sp_len);
safe_strcpy(&frm[16 + sp_len + 1], lck->filename, fn_len);
+ msg = data_blob_const(frm, msg_len);
+
/* Send the messages. */
for (i=0; i<lck->num_share_modes; i++) {
struct share_mode_entry *se = &lck->share_modes[i];
(unsigned int)lck->dev, (double)lck->ino,
lck->servicepath, lck->filename ));
- message_send_pid(se->pid, MSG_SMB_FILE_RENAME,
- frm, msg_len, True);
+ messaging_send(msg_ctx, se->pid, MSG_SMB_FILE_RENAME, &msg);
}
return True;
}
-BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode)
+static int pull_delete_on_close_flag(TDB_DATA key, TDB_DATA dbuf,
+ void *private_data)
{
- BOOL result;
- struct share_mode_lock *lck = get_share_mode_lock(NULL, dev, inode, NULL, NULL);
- if (!lck) {
- return False;
+ BOOL *result = (BOOL *)private_data;
+ struct locking_data *data;
+
+ if (dbuf.dsize < sizeof(struct locking_data)) {
+ smb_panic("PANIC: parse_share_modes: buffer too short.\n");
}
- result = lck->delete_on_close;
- TALLOC_FREE(lck);
+
+ data = (struct locking_data *)dbuf.dptr;
+
+ *result = data->u.s.delete_on_close;
+ return 0;
+}
+
+BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode)
+{
+ TDB_DATA key = locking_key(dev, inode);
+ BOOL result = False;
+
+ tdb_parse_record(tdb, key, pull_delete_on_close_flag,
+ (void *)&result);
return result;
}
e->inode = fsp->inode;
e->share_file_id = fsp->fh->file_id;
e->uid = (uint32)uid;
+ e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0;
}
static void fill_deferred_open_entry(struct share_mode_entry *e,
e->dev = dev;
e->inode = ino;
e->uid = (uint32)-1;
+ e->flags = 0;
}
static void add_share_mode_entry(struct share_mode_lock *lck,
}
void set_share_mode(struct share_mode_lock *lck, files_struct *fsp,
- uid_t uid, uint16 mid, uint16 op_type)
+ uid_t uid, uint16 mid, uint16 op_type, BOOL initial_delete_on_close_allowed)
{
struct share_mode_entry entry;
fill_share_mode_entry(&entry, fsp, uid, mid, op_type);
+ if (initial_delete_on_close_allowed) {
+ entry.flags |= SHARE_MODE_ALLOW_INITIAL_DELETE_ON_CLOSE;
+ }
add_share_mode_entry(lck, &entry);
}
/* Don't allow delete on close for non-empty directories. */
if (fsp->is_directory) {
- long offset = 0;
- NTSTATUS status;
- SMB_STRUCT_STAT st;
- struct dptr_struct *dirptr;
- const char *name;
-
- status = dptr_create(fsp->conn,
- fsp->fsp_name,
- False,
- True,
- 0,
- "*",
- True,
- 0,
- &dirptr);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /* Read 3 entries. Ignore first 2 (they're . and .. ) */
- name = dptr_ReadDirName(dirptr, &offset, &st);
- if (!name) {
- dptr_CloseDir(dirptr);
- return NT_STATUS_ACCESS_DENIED;
- }
- name = dptr_ReadDirName(dirptr, &offset, &st);
- if (!name) {
- dptr_CloseDir(dirptr);
- return NT_STATUS_ACCESS_DENIED;
- }
- name = dptr_ReadDirName(dirptr, &offset, &st);
- dptr_CloseDir(dirptr);
- if (name) {
- DEBUG(10,("can_set_delete_on_close: got name %s - can't delete\n", name ));
- return NT_STATUS_DIRECTORY_NOT_EMPTY;
- }
+ return can_delete_directory(fsp->conn, fsp->fsp_name);
}
return NT_STATUS_OK;
}
+/****************************************************************************
+ Do we have an open file handle that created this entry ?
+****************************************************************************/
+
+BOOL can_set_initial_delete_on_close(const struct share_mode_lock *lck)
+{
+ int i;
+
+ for (i=0; i<lck->num_share_modes; i++) {
+ if (lck->share_modes[i].flags & SHARE_MODE_ALLOW_INITIAL_DELETE_ON_CLOSE) {
+ return True;
+ }
+ }
+ return False;
+}
+
/*************************************************************************
Return a talloced copy of a UNIX_USER_TOKEN. NULL on fail.
(Should this be in locking.c.... ?).
set_delete_on_close_lck(lck, delete_on_close, tok);
+ if (fsp->is_directory) {
+ send_stat_cache_delete_message(fsp->fsp_name);
+ }
+
TALLOC_FREE(lck);
return True;
}
+/****************************************************************************
+ Sets the allow initial delete on close flag for this share mode.
+****************************************************************************/
+
+BOOL set_allow_initial_delete_on_close(struct share_mode_lock *lck, files_struct *fsp, BOOL delete_on_close)
+{
+ struct share_mode_entry entry, *e;
+
+ /* Don't care about the pid owner being correct here - just a search. */
+ fill_share_mode_entry(&entry, fsp, (uid_t)-1, 0, NO_OPLOCK);
+
+ e = find_share_mode_entry(lck, &entry);
+ if (e == NULL) {
+ return False;
+ }
+
+ if (delete_on_close) {
+ e->flags |= SHARE_MODE_ALLOW_INITIAL_DELETE_ON_CLOSE;
+ } else {
+ e->flags &= ~SHARE_MODE_ALLOW_INITIAL_DELETE_ON_CLOSE;
+ }
+ lck->modified = True;
+ return True;
+}
+
struct forall_state {
void (*fn)(const struct share_mode_entry *entry,
const char *sharepath,
data = (struct locking_data *)dbuf.dptr;
shares = (struct share_mode_entry *)(dbuf.dptr + sizeof(*data));
- sharepath = dbuf.dptr + sizeof(*data) +
+ sharepath = (const char *)dbuf.dptr + sizeof(*data) +
data->u.s.num_share_mode_entries*sizeof(*shares) +
data->u.s.delete_token_size;
- fname = dbuf.dptr + sizeof(*data) +
+ fname = (const char *)dbuf.dptr + sizeof(*data) +
data->u.s.num_share_mode_entries*sizeof(*shares) +
data->u.s.delete_token_size +
strlen(sharepath) + 1;