Problems with Samba 2.2.0 on Solaris 8 with quotas

Shirish Kalele kalele at veritas.com
Tue Jun 19 01:39:28 GMT 2001


Hi Jeremy,

On Fri, 15 Jun 2001, Jeremy Allison wrote:

>Shirish Kalele wrote:
>> 
>> David,
>> 
>> I have a fix for 2.0.9 based on the description. With the fix, samba does a
>> disk space check on every zero byte write. I've also fixed the
>> delete-on-close behaviour in 2.0: propagating delete-on-close flags to all
>> share mode entries for the file, setting it on a TRANS2
>> SET_FILE_DISPOSITION_INFO call, checking delete-on-close flags before doing
>> any oplock-processing on opens, sending delete-pending errors on opens etc.
>> Since there won't be further releases of the 2.0 tree, I was wondering if I
>> should check these fixes into 2.0?
>
>Probably not.
>
>> Also, I don't know if Jeremy is okay with doing space-checks on zero-byte
>> writes.
>
>Can you send me the patches against 2.2 ? Zero byte writes
>are rare enough I think that this should be ok.
>

Here are the patches against 2.2..

Off topic, what do you think about having a coding standard for samba
standardizing indenting, positions of braces, commenting etc? Or do we
already having something like this? This will make the source look cleaner
and more readable, and also eliminate all the superfluous diff's because
of different coding styles.

For the nonconformists, maybe we could have them run indent with our
standard to standardize their changes once they're done.

Cheers,
Shirish

Index: smbd/dfree.c
===================================================================
RCS file: /data/cvs/samba/source/smbd/dfree.c,v
retrieving revision 1.14.4.3
diff -u -r1.14.4.3 dfree.c
--- smbd/dfree.c	8 Apr 2001 20:22:54 -0000	1.14.4.3
+++ smbd/dfree.c	19 Jun 2001 01:14:48 -0000
@@ -166,3 +166,60 @@
 {
 	return(disk_free(dos_to_unix(path,False),small_query, bsize,dfree,dsize));
 }
+
+/***********************************************************************
+ * Check to see if there is enough space to extend the file size to
+ * 'offset'
+ ***********************************************************************/
+int enuf_space(files_struct* fsp, SMB_OFF_T offset)
+{
+	SMB_STRUCT_STAT sbuf;
+	SMB_BIG_UINT blks_allocated, blks_offset, blks_needed;
+	SMB_BIG_UINT dfree,dsize,bsize;
+
+	/* Find how many blocks this file occupies */
+	if (sys_fstat(fsp->fd, &sbuf) != 0) {
+		DEBUG(1,("enuf_space: sys_fstat() failed on file %s: %s\n",
+			 fsp->fsp_name, strerror(errno) ));
+		return -1;
+	}
+
+	blks_allocated = sbuf.st_blocks;
+
+	/* Get the total blocks needed to extend file to 'offset' */
+	blks_offset = (offset + 511)/ 512;
+	
+	if (blks_offset < blks_allocated)
+		return 1;
+
+       	blks_needed = blks_offset - blks_allocated;
+	
+	if (blks_needed == 0) {
+		DEBUG(10,("enuf_space: blks_needed is zero!!\n"));
+	}
+
+	DEBUG(8,("enuf_space: blks_needed: %u blks_offset: %u (offset: %u) blks_allocated %u\n",
+		 (unsigned int) blks_needed, 
+		 (unsigned int) blks_offset, 
+		 (unsigned int) offset,
+		 (unsigned int) blks_allocated));
+
+	disk_free(fsp->fsp_name, False, &bsize,&dfree,&dsize);
+
+	if (bsize != 512) {
+		dfree = (unsigned int)(dfree * ((float) bsize / 512));
+		dsize = (unsigned int)(dsize * ((float) bsize / 512));
+	}
+		
+	if (blks_needed <= dfree) {
+		DEBUG(8,("enuf_space: blks_needed: %d, free blks: %d, Allow set_filelen()\n",
+			 (unsigned int) blks_needed, 
+			 (unsigned int) dfree));
+		return 1;
+	} else {
+		DEBUG(8,("enuf_space: blks_needed: %d, free blks: %d, Disallow set_filelen()\n",
+			 (unsigned int) blks_needed, 
+			 (unsigned int) dfree));
+		return 0;
+	}
+}
Index: smbd/nttrans.c
===================================================================
RCS file: /data/cvs/samba/source/smbd/nttrans.c,v
retrieving revision 1.104.4.16
diff -u -r1.104.4.16 nttrans.c
--- smbd/nttrans.c	9 Jun 2001 01:38:18 -0000	1.104.4.16
+++ smbd/nttrans.c	19 Jun 2001 01:14:49 -0000
@@ -942,7 +942,15 @@
 				}
 				
 				restore_case_semantics(file_attributes);
-				
+							
+				/* unix_ERR_class = 0 indicates an NT
+				   status error 
+				*/
+				if (unix_ERR_class == 0 && unix_ERR_code != 0) {
+					SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+					return (ERROR(0, unix_ERR_code));
+				}
+	
 				END_PROFILE(SMBntcreateX);
 				return(UNIXERROR(ERRDOS,ERRnoaccess));
 			}
Index: smbd/open.c
===================================================================
RCS file: /data/cvs/samba/source/smbd/open.c,v
retrieving revision 1.62.4.17
diff -u -r1.62.4.17 open.c
--- smbd/open.c	18 Apr 2001 04:09:13 -0000	1.62.4.17
+++ smbd/open.c	19 Jun 2001 01:14:49 -0000
@@ -371,19 +371,6 @@
 	int old_deny_mode = GET_DENY_MODE(share->share_mode);
 
 	/*
-	 * Don't allow any opens once the delete on close flag has been
-	 * set.
-	 */
-
-	if (GET_DELETE_ON_CLOSE_FLAG(share->share_mode)) {
-		DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n",
-			fname ));
-		unix_ERR_class = ERRDOS;
-		unix_ERR_code = ERRnoaccess;
-		return False;
-	}
-
-	/*
 	 * If delete access was requested and the existing share mode doesn't have
 	 * ALLOW_SHARE_DELETE then deny.
 	 */
@@ -479,6 +466,19 @@
     for(i = 0; i < num_share_modes; i++) {
       share_mode_entry *share_entry = &old_shares[i];
 
+      /*
+       * Looks like delete-on-close is checked even before any oplock processing is done.
+       * Some clients depend on this.
+       */
+      if(GET_DELETE_ON_CLOSE_FLAG(share_entry->share_mode)) {
+		  DEBUG(5,("check_share_mode: Failing open on file %s as delete pending on the file.\n", fname ));
+		  free((char *)old_shares);
+		  unix_ERR_class = 0;
+		  unix_ERR_code = 0xC0000000 | NT_STATUS_DELETE_PENDING;
+		  errno=EACCES;
+		  return -1;
+	  }
+
       /* 
        * By observation of NetBench, oplocks are broken *before* share
        * modes are checked. This allows a file to be closed by the client
@@ -730,7 +730,7 @@
 			file_free(fsp);
 			return NULL;
 		}
-
+		
 		/*
 		 * We exit this block with the share entry *locked*.....
 		 */
Index: smbd/process.c
===================================================================
RCS file: /data/cvs/samba/source/smbd/process.c,v
retrieving revision 1.44.2.14
diff -u -r1.44.2.14 process.c
--- smbd/process.c	9 Jun 2001 01:38:18 -0000	1.44.2.14
+++ smbd/process.c	19 Jun 2001 01:14:49 -0000
@@ -898,7 +898,8 @@
   CVAL(outbuf,smb_reh) = 0;
   SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); /* bit 7 set
                                  means a reply */
-  SSVAL(outbuf,smb_flg2,FLAGS2_LONG_PATH_COMPONENTS);
+  SSVAL(outbuf,smb_flg2,FLAGS2_LONG_PATH_COMPONENTS |
+	FLAGS2_UNICODE_STRINGS);
 	/* say we support long filenames */
 
   SSVAL(outbuf,smb_err,SMB_SUCCESS);
Index: smbd/quotas.c
===================================================================
RCS file: /data/cvs/samba/source/smbd/quotas.c,v
retrieving revision 1.34.4.8
diff -u -r1.34.4.8 quotas.c
--- smbd/quotas.c	27 Apr 2001 22:17:21 -0000	1.34.4.8
+++ smbd/quotas.c	19 Jun 2001 01:14:49 -0000
@@ -452,6 +452,7 @@
   
 	devno = sbuf.st_dev ;
 	DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,(unsigned int)devno));
+
 	if ( devno != devno_cached ) {
 		devno_cached = devno ;
 #if defined(SUNOS5)
@@ -461,9 +462,25 @@
 		found = False ;
 		slprintf(devopt, sizeof(devopt) - 1, "dev=%x", (unsigned int)devno);
 		while (getmntent(fd, &mnt) == 0) {
+			
+/*
+		JEREMY:   Can't depend on hasmntopt() as third-party file
+			  systems do/may not have the dev= entry (e.g. VxFS on
+			  Solaris 2.7). stat's should be faster than string parsing
+			  anyway.
+			
 			if( !hasmntopt(&mnt, devopt) )
 				continue;
 
+*/		     
+			if (sys_stat(mnt.mnt_mountp,&sbuf) == -1) 
+				continue ;
+
+			DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n",
+				 mnt.mnt_mountp,sbuf.st_dev));
+			if (sbuf.st_dev != devno) 
+				continue;
+				
 			DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt));
 
 			/* quotas are only on vxfs, UFS or NFS */
Index: smbd/reply.c
===================================================================
RCS file: /data/cvs/samba/source/smbd/reply.c,v
retrieving revision 1.240.2.35
diff -u -r1.240.2.35 reply.c
--- smbd/reply.c	9 Jun 2001 01:38:18 -0000	1.240.2.35
+++ smbd/reply.c	19 Jun 2001 01:14:53 -0000
@@ -665,7 +665,7 @@
 
 /****************************************************************************
  Return a bad password error configured for the correct client type.
-****************************************************************************/       
+****************************************************************************/
 
 static int bad_password_error(char *inbuf,char *outbuf)
 {
@@ -681,6 +681,26 @@
 }
 
 /****************************************************************************
+ Return a disk full error configured for the correct client type.
+ (we need a generic function that returns nt-status/dos errors depending
+  on the client type)
+****************************************************************************/
+
+static int disk_full_error(char *inbuf, char *outbuf)
+{
+	enum remote_arch_types ra_type = get_remote_arch();
+
+	if ( ((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) &&
+	     (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32)) ) {
+
+		SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+		return (ERROR(0, NT_STATUS_DISK_FULL));
+	}
+
+	return (ERROR(ERRHRD, ERRdiskfull));
+}
+
+/****************************************************************************
 reply to a session setup command
 ****************************************************************************/
 
@@ -2625,7 +2645,17 @@
      zero then the file size should be extended or
      truncated to the size given in smb_vwv[2-3] */
   if(numtowrite == 0) {
-      nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
+
+	  /* check to see if the file being extended
+	   * can fit in the available disk space. 
+	   * Before setting the file size, check quota/disk space 
+	   * information
+	   */
+	  if(!enuf_space(fsp, (SMB_OFF_T) startpos)) {
+		  return disk_full_error(inbuf, outbuf);
+	  }
+
+    nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
   } else
     nwritten = write_file(fsp,data,startpos,numtowrite);
   





More information about the samba-technical mailing list