s3:smbd: try to make fsp->fh->gen_id as globally unique as possible
authorStefan Metzmacher <metze@samba.org>
Wed, 13 Jun 2012 10:11:51 +0000 (12:11 +0200)
committerKarolin Seeger <kseeger@samba.org>
Sun, 17 Jun 2012 19:01:24 +0000 (21:01 +0200)
This makes sure the value is never 0, it's between 1 and UINT32_MAX.

While fsp->fh->gen_id is 'unsigned long' currently (which might by 8 bytes),
there's some oplock code which truncates it to uint32_t (using IVAL()).

Which means we could reuse fsp->fh->gen_id as persistent file id
until we have a final fix, which uses database.

See bug #8995 for more details.

Based on code from Ira Cooper. Ensure fsp->fh->gen_id starts from
a random point. We will use this as the SMB2 persistent_id.

metze

Signed-off-by: Jeremy Allison <jra@samba.org>
source3/smbd/files.c

index d222bafbd969cf64a966f0ceecb2929203913580..0018ceed5e51cf0b45afa3606b5a78c9146704c6 100644 (file)
 #define FILE_HANDLE_OFFSET 0x1000
 
 /****************************************************************************
- Return a unique number identifying this fsp over the life of this pid.
+ Return a unique number identifying this fsp over the life of this pid,
+ and try to make it as globally unique as possible.
+ See bug #8995 for the details.
 ****************************************************************************/
 
 static unsigned long get_gen_count(struct smbd_server_connection *sconn)
 {
+       /*
+        * While fsp->fh->gen_id is 'unsigned long' currently
+        * (which might by 8 bytes),
+        * there's some oplock code which truncates it to
+        * uint32_t(using IVAL()).
+        */
+       if (sconn->file_gen_counter == 0) {
+               sconn->file_gen_counter = generate_random();
+       }
        sconn->file_gen_counter += 1;
+       if (sconn->file_gen_counter >= UINT32_MAX) {
+               sconn->file_gen_counter = 0;
+       }
        if (sconn->file_gen_counter == 0) {
                sconn->file_gen_counter += 1;
        }
@@ -284,6 +298,10 @@ files_struct *file_find_dif(struct smbd_server_connection *sconn,
        int count=0;
        files_struct *fsp;
 
+       if (gen_id == 0) {
+               return NULL;
+       }
+
        for (fsp=sconn->files; fsp; fsp=fsp->next,count++) {
                /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */
                if (file_id_equal(&fsp->file_id, &id) &&