svn commit: samba r20433 - in branches/SAMBA_3_0/source/smbd: .

vlendec at samba.org vlendec at samba.org
Sun Dec 31 10:16:04 GMT 2006


Author: vlendec
Date: 2006-12-31 10:16:03 +0000 (Sun, 31 Dec 2006)
New Revision: 20433

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=20433

Log:
Work in progress: Survive more of RAW-NOTIFY.

call_nt_transact_notify_change() is now sync if there are changes around.

A notify_message does a direct reply from within the message, so
process_pending_change_notify_queue is not needed anymore for samba-generated
events. Next step is to restructure the kernel-mechanisms to generate
messages.

Volker

Modified:
   branches/SAMBA_3_0/source/smbd/notify.c
   branches/SAMBA_3_0/source/smbd/notify_hash.c
   branches/SAMBA_3_0/source/smbd/nttrans.c
   branches/SAMBA_3_0/source/smbd/open.c
   branches/SAMBA_3_0/source/smbd/reply.c


Changeset:
Modified: branches/SAMBA_3_0/source/smbd/notify.c
===================================================================
--- branches/SAMBA_3_0/source/smbd/notify.c	2006-12-31 10:08:52 UTC (rev 20432)
+++ branches/SAMBA_3_0/source/smbd/notify.c	2006-12-31 10:16:03 UTC (rev 20433)
@@ -33,7 +33,6 @@
 struct change_notify {
 	struct change_notify *next, *prev;
 	files_struct *fsp;
-	connection_struct *conn;
 	uint32 flags;
 	uint32 max_param_count;
 	char request_buf[smb_size];
@@ -97,13 +96,13 @@
  Setup the common parts of the return packet and send it.
 *****************************************************************************/
 
-static void change_notify_reply_packet(struct change_notify *notify,
+static void change_notify_reply_packet(const char *request_buf,
 				       NTSTATUS error_code)
 {
 	char outbuf[smb_size+38];
 
 	memset(outbuf, '\0', sizeof(outbuf));
-	construct_reply_common(notify->request_buf, outbuf);
+	construct_reply_common(request_buf, outbuf);
 
 	ERROR_NT(error_code);
 
@@ -118,34 +117,34 @@
 		exit_server_cleanly("change_notify_reply_packet: send_smb failed.");
 }
 
-static void change_notify_reply(struct change_notify *notify)
+void change_notify_reply(const char *request_buf, uint32 max_param_count,
+			 files_struct *fsp)
 {
 	char *outbuf = NULL;
 	prs_struct ps;
-	size_t buflen = smb_size+38+notify->max_param_count;
+	size_t buflen = smb_size+38+max_param_count;
 
 	if (!prs_init(&ps, 0, NULL, False)
-	    || !notify_marshall_changes(notify->fsp->notify, &ps)) {
-		change_notify_reply_packet(notify, NT_STATUS_NO_MEMORY);
+	    || !notify_marshall_changes(fsp->notify, &ps)) {
+		change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY);
 		goto done;
 	}
 
-	if (prs_offset(&ps) > notify->max_param_count) {
+	if (prs_offset(&ps) > max_param_count) {
 		/*
 		 * We exceed what the client is willing to accept. Send
 		 * nothing.
 		 */
-		change_notify_reply_packet(notify, NT_STATUS_OK);
+		change_notify_reply_packet(request_buf, NT_STATUS_OK);
 		goto done;
 	}
 
 	if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) {
-		change_notify_reply_packet(notify, NT_STATUS_NO_MEMORY);
+		change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY);
 		goto done;
 	}
 
-	memset(outbuf, '\0', sizeof(outbuf));
-	construct_reply_common(notify->request_buf, outbuf);
+	construct_reply_common(request_buf, outbuf);
 
 	if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps),
 			    prs_offset(&ps), NULL, 0) == -1) {
@@ -155,8 +154,8 @@
  done:
 	SAFE_FREE(outbuf);
 	prs_mem_free(&ps);
-	notify->fsp->notify->num_changes = 0;
-	TALLOC_FREE(notify->fsp->notify->changes);
+	fsp->notify->num_changes = 0;
+	TALLOC_FREE(fsp->notify->changes);
 }
 
 /****************************************************************************
@@ -183,7 +182,7 @@
 	for (cnbp=change_notify_list; cnbp; cnbp=next) {
 		next=cnbp->next;
 		if (cnbp->fsp->fnum == fsp->fnum) {
-			change_notify_reply_packet(cnbp, status);
+			change_notify_reply_packet(cnbp->request_buf, status);
 			change_notify_remove(cnbp);
 		}
 	}
@@ -200,7 +199,8 @@
 	for (cnbp=change_notify_list; cnbp; cnbp=next) {
 		next=cnbp->next;
 		if(SVAL(cnbp->request_buf,smb_mid) == mid) {
-			change_notify_reply_packet(cnbp, NT_STATUS_CANCELLED);
+			change_notify_reply_packet(cnbp->request_buf,
+						   NT_STATUS_CANCELLED);
 			change_notify_remove(cnbp);
 		}
 	}
@@ -222,7 +222,7 @@
 		 * the filename are identical.
 		 */
 		if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) {
-			change_notify_reply_packet(cnbp, status);
+			change_notify_reply_packet(cnbp->request_buf, status);
 			change_notify_remove(cnbp);
 		}
 	}
@@ -265,13 +265,25 @@
 
 		vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid);
 
-		if ((cnbp->fsp->notify->num_changes != 0)
-		    || cnotify->check_notify(cnbp->conn, vuid,
-					     cnbp->fsp->fsp_name, cnbp->flags,
-					     cnbp->change_data, t)) {
+		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)) {
 			DEBUG(10,("process_pending_change_notify_queue: dir "
 				  "%s changed !\n", cnbp->fsp->fsp_name ));
-			change_notify_reply(cnbp);
+			change_notify_reply(cnbp->request_buf,
+					    cnbp->max_param_count,
+					    cnbp->fsp);
 			change_notify_remove(cnbp);
 		}
 	}
@@ -300,7 +312,6 @@
 
 	memcpy(cnbp->request_buf, inbuf, smb_size);
 	cnbp->fsp = fsp;
-	cnbp->conn = conn;
 	cnbp->flags = flags;
 	cnbp->max_param_count = max_param_count;
 	cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name,
@@ -393,6 +404,9 @@
 	struct process_id *pids;
 	int num_pids;
 
+	DEBUG(10, ("notify_action: parent=%s, name=%s, action=%u\n",
+		   parent, name, (unsigned)action));
+
 	if (SMB_VFS_STAT(conn, parent, &sbuf) != 0) {
 		/*
 		 * Not 100% critical, ignore failure
@@ -458,12 +472,13 @@
 	TALLOC_FREE(lck);
 }
 
-static void notify_message(int msgtype, struct process_id pid,
-			   void *buf, size_t len)
+static void notify_message_callback(int msgtype, struct process_id pid,
+				    void *buf, size_t len)
 {
 	struct notify_message msg;
 	files_struct *fsp;
 	struct notify_change *changes, *change;
+	struct change_notify *cnbp;
 
 	if (!buf_to_notify_message(buf, len, &msg)) {
 		return;
@@ -472,7 +487,24 @@
 	DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n",
 		   (unsigned)msg.dev, (double)msg.inode, msg.action));
 
-	if (!(fsp = file_find_dir_lowest_id(msg.dev, msg.inode))) {
+	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))) {
 		DEBUG(10, ("notify_message: did not find fsp\n"));
 		return;
 	}
@@ -494,6 +526,18 @@
 	}
 	change->action = msg.action;
 	fsp->notify->num_changes += 1;
+
+	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;
+	}
 }
 
 /****************************************************************************
@@ -519,7 +563,7 @@
 		return False;
 	}
 
-	message_register(MSG_SMB_NOTIFY, notify_message);
+	message_register(MSG_SMB_NOTIFY, notify_message_callback);
 
 	return True;
 }

Modified: branches/SAMBA_3_0/source/smbd/notify_hash.c
===================================================================
--- branches/SAMBA_3_0/source/smbd/notify_hash.c	2006-12-31 10:08:52 UTC (rev 20432)
+++ branches/SAMBA_3_0/source/smbd/notify_hash.c	2006-12-31 10:16:03 UTC (rev 20433)
@@ -186,6 +186,9 @@
 	struct change_data data2;
 	int cnto = lp_change_notify_timeout(SNUM(conn));
 
+	DEBUG(10, ("hash_change_notify called for path %s\n", path));
+	return False;
+
 	if (t && cnto <= 0) {
 		/* Change notify turned off on this share.
 		 * Only scan when (t==0) - we think something changed. */

Modified: branches/SAMBA_3_0/source/smbd/nttrans.c
===================================================================
--- branches/SAMBA_3_0/source/smbd/nttrans.c	2006-12-31 10:08:52 UTC (rev 20432)
+++ branches/SAMBA_3_0/source/smbd/nttrans.c	2006-12-31 10:16:03 UTC (rev 20433)
@@ -1847,6 +1847,17 @@
 		return ERROR_DOS(ERRDOS,ERRbadfid);
 	}
 
+	if (fsp->notify->num_changes > 0) {
+
+		change_notify_reply(inbuf, max_param_count, fsp);
+
+		/*
+		 * change_notify_reply() above has independently sent its
+		 * results
+		 */
+		return -1;
+	}
+
 	if (!change_notify_set(inbuf, fsp, conn, flags, max_param_count)) {
 		return(UNIXERROR(ERRDOS,ERRbadfid));
 	}

Modified: branches/SAMBA_3_0/source/smbd/open.c
===================================================================
--- branches/SAMBA_3_0/source/smbd/open.c	2006-12-31 10:08:52 UTC (rev 20432)
+++ branches/SAMBA_3_0/source/smbd/open.c	2006-12-31 10:16:03 UTC (rev 20433)
@@ -198,7 +198,8 @@
 static NTSTATUS open_file(files_struct *fsp,
 			  connection_struct *conn,
 			  const char *parent_dir,
-			  const char *fname,
+			  const char *name,
+			  const char *path,
 			  SMB_STRUCT_STAT *psbuf,
 			  int flags,
 			  mode_t unx_mode,
@@ -227,7 +228,7 @@
 	if (!CAN_WRITE(conn)) {
 		/* It's a read-only share - fail if we wanted to write. */
 		if(accmode != O_RDONLY) {
-			DEBUG(3,("Permission denied opening %s\n",fname));
+			DEBUG(3,("Permission denied opening %s\n", path));
 			return NT_STATUS_ACCESS_DENIED;
 		} else if(flags & O_CREAT) {
 			/* We don't want to write - but we must make sure that
@@ -253,7 +254,7 @@
 
 	if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) {
 		DEBUG(10,("open_file: truncate requested on read-only open "
-			  "for file %s\n",fname ));
+			  "for file %s\n", path));
 		local_flags = (flags & ~O_ACCMODE)|O_RDWR;
 	}
 
@@ -282,15 +283,15 @@
 
 		/* Don't create files with Microsoft wildcard characters. */
 		if ((local_flags & O_CREAT) && !file_existed &&
-		    ms_has_wild(fname))  {
+		    ms_has_wild(path))  {
 			return NT_STATUS_OBJECT_NAME_INVALID;
 		}
 
 		/* Actually do the open */
-		if (!fd_open(conn, fname, fsp, local_flags, unx_mode)) {
+		if (!fd_open(conn, path, fsp, local_flags, unx_mode)) {
 			DEBUG(3,("Error opening file %s (%s) (local_flags=%d) "
 				 "(flags=%d)\n",
-				 fname,strerror(errno),local_flags,flags));
+				 path,strerror(errno),local_flags,flags));
 			return map_nt_error_from_unix(errno);
 		}
 
@@ -298,7 +299,7 @@
 
 			/* Inherit the ACL if required */
 			if (lp_inherit_perms(SNUM(conn))) {
-				inherit_access_acl(conn, parent_dir, fname,
+				inherit_access_acl(conn, parent_dir, path,
 						   unx_mode);
 			}
 
@@ -307,6 +308,9 @@
 				change_file_owner_to_parent(conn, parent_dir,
 							    fsp);
 			}
+
+			notify_action(conn, parent_dir, name,
+				      NOTIFY_ACTION_ADDED);
 		}
 
 	} else {
@@ -317,13 +321,13 @@
 		int ret;
 
 		if (fsp->fh->fd == -1) {
-			ret = SMB_VFS_STAT(conn, fname, psbuf);
+			ret = SMB_VFS_STAT(conn, path, psbuf);
 		} else {
 			ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf);
 			/* If we have an fd, this stat should succeed. */
 			if (ret == -1) {
 				DEBUG(0,("Error doing fstat on open file %s "
-					 "(%s)\n", fname,strerror(errno) ));
+					 "(%s)\n", path,strerror(errno) ));
 			}
 		}
 
@@ -365,12 +369,13 @@
 	fsp->sent_oplock_break = NO_BREAK_SENT;
 	fsp->is_directory = False;
 	fsp->is_stat = False;
-	if (conn->aio_write_behind_list &&
-	    is_in_path(fname, conn->aio_write_behind_list, conn->case_sensitive)) {
+	if (conn->aio_write_behind_list
+	    && is_in_path(path, conn->aio_write_behind_list,
+			  conn->case_sensitive)) {
 		fsp->aio_write_behind = True;
 	}
 
-	string_set(&fsp->fsp_name,fname);
+	string_set(&fsp->fsp_name, path);
 	fsp->wcp = NULL; /* Write cache pointer. */
 
 	DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
@@ -1579,8 +1584,9 @@
 	 * open_file strips any O_TRUNC flags itself.
 	 */
 
-	fsp_open = open_file(fsp, conn, parent_dir, fname, psbuf, flags|flags2,
-			     unx_mode, access_mask, open_access_mask);
+	fsp_open = open_file(fsp, conn, parent_dir, newname, fname, psbuf,
+			     flags|flags2, unx_mode, access_mask,
+			     open_access_mask);
 
 	if (!NT_STATUS_IS_OK(fsp_open)) {
 		if (lck != NULL) {
@@ -1845,7 +1851,7 @@
 
 	/* note! we must use a non-zero desired access or we don't get
            a real file descriptor. Oh what a twisted web we weave. */
-	status = open_file(fsp, conn, NULL, fname, psbuf, O_WRONLY, 0,
+	status = open_file(fsp, conn, NULL, NULL, fname, psbuf, O_WRONLY, 0,
 			   FILE_WRITE_DATA, FILE_WRITE_DATA);
 
 	/* 

Modified: branches/SAMBA_3_0/source/smbd/reply.c
===================================================================
--- branches/SAMBA_3_0/source/smbd/reply.c	2006-12-31 10:08:52 UTC (rev 20432)
+++ branches/SAMBA_3_0/source/smbd/reply.c	2006-12-31 10:16:03 UTC (rev 20433)
@@ -1975,10 +1975,12 @@
  code.
 ****************************************************************************/
 
-NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, BOOL has_wild)
+NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
+			  char *name, BOOL has_wild)
 {
 	pstring directory;
 	pstring mask;
+	pstring orig_name;
 	char *p;
 	int count=0;
 	NTSTATUS error = NT_STATUS_OK;
@@ -1989,6 +1991,11 @@
 	*directory = *mask = 0;
 	
 	rc = unix_convert(name,conn,0,&bad_path,&sbuf);
+
+	/*
+	 * Feel my pain, this code needs rewriting *very* badly! -- vl
+	 */
+	pstrcpy(orig_name, name);
 	
 	p = strrchr_m(name,'/');
 	if (!p) {
@@ -2089,6 +2096,18 @@
 		error = map_nt_error_from_unix(errno);
 	}
 
+	{
+		char *dir;
+		const char *fname;
+
+		if (parent_dirname_talloc(tmp_talloc_ctx(), orig_name,
+					  &dir, &fname)) {
+			notify_action(conn, dir, fname,
+				      NOTIFY_ACTION_REMOVED);
+			TALLOC_FREE(dir); /* not strictly necessary */
+		}
+	}
+
 	return error;
 }
 



More information about the samba-cvs mailing list