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

r21092: Ok, that's the one that activates the Samba4 notify backend.

Now to clean up / fix lots of stuff.

Volker
This commit is contained in:
Volker Lendecke 2007-01-31 14:42:56 +00:00 committed by Gerald (Jerry) Carter
parent 686345b7ed
commit 9e7443fa14
5 changed files with 118 additions and 46 deletions

View File

@ -669,6 +669,7 @@ typedef struct connection_struct {
name_compare_entry *aio_write_behind_list; /* Per-share list of files to use aio write behind on. */
struct dfree_cached_info *dfree_info;
struct trans_state *pending_trans;
struct notify_context *notify_ctx;
} connection_struct;
struct current_user {

View File

@ -483,7 +483,10 @@ void file_free(files_struct *fsp)
fsp->fh->ref_count--;
}
TALLOC_FREE(fsp->notify);
if (fsp->notify) {
notify_remove(fsp->conn->notify_ctx, fsp);
TALLOC_FREE(fsp->notify);
}
bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
files_used--;

View File

@ -159,7 +159,8 @@ void change_notify_reply(const char *request_buf, uint32 max_param_count,
}
NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count,
uint32 filter, struct files_struct *fsp)
uint32 filter, BOOL recursive,
struct files_struct *fsp)
{
struct notify_change_request *request = NULL;
struct notify_mid_map *map = NULL;
@ -177,9 +178,7 @@ NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count,
request->max_param_count = max_param_count;
request->filter = filter;
request->fsp = fsp;
request->backend_data = cnotify->notify_add(NULL, smbd_event_context(),
fsp, &request->filter);
request->backend_data = NULL;
DLIST_ADD_END(fsp->notify->requests, request,
struct notify_change_request *);
@ -343,6 +342,18 @@ void notify_action(connection_struct *conn, const char *parent,
return;
}
{
char *fullpath;
if (asprintf(&fullpath, "%s/%s/%s", conn->connectpath,
parent, name) != -1) {
notify_trigger(conn->notify_ctx, action, filter,
fullpath);
SAFE_FREE(fullpath);
}
return;
}
if (!(lck = get_share_mode_lock(NULL, sbuf.st_dev, sbuf.st_ino,
NULL, NULL))) {
return;
@ -405,20 +416,21 @@ void notify_action(connection_struct *conn, const char *parent,
void notify_fname(connection_struct *conn, uint32 action, uint32 filter,
const char *path)
{
char *parent;
const char *name;
char *fullpath;
if (!parent_dirname_talloc(tmp_talloc_ctx(), path, &parent, &name)) {
if (asprintf(&fullpath, "%s/%s", conn->connectpath, path) == -1) {
DEBUG(0, ("asprintf failed\n"));
return;
}
notify_action(conn, parent, name, filter, action);
TALLOC_FREE(parent);
notify_trigger(conn->notify_ctx, action, filter, fullpath);
SAFE_FREE(fullpath);
}
void notify_fsp(files_struct *fsp, uint32 action, char *name)
void notify_fsp(files_struct *fsp, uint32 action, const char *name)
{
struct notify_change *change, *changes;
char *name2;
if (fsp->notify == NULL) {
/*
@ -427,35 +439,12 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name)
return;
}
if (fsp->notify->requests != NULL) {
/*
* Someone is waiting for the change, trigger the reply
* immediately.
*
* TODO: do we have to walk the lists of requests pending?
*/
struct notify_change_request *req = fsp->notify->requests;
struct notify_change onechange;
if (name == NULL) {
/*
* Catch-all change, possibly from notify_hash.c
*/
change_notify_reply(req->request_buf,
req->max_param_count,
-1, NULL);
if (!(name2 = talloc_strdup(fsp->notify, name))) {
DEBUG(0, ("talloc_strdup failed\n"));
return;
}
onechange.action = action;
onechange.name = name;
change_notify_reply(req->request_buf, req->max_param_count,
1, &onechange);
change_notify_remove_request(req);
return;
}
string_replace(name2, '/', '\\');
/*
* Someone has triggered a notify previously, queue the change for
@ -468,6 +457,7 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name)
* W2k3 seems to store at most 30 changes.
*/
TALLOC_FREE(fsp->notify->changes);
TALLOC_FREE(name2);
fsp->notify->num_changes = -1;
return;
}
@ -480,6 +470,7 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name)
fsp->notify, fsp->notify->changes,
struct notify_change, fsp->notify->num_changes+1))) {
DEBUG(0, ("talloc_realloc failed\n"));
TALLOC_FREE(name2);
return;
}
@ -487,14 +478,40 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name)
change = &(fsp->notify->changes[fsp->notify->num_changes]);
if (!(change->name = talloc_strdup(changes, name))) {
DEBUG(0, ("talloc_strdup failed\n"));
return;
}
change->name = talloc_move(changes, &name2);
change->action = action;
fsp->notify->num_changes += 1;
if (fsp->notify->requests == NULL) {
/*
* Nobody is waiting, so don't send anything. The ot
*/
return;
}
if (action == NOTIFY_ACTION_OLD_NAME) {
/*
* We have to send the two rename events in one reply. So hold
* the first part back.
*/
return;
}
/*
* Someone is waiting for the change, trigger the reply immediately.
*
* TODO: do we have to walk the lists of requests pending?
*/
change_notify_reply(fsp->notify->requests->request_buf,
fsp->notify->requests->max_param_count,
fsp->notify->num_changes,
fsp->notify->changes);
change_notify_remove_request(fsp->notify->requests);
TALLOC_FREE(fsp->notify->changes);
fsp->notify->num_changes = 0;
}
static void notify_message_callback(int msgtype, struct process_id pid,

View File

@ -1787,6 +1787,13 @@ int reply_ntrename(connection_struct *conn,
don't allow a directory to be opened.
****************************************************************************/
static void notify_callback(void *private_data, const struct notify_event *e)
{
files_struct *fsp = (files_struct *)private_data;
DEBUG(10, ("notify_callback called for %s\n", fsp->fsp_name));
notify_fsp(fsp, e->action, e->path);
}
static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
char *outbuf, int length,
int bufsize,
@ -1801,6 +1808,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
files_struct *fsp;
uint32 filter;
NTSTATUS status;
BOOL recursive;
if(setup_count < 6) {
return ERROR_DOS(ERRDOS,ERRbadfunc);
@ -1808,6 +1816,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
fsp = file_fsp((char *)setup,4);
filter = IVAL(setup, 0);
recursive = (SVAL(setup, 6) != 0) ? True : False;
DEBUG(3,("call_nt_transact_notify_change\n"));
@ -1815,18 +1824,55 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
return ERROR_DOS(ERRDOS,ERRbadfid);
}
DEBUG(3,("call_nt_transact_notify_change: notify change called on "
"directory name = %s\n", fsp->fsp_name ));
{
char *filter_string;
if (!(filter_string = notify_filter_string(NULL, filter))) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
DEBUG(3,("call_nt_transact_notify_change: notify change "
"called on %s, filter = %s, recursive = %d\n",
fsp->fsp_name, filter_string, recursive));
TALLOC_FREE(filter_string);
}
if((!fsp->is_directory) || (conn != fsp->conn)) {
return ERROR_DOS(ERRDOS,ERRbadfid);
}
if (fsp->notify == NULL) {
char *fullpath;
struct notify_entry e;
if (!(fsp->notify = TALLOC_ZERO_P(
NULL, struct notify_change_buf))) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
if (asprintf(&fullpath, "%s/%s", fsp->conn->connectpath,
fsp->fsp_name) == -1) {
DEBUG(0, ("asprintf failed\n"));
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
e.path = fullpath;
e.filter = filter;
e.subdir_filter = 0;
if (recursive) {
e.subdir_filter = filter;
}
status = notify_add(fsp->conn->notify_ctx, &e, notify_callback,
fsp);
SAFE_FREE(fullpath);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("notify_add returned %s\n",
nt_errstr(status)));
return ERROR_NT(status);
}
}
if (fsp->notify->num_changes != 0) {
@ -1840,8 +1886,6 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
* here.
*/
SMB_ASSERT(fsp->notify->requests == NULL);
change_notify_reply(inbuf, max_param_count,
fsp->notify->num_changes,
fsp->notify->changes);
@ -1861,7 +1905,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
*/
status = change_notify_add_request(inbuf, max_param_count, filter,
fsp);
recursive, fsp);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}

View File

@ -946,6 +946,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
set_conn_connectpath(conn,s);
}
if ((!conn->printer) && (!conn->ipc)) {
conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
smbd_messaging_context(),
smbd_event_context(),
conn->params);
}
/* ROOT Activities: */
/* check number of connections */
if (!claim_connection(conn,