Add name_hash into the share mode entry struct (as yet only use for renames to identi...
authorJeremy Allison <jra@samba.org>
Tue, 25 Jan 2011 22:01:52 +0000 (14:01 -0800)
committerJeremy Allison <jra@samba.org>
Tue, 25 Jan 2011 22:01:52 +0000 (14:01 -0800)
source3/include/proto.h
source3/include/smb.h
source3/libsmb/smb_share_modes.c
source3/locking/locking.c
source3/smbd/oplock.c
source3/smbd/reply.c

index fafcf6be52e8a3574ac5ce62b83ce84966fc2cb9..cf508e339816d3384238383d1458394b429fb3e1 100644 (file)
@@ -3068,6 +3068,8 @@ struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
 bool rename_share_filename(struct messaging_context *msg_ctx,
                        struct share_mode_lock *lck,
                        const char *servicepath,
+                       uint32_t orig_name_hash,
+                       uint32_t new_name_hash,
                        const struct smb_filename *smb_fname);
 void get_file_infos(struct file_id id,
                    bool *delete_on_close,
index 6cfb6307d0f66aaddfb4db453fcb43fe6c8436b9..5269c2348fc08faa9f468bc705942ce1925d0d98 100644 (file)
@@ -685,6 +685,7 @@ struct share_mode_entry {
        unsigned long share_file_id;
        uint32 uid;             /* uid of file opener. */
        uint16 flags;           /* See SHARE_MODE_XX above. */
+       uint32_t name_hash;             /* Jenkins hash of full pathname. */
 };
 
 /* oplock break message definition - linearization of share_mode_entry.
@@ -704,7 +705,8 @@ Offset  Data                        length.
 58     unsigned long file_id   4 bytes
 62     uint32 uid              4 bytes
 66     uint16 flags            2 bytes
-68
+68     uint32 name_hash        4 bytes
+72
 
 */
 
@@ -722,12 +724,13 @@ Offset  Data                      length.
 #define OP_BREAK_MSG_FILE_ID_OFFSET 58
 #define OP_BREAK_MSG_UID_OFFSET 62
 #define OP_BREAK_MSG_FLAGS_OFFSET 66
+#define OP_BREAK_MSG_NAME_HASH_OFFSET 68
 
 #ifdef CLUSTER_SUPPORT
-#define OP_BREAK_MSG_VNN_OFFSET 68
-#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 72
+#define OP_BREAK_MSG_VNN_OFFSET 72
+#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 76
 #else
-#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 68
+#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 72
 #endif
 
 struct share_mode_lock {
index 9f985501b6f930d2573616fb9ef7b3018fe74d30..2eda7a499fd3a6bb553f95b3a148bc49559e90c7 100644 (file)
@@ -155,7 +155,8 @@ static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry,
  */
 
 static void create_share_mode_entry(struct share_mode_entry *out,
-                               const struct smb_share_mode_entry *in)
+                               const struct smb_share_mode_entry *in,
+                               uint32_t name_hash)
 {
        memset(out, '\0', sizeof(struct share_mode_entry));
 
@@ -170,6 +171,7 @@ static void create_share_mode_entry(struct share_mode_entry *out,
        out->id.extid = in->extid;
        out->uid = (uint32)geteuid();
        out->flags = 0;
+       out->name_hash = name_hash;
 }
 
 /*
@@ -261,6 +263,26 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx,
        return list_num;
 }
 
+static uint32_t smb_name_hash(const char *sharepath, const char *filename, int *err)
+{
+       TDB_DATA key;
+       char *fullpath = NULL;
+       int ret;
+       uint32_t name_hash;
+
+       *err = 0;
+       ret = asprintf(&fullpath, "%s/%s", sharepath, filename);
+       if (ret == -1 || fullpath == NULL) {
+               *err = 1;
+               return 0;
+       }
+       key.dptr = (uint8_t *)fullpath;
+       key.dsize = strlen(fullpath);
+       name_hash = tdb_jenkins_hash(&key);
+       free(fullpath);
+       return name_hash;
+}
+
 /* 
  * Create an entry in the Samba share mode db.
  */
@@ -281,6 +303,12 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
        struct share_mode_entry *shares = NULL;
        uint8 *new_data_p = NULL;
        size_t new_data_size = 0;
+       int err = 0;
+       uint32_t name_hash = smb_name_hash(sharepath, filename, &err);
+
+       if (err) {
+               return -1;
+       }
 
        db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
        if (!db_data.dptr) {
@@ -299,7 +327,7 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
                ld->u.s.delete_on_close = 0;
                ld->u.s.delete_token_size = 0;
                shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct locking_data));
-               create_share_mode_entry(shares, new_entry);
+               create_share_mode_entry(shares, new_entry, name_hash);
 
                memcpy(db_data.dptr + sizeof(struct locking_data) + sizeof(struct share_mode_entry),
                        sharepath,
@@ -338,7 +366,7 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
        shares = (struct share_mode_entry *)(new_data_p + sizeof(struct locking_data) +
                        (orig_num_share_modes * sizeof(struct share_mode_entry)));
 
-       create_share_mode_entry(shares, new_entry);
+       create_share_mode_entry(shares, new_entry, name_hash);
 
        ld = (struct locking_data *)new_data_p;
        ld->u.s.num_share_mode_entries++;
@@ -521,7 +549,7 @@ int smb_change_share_mode_entry(struct smbdb_ctx *db_ctx,
                }
 
                if (share_mode_entry_equal(set_entry, share)) {
-                       create_share_mode_entry(share, new_entry);
+                       create_share_mode_entry(share, new_entry, share->name_hash);
                        found_entry = 1;
                        break;
                }
index 4a619531769357164c2c80e913aae57e894ab221..a65fcbdba8840ed7ea218ea75bde2131545c320d 100644 (file)
@@ -492,7 +492,7 @@ char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e)
        return talloc_asprintf(ctx, "share_mode_entry[%d]: %s "
                 "pid = %s, share_access = 0x%x, private_options = 0x%x, "
                 "access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %lu, "
-                "uid = %u, flags = %u, file_id %s",
+                "uid = %u, flags = %u, file_id %s, name_hash = 0x%x",
                 num,
                 e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "",
                 procid_str_static(&e->pid),
@@ -500,7 +500,8 @@ char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e)
                 e->access_mask, (unsigned long long)e->op_mid,
                 e->op_type, e->share_file_id,
                 (unsigned int)e->uid, (unsigned int)e->flags,
-                file_id_string_tos(&e->id));
+                file_id_string_tos(&e->id),
+                (unsigned int)e->name_hash);
 }
 
 /*******************************************************************
@@ -953,6 +954,8 @@ struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
 bool rename_share_filename(struct messaging_context *msg_ctx,
                        struct share_mode_lock *lck,
                        const char *servicepath,
+                       uint32_t orig_name_hash,
+                       uint32_t new_name_hash,
                        const struct smb_filename *smb_fname_dst)
 {
        size_t sp_len;
@@ -1018,6 +1021,15 @@ bool rename_share_filename(struct messaging_context *msg_ctx,
                if (!is_valid_share_mode_entry(se)) {
                        continue;
                }
+
+               /* If this is a hardlink to the inode
+                  with a different name, skip this. */
+               if (se->name_hash != orig_name_hash) {
+                       continue;
+               }
+
+               se->name_hash = new_name_hash;
+
                /* But not to ourselves... */
                if (procid_is_me(&se->pid)) {
                        continue;
@@ -1125,6 +1137,7 @@ static void fill_share_mode_entry(struct share_mode_entry *e,
        e->share_file_id = fsp->fh->gen_id;
        e->uid = (uint32)uid;
        e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0;
+       e->name_hash = fsp->name_hash;
 }
 
 static void fill_deferred_open_entry(struct share_mode_entry *e,
index 6f4d5780f3b78c85525dbadd0331cd051aa2b4b0..e92fbd43af1ad5c66a6cbb9bc9fc48598a56d283 100644 (file)
@@ -873,6 +873,7 @@ void share_mode_entry_to_message(char *msg, const struct share_mode_entry *e)
        SIVAL(msg,OP_BREAK_MSG_FILE_ID_OFFSET,e->share_file_id);
        SIVAL(msg,OP_BREAK_MSG_UID_OFFSET,e->uid);
        SSVAL(msg,OP_BREAK_MSG_FLAGS_OFFSET,e->flags);
+       SIVAL(msg,OP_BREAK_MSG_NAME_HASH_OFFSET,e->name_hash);
 #ifdef CLUSTER_SUPPORT
        SIVAL(msg,OP_BREAK_MSG_VNN_OFFSET,e->pid.vnn);
 #endif
@@ -896,6 +897,7 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg)
        e->share_file_id = (unsigned long)IVAL(msg,OP_BREAK_MSG_FILE_ID_OFFSET);
        e->uid = (uint32)IVAL(msg,OP_BREAK_MSG_UID_OFFSET);
        e->flags = (uint16)SVAL(msg,OP_BREAK_MSG_FLAGS_OFFSET);
+       e->name_hash = IVAL(msg,OP_BREAK_MSG_NAME_HASH_OFFSET);
 #ifdef CLUSTER_SUPPORT
        e->pid.vnn = IVAL(msg,OP_BREAK_MSG_VNN_OFFSET);
 #endif
index 0c3b8980b2af05ed0d8dccce359baa8cc941ac0d..92be257029dbb94b595348efe900f2ee4a000f32 100644 (file)
@@ -5804,11 +5804,13 @@ static bool resolve_wildcards(TALLOC_CTX *ctx,
 
 static void rename_open_files(connection_struct *conn,
                              struct share_mode_lock *lck,
+                             uint32_t orig_name_hash,
                              const struct smb_filename *smb_fname_dst)
 {
        files_struct *fsp;
        bool did_rename = False;
        NTSTATUS status;
+       uint32_t new_name_hash;
 
        for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
            fsp = file_find_di_next(fsp)) {
@@ -5819,6 +5821,9 @@ static void rename_open_files(connection_struct *conn,
                if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
                        continue;
                }
+               if (fsp->name_hash != orig_name_hash) {
+                       continue;
+               }
                DEBUG(10, ("rename_open_files: renaming file fnum %d "
                           "(file_id %s) from %s -> %s\n", fsp->fnum,
                           file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
@@ -5827,6 +5832,7 @@ static void rename_open_files(connection_struct *conn,
                status = fsp_set_smb_fname(fsp, smb_fname_dst);
                if (NT_STATUS_IS_OK(status)) {
                        did_rename = True;
+                       new_name_hash = fsp->name_hash;
                }
        }
 
@@ -5838,6 +5844,7 @@ static void rename_open_files(connection_struct *conn,
 
        /* Send messages to all smbd's (not ourself) that the name has changed. */
        rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
+                             orig_name_hash, new_name_hash,
                              smb_fname_dst);
 
 }
@@ -6147,7 +6154,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
                notify_rename(conn, fsp->is_directory, fsp->fsp_name,
                              smb_fname_dst);
 
-               rename_open_files(conn, lck, smb_fname_dst);
+               rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
 
                /*
                 * A rename acts as a new file create w.r.t. allowing an initial delete