/*
Unix SMB / CIFS implementation .
change notify handling
Copyright ( C ) Andrew Tridgell 2000
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
Copyright ( C ) Jeremy Allison 1994 - 1998
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 0213 9 , USA .
*/
# include "includes.h"
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
static struct cnotify_fns * cnotify ;
/****************************************************************************
This is the structure to queue to implement NT change
notify . It consists of smb_size bytes stored from the
transact command ( to keep the mid , tid etc around ) .
Plus the fid to examine and notify private data .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
struct change_notify {
struct change_notify * next , * prev ;
files_struct * fsp ;
uint32 flags ;
2006-12-28 21:50:31 +00:00
uint32 max_param_count ;
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
char request_buf [ smb_size ] ;
void * change_data ;
} ;
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
static struct change_notify * change_notify_list ;
2006-12-28 21:50:31 +00:00
static BOOL notify_marshall_changes ( struct notify_changes * changes ,
prs_struct * ps )
{
int i ;
UNISTR uni_name ;
for ( i = 0 ; i < changes - > num_changes ; i + + ) {
struct notify_change * c = & changes - > changes [ i ] ;
size_t namelen ;
uint32 u32_tmp ; /* Temp arg to prs_uint32 to avoid
* signed / unsigned issues */
namelen = convert_string_allocate (
NULL , CH_UNIX , CH_UTF16LE , c - > name , strlen ( c - > name ) + 1 ,
& uni_name . buffer , True ) ;
if ( ( namelen = = - 1 ) | | ( uni_name . buffer = = NULL ) ) {
goto fail ;
}
namelen - = 2 ; /* Dump NULL termination */
/*
* Offset to next entry , only if there is one
*/
u32_tmp = ( i = = changes - > num_changes - 1 ) ? 0 : namelen + 12 ;
if ( ! prs_uint32 ( " offset " , ps , 1 , & u32_tmp ) ) goto fail ;
u32_tmp = c - > action ;
if ( ! prs_uint32 ( " action " , ps , 1 , & u32_tmp ) ) goto fail ;
u32_tmp = namelen ;
if ( ! prs_uint32 ( " namelen " , ps , 1 , & u32_tmp ) ) goto fail ;
if ( ! prs_unistr ( " name " , ps , 1 , & uni_name ) ) goto fail ;
/*
* Not NULL terminated , decrease by the 2 UCS2 \ 0 chars
*/
prs_set_offset ( ps , prs_offset ( ps ) - 2 ) ;
SAFE_FREE ( uni_name . buffer ) ;
}
return True ;
fail :
SAFE_FREE ( uni_name . buffer ) ;
return False ;
}
/****************************************************************************
Setup the common parts of the return packet and send it .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-12-31 10:16:03 +00:00
static void change_notify_reply_packet ( const char * request_buf ,
2006-12-28 21:50:31 +00:00
NTSTATUS error_code )
{
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
char outbuf [ smb_size + 38 ] ;
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
memset ( outbuf , ' \0 ' , sizeof ( outbuf ) ) ;
2006-12-31 10:16:03 +00:00
construct_reply_common ( request_buf , outbuf ) ;
ERROR_NT ( error_code ) ;
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
/*
* Seems NT needs a transact command with an error code
* in it . This is a longer packet than a simple error .
*/
set_message ( outbuf , 18 , 0 , False ) ;
2005-06-27 22:53:56 +00:00
show_msg ( outbuf ) ;
if ( ! send_smb ( smbd_server_fd ( ) , outbuf ) )
2006-12-18 04:25:21 +00:00
exit_server_cleanly ( " change_notify_reply_packet: send_smb failed. " ) ;
}
2006-12-31 10:16:03 +00:00
void change_notify_reply ( const char * request_buf , uint32 max_param_count ,
files_struct * fsp )
2006-12-28 21:50:31 +00:00
{
char * outbuf = NULL ;
prs_struct ps ;
2006-12-31 10:16:03 +00:00
size_t buflen = smb_size + 38 + max_param_count ;
2006-12-28 21:50:31 +00:00
if ( ! prs_init ( & ps , 0 , NULL , False )
2006-12-31 10:16:03 +00:00
| | ! notify_marshall_changes ( fsp - > notify , & ps ) ) {
change_notify_reply_packet ( request_buf , NT_STATUS_NO_MEMORY ) ;
2006-12-28 21:50:31 +00:00
goto done ;
}
2006-12-31 10:16:03 +00:00
if ( prs_offset ( & ps ) > max_param_count ) {
2006-12-28 21:50:31 +00:00
/*
* We exceed what the client is willing to accept . Send
* nothing .
*/
2006-12-31 10:16:03 +00:00
change_notify_reply_packet ( request_buf , NT_STATUS_OK ) ;
2006-12-28 21:50:31 +00:00
goto done ;
}
if ( ! ( outbuf = SMB_MALLOC_ARRAY ( char , buflen ) ) ) {
2006-12-31 10:16:03 +00:00
change_notify_reply_packet ( request_buf , NT_STATUS_NO_MEMORY ) ;
2006-12-28 21:50:31 +00:00
goto done ;
}
2006-12-31 10:16:03 +00:00
construct_reply_common ( request_buf , outbuf ) ;
2006-12-28 21:50:31 +00:00
if ( send_nt_replies ( outbuf , buflen , NT_STATUS_OK , prs_data_p ( & ps ) ,
prs_offset ( & ps ) , NULL , 0 ) = = - 1 ) {
exit_server ( " change_notify_reply_packet: send_smb failed. " ) ;
}
done :
SAFE_FREE ( outbuf ) ;
prs_mem_free ( & ps ) ;
2006-12-31 10:16:03 +00:00
fsp - > notify - > num_changes = 0 ;
TALLOC_FREE ( fsp - > notify - > changes ) ;
2006-12-28 21:50:31 +00:00
}
/****************************************************************************
Remove an entry from the list and free it , also closing any
directory handle if necessary .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
static void change_notify_remove ( struct change_notify * cnbp )
{
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
cnotify - > remove_notify ( cnbp - > change_data ) ;
DLIST_REMOVE ( change_notify_list , cnbp ) ;
ZERO_STRUCTP ( cnbp ) ;
SAFE_FREE ( cnbp ) ;
}
/****************************************************************************
Delete entries by fnum from the change notify pending queue .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-10-27 23:30:25 +00:00
void remove_pending_change_notify_requests_by_fid ( files_struct * fsp , NTSTATUS status )
{
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
struct change_notify * cnbp , * next ;
for ( cnbp = change_notify_list ; cnbp ; cnbp = next ) {
next = cnbp - > next ;
if ( cnbp - > fsp - > fnum = = fsp - > fnum ) {
2006-12-31 10:16:03 +00:00
change_notify_reply_packet ( cnbp - > request_buf , status ) ;
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
change_notify_remove ( cnbp ) ;
}
}
}
/****************************************************************************
Delete entries by mid from the change notify pending queue . Always send reply .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void remove_pending_change_notify_requests_by_mid ( int mid )
{
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
struct change_notify * cnbp , * next ;
for ( cnbp = change_notify_list ; cnbp ; cnbp = next ) {
next = cnbp - > next ;
if ( SVAL ( cnbp - > request_buf , smb_mid ) = = mid ) {
2006-12-31 10:16:03 +00:00
change_notify_reply_packet ( cnbp - > request_buf ,
NT_STATUS_CANCELLED ) ;
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
change_notify_remove ( cnbp ) ;
}
}
}
/****************************************************************************
Delete entries by filename and cnum from the change notify pending queue .
Always send reply .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-10-27 23:30:25 +00:00
void remove_pending_change_notify_requests_by_filename ( files_struct * fsp , NTSTATUS status )
{
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
struct change_notify * cnbp , * next ;
for ( cnbp = change_notify_list ; cnbp ; cnbp = next ) {
next = cnbp - > next ;
/*
* We know it refers to the same directory if the connection number and
* the filename are identical .
*/
if ( ( cnbp - > fsp - > conn = = fsp - > conn ) & & strequal ( cnbp - > fsp - > fsp_name , fsp - > fsp_name ) ) {
2006-12-31 10:16:03 +00:00
change_notify_reply_packet ( cnbp - > request_buf , status ) ;
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
change_notify_remove ( cnbp ) ;
}
}
}
/****************************************************************************
2006-05-12 23:10:01 +00:00
Set the current change notify timeout to the lowest value across all service
values .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void set_change_notify_timeout ( int val )
{
if ( val > 0 ) {
cnotify - > select_time = MIN ( cnotify - > select_time , val ) ;
}
}
/****************************************************************************
Longest time to sleep for before doing a change notify scan .
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int change_notify_timeout ( void )
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
{
return cnotify - > select_time ;
}
/****************************************************************************
Process the change notify queue . Note that this is only called as root .
Returns True if there are still outstanding change notify requests on the
queue .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL process_pending_change_notify_queue ( time_t t )
{
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
struct change_notify * cnbp , * next ;
uint16 vuid ;
for ( cnbp = change_notify_list ; cnbp ; cnbp = next ) {
next = cnbp - > next ;
vuid = ( lp_security ( ) = = SEC_SHARE ) ? UID_FIELD_INVALID : SVAL ( cnbp - > request_buf , smb_uid ) ;
2006-12-31 10:16:03 +00:00
if ( cnbp - > fsp - > notify - > num_changes ! = 0 ) {
DEBUG ( 10 , ( " process_pending_change_notify_queue: %s "
" has %d changes! \n " , cnbp - > fsp - > fsp_name ,
cnbp - > fsp - > notify - > num_changes ) ) ;
change_notify_reply ( cnbp - > request_buf ,
cnbp - > max_param_count ,
cnbp - > fsp ) ;
change_notify_remove ( cnbp ) ;
continue ;
}
if ( cnotify - > check_notify ( cnbp - > fsp - > conn , vuid ,
cnbp - > fsp - > fsp_name , cnbp - > flags ,
cnbp - > change_data , t ) ) {
2006-12-28 21:50:31 +00:00
DEBUG ( 10 , ( " process_pending_change_notify_queue: dir "
" %s changed ! \n " , cnbp - > fsp - > fsp_name ) ) ;
2006-12-31 10:16:03 +00:00
change_notify_reply ( cnbp - > request_buf ,
cnbp - > max_param_count ,
cnbp - > fsp ) ;
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
change_notify_remove ( cnbp ) ;
}
}
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
return ( change_notify_list ! = NULL ) ;
}
/****************************************************************************
Now queue an entry on the notify change list .
We only need to save smb_size bytes from this incoming packet
as we will always by returning a ' read the directory yourself '
error .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-12-28 21:50:31 +00:00
BOOL change_notify_set ( char * inbuf , files_struct * fsp , connection_struct * conn ,
uint32 flags , uint32 max_param_count )
{
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
struct change_notify * cnbp ;
2004-12-07 18:25:53 +00:00
if ( ( cnbp = SMB_MALLOC_P ( struct change_notify ) ) = = NULL ) {
DEBUG ( 0 , ( " change_notify_set: malloc fail ! \n " ) ) ;
2006-12-28 21:50:31 +00:00
return False ;
}
ZERO_STRUCTP ( cnbp ) ;
memcpy ( cnbp - > request_buf , inbuf , smb_size ) ;
cnbp - > fsp = fsp ;
cnbp - > flags = flags ;
2006-12-28 21:50:31 +00:00
cnbp - > max_param_count = max_param_count ;
cnbp - > change_data = cnotify - > register_notify ( conn , fsp - > fsp_name ,
flags ) ;
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
if ( ! cnbp - > change_data ) {
SAFE_FREE ( cnbp ) ;
return False ;
}
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
DLIST_ADD ( change_notify_list , cnbp ) ;
/* Push the MID of this packet on the signing queue. */
srv_defer_sign_response ( SVAL ( inbuf , smb_mid ) ) ;
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
return True ;
}
2006-02-13 04:07:15 +00:00
int change_notify_fd ( void )
{
if ( cnotify ) {
return cnotify - > notification_fd ;
}
return - 1 ;
}
2006-12-28 21:50:31 +00:00
/* notify message definition
Offset Data length .
0 SMB_DEV_T dev 8
8 SMB_INO_T inode 8
16 uint32 action 4
20. . name
*/
# define MSG_NOTIFY_MESSAGE_SIZE 21 /* Includes at least the '\0' terminator */
struct notify_message {
SMB_DEV_T dev ;
SMB_INO_T inode ;
uint32_t action ;
char * name ;
} ;
static DATA_BLOB notify_message_to_buf ( const struct notify_message * msg )
{
DATA_BLOB result ;
size_t len ;
len = strlen ( msg - > name ) ;
result = data_blob ( NULL , MSG_NOTIFY_MESSAGE_SIZE + len ) ;
if ( ! result . data ) {
return result ;
}
SDEV_T_VAL ( result . data , 0 , msg - > dev ) ;
SINO_T_VAL ( result . data , 8 , msg - > inode ) ;
SIVAL ( result . data , 16 , msg - > action ) ;
memcpy ( result . data + 20 , msg - > name , len + 1 ) ;
return result ;
}
static BOOL buf_to_notify_message ( void * buf , size_t len ,
struct notify_message * msg )
{
if ( len < MSG_NOTIFY_MESSAGE_SIZE ) {
DEBUG ( 0 , ( " Got invalid notify message of len %d \n " , len ) ) ;
return False ;
}
msg - > dev = DEV_T_VAL ( buf , 0 ) ;
msg - > inode = INO_T_VAL ( buf , 8 ) ;
msg - > action = IVAL ( buf , 16 ) ;
msg - > name = ( ( char * ) buf ) + 20 ;
return True ;
}
void notify_action ( connection_struct * conn , const char * parent ,
const char * name , uint32_t action )
{
struct share_mode_lock * lck ;
SMB_STRUCT_STAT sbuf ;
int i ;
struct notify_message msg ;
DATA_BLOB blob ;
struct process_id * pids ;
int num_pids ;
2006-12-31 10:16:03 +00:00
DEBUG ( 10 , ( " notify_action: parent=%s, name=%s, action=%u \n " ,
parent , name , ( unsigned ) action ) ) ;
2006-12-28 21:50:31 +00:00
if ( SMB_VFS_STAT ( conn , parent , & sbuf ) ! = 0 ) {
/*
* Not 100 % critical , ignore failure
*/
return ;
}
if ( ! ( lck = get_share_mode_lock ( NULL , sbuf . st_dev , sbuf . st_ino ,
NULL , NULL ) ) ) {
return ;
}
msg . dev = sbuf . st_dev ;
msg . inode = sbuf . st_ino ;
msg . action = action ;
msg . name = CONST_DISCARD ( char * , name ) ;
blob = notify_message_to_buf ( & msg ) ;
if ( blob . data = = NULL ) {
DEBUG ( 0 , ( " notify_message_to_buf failed \n " ) ) ;
return ;
}
pids = NULL ;
num_pids = 0 ;
become_root_uid_only ( ) ;
for ( i = 0 ; i < lck - > num_share_modes ; i + + ) {
struct share_mode_entry * e = & lck - > share_modes [ i ] ;
int j ;
struct process_id * tmp ;
for ( j = 0 ; j < num_pids ; j + + ) {
if ( procid_equal ( & e - > pid , & pids [ j ] ) ) {
break ;
}
}
if ( j < num_pids ) {
/*
* Already sent to that process , skip it
*/
continue ;
}
message_send_pid ( lck - > share_modes [ i ] . pid , MSG_SMB_NOTIFY ,
blob . data , blob . length , True ) ;
if ( ! ( tmp = TALLOC_REALLOC_ARRAY ( lck , pids , struct process_id ,
num_pids + 1 ) ) ) {
DEBUG ( 0 , ( " realloc failed \n " ) ) ;
break ;
}
pids = tmp ;
pids [ num_pids ] = e - > pid ;
num_pids + = 1 ;
}
unbecome_root_uid_only ( ) ;
data_blob_free ( & blob ) ;
TALLOC_FREE ( lck ) ;
}
2006-12-31 10:16:03 +00:00
static void notify_message_callback ( int msgtype , struct process_id pid ,
void * buf , size_t len )
2006-12-28 21:50:31 +00:00
{
struct notify_message msg ;
files_struct * fsp ;
struct notify_change * changes , * change ;
2006-12-31 10:16:03 +00:00
struct change_notify * cnbp ;
2006-12-28 21:50:31 +00:00
if ( ! buf_to_notify_message ( buf , len , & msg ) ) {
return ;
}
DEBUG ( 10 , ( " Received notify_message for 0x%x/%.0f: %d \n " ,
( unsigned ) msg . dev , ( double ) msg . inode , msg . action ) ) ;
2006-12-31 10:16:03 +00:00
fsp = NULL ;
for ( cnbp = change_notify_list ; cnbp ! = NULL ; cnbp = cnbp - > next ) {
if ( ( cnbp - > fsp - > dev = = msg . dev )
& & ( cnbp - > fsp - > inode = = msg . inode ) ) {
break ;
}
}
if ( cnbp ! = NULL ) {
DEBUG ( 10 , ( " Found pending change notify for %s \n " ,
cnbp - > fsp - > fsp_name ) ) ;
fsp = cnbp - > fsp ;
SMB_ASSERT ( fsp - > notify - > num_changes = = 0 ) ;
}
if ( ( fsp = = NULL )
& & ! ( fsp = file_find_dir_lowest_id ( msg . dev , msg . inode ) ) ) {
2006-12-28 21:50:31 +00:00
DEBUG ( 10 , ( " notify_message: did not find fsp \n " ) ) ;
return ;
}
if ( ! ( changes = TALLOC_REALLOC_ARRAY (
fsp - > notify , fsp - > notify - > changes ,
struct notify_change , fsp - > notify - > num_changes + 1 ) ) ) {
DEBUG ( 0 , ( " talloc_realloc failed \n " ) ) ;
return ;
}
fsp - > notify - > changes = changes ;
change = & ( fsp - > notify - > changes [ fsp - > notify - > num_changes ] ) ;
if ( ! ( change - > name = talloc_strdup ( changes , msg . name ) ) ) {
DEBUG ( 0 , ( " talloc_strdup failed \n " ) ) ;
return ;
}
change - > action = msg . action ;
fsp - > notify - > num_changes + = 1 ;
2006-12-31 10:16:03 +00:00
if ( cnbp ! = NULL ) {
/*
* Respond directly , we have a someone waiting for this change
*/
DEBUG ( 10 , ( " Found pending cn for %s, responding directly \n " ,
cnbp - > fsp - > fsp_name ) ) ;
change_notify_reply ( cnbp - > request_buf , cnbp - > max_param_count ,
cnbp - > fsp ) ;
change_notify_remove ( cnbp ) ;
return ;
}
2006-12-28 21:50:31 +00:00
}
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
/****************************************************************************
Initialise the change notify subsystem .
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
BOOL init_change_notify ( void )
{
2006-01-19 00:30:16 +00:00
cnotify = NULL ;
# if HAVE_KERNEL_CHANGE_NOTIFY
2006-01-19 00:30:16 +00:00
if ( cnotify = = NULL & & lp_kernel_change_notify ( ) )
cnotify = kernel_notify_init ( ) ;
2006-01-19 00:30:16 +00:00
# endif
# if HAVE_FAM_CHANGE_NOTIFY
if ( cnotify = = NULL & & lp_fam_change_notify ( ) )
cnotify = fam_notify_init ( ) ;
# endif
if ( ! cnotify ) cnotify = hash_notify_init ( ) ;
totally rewrote the async signal, notification and oplock notification
handling in Samba. This was needed due to several limitations and
races in the previous code - as a side effect the new code is much
cleaner :)
in summary:
- changed sys_select() to avoid a signal/select race condition. It is a
rare race but once we have signals doing notification and oplocks it
is important.
- changed our main processing loop to take advantage of the new
sys_select semantics
- split the notify code into implementaion dependent and general
parts. Added the following structure that defines an implementation:
struct cnotify_fns {
void * (*register_notify)(connection_struct *conn, char *path, uint32 flags);
BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t);
void (*remove_notify)(void *data);
};
then I wrote two implementations, one using hash/poll (like our old
code) and the other using the new Linux kernel change notify. It
should be easy to add other change notify implementations by creating
a sructure of the above type.
- fixed a bug in change notify where we were returning the wrong error
code.
- rewrote the core change notify code to be much simpler
- moved to real-time signals for leases and change notify
Amazingly, it all seems to work. I was very surprised!
-
if ( ! cnotify ) {
DEBUG ( 0 , ( " Failed to init change notify system \n " ) ) ;
return False ;
}
2006-12-31 10:16:03 +00:00
message_register ( MSG_SMB_NOTIFY , notify_message_callback ) ;
2006-12-28 21:50:31 +00:00
return True ;
}