mirror of
				https://github.com/minio/minio.git
				synced 2025-10-31 08:11:19 +01:00 
			
		
		
		
	hold granular locking for multi-pool PutObject() (#20434)
- PutObject() for multi-pooled was holding large region locks, which was not necessary. This affects almost all slowpoke clients and lengthy uploads. - Re-arrange locks for CompleteMultipart, PutObject to be close to rename()
This commit is contained in:
		
							parent
							
								
									e47d787adb
								
							
						
					
					
						commit
						5bf41aff17
					
				| @ -455,8 +455,11 @@ func (er erasureObjects) newMultipartUpload(ctx context.Context, bucket string, | |||||||
| 	} | 	} | ||||||
| 	fi.DataDir = mustGetUUID() | 	fi.DataDir = mustGetUUID() | ||||||
| 
 | 
 | ||||||
| 	if userDefined[ReplicationSsecChecksumHeader] != "" { | 	if ckSum := userDefined[ReplicationSsecChecksumHeader]; ckSum != "" { | ||||||
| 		fi.Checksum, _ = base64.StdEncoding.DecodeString(userDefined[ReplicationSsecChecksumHeader]) | 		v, err := base64.StdEncoding.DecodeString(ckSum) | ||||||
|  | 		if err == nil { | ||||||
|  | 			fi.Checksum = v | ||||||
|  | 		} | ||||||
| 		delete(userDefined, ReplicationSsecChecksumHeader) | 		delete(userDefined, ReplicationSsecChecksumHeader) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -1331,16 +1334,6 @@ func (er erasureObjects) CompleteMultipartUpload(ctx context.Context, bucket str | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if !opts.NoLock { |  | ||||||
| 		lk := er.NewNSLock(bucket, object) |  | ||||||
| 		lkctx, err := lk.GetLock(ctx, globalOperationTimeout) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return ObjectInfo{}, err |  | ||||||
| 		} |  | ||||||
| 		ctx = lkctx.Context() |  | ||||||
| 		defer lk.Unlock(lkctx) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Accept encrypted checksum from incoming request. | 	// Accept encrypted checksum from incoming request. | ||||||
| 	if opts.UserDefined[ReplicationSsecChecksumHeader] != "" { | 	if opts.UserDefined[ReplicationSsecChecksumHeader] != "" { | ||||||
| 		if v, err := base64.StdEncoding.DecodeString(opts.UserDefined[ReplicationSsecChecksumHeader]); err == nil { | 		if v, err := base64.StdEncoding.DecodeString(opts.UserDefined[ReplicationSsecChecksumHeader]); err == nil { | ||||||
| @ -1419,6 +1412,16 @@ func (er erasureObjects) CompleteMultipartUpload(ctx context.Context, bucket str | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if !opts.NoLock { | ||||||
|  | 		lk := er.NewNSLock(bucket, object) | ||||||
|  | 		lkctx, err := lk.GetLock(ctx, globalOperationTimeout) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return ObjectInfo{}, err | ||||||
|  | 		} | ||||||
|  | 		ctx = lkctx.Context() | ||||||
|  | 		defer lk.Unlock(lkctx) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	er.cleanupMultipartPath(ctx, paths...) // cleanup all part.N.meta, and skipped part.N's before final rename(). | 	er.cleanupMultipartPath(ctx, paths...) // cleanup all part.N.meta, and skipped part.N's before final rename(). | ||||||
| 
 | 
 | ||||||
| 	defer func() { | 	defer func() { | ||||||
|  | |||||||
| @ -1333,12 +1333,12 @@ func (er erasureObjects) putObject(ctx context.Context, bucket string, object st | |||||||
| 	if opts.EncryptFn != nil { | 	if opts.EncryptFn != nil { | ||||||
| 		fi.Checksum = opts.EncryptFn("object-checksum", fi.Checksum) | 		fi.Checksum = opts.EncryptFn("object-checksum", fi.Checksum) | ||||||
| 	} | 	} | ||||||
| 	if userDefined[ReplicationSsecChecksumHeader] != "" { | 	if ckSum := userDefined[ReplicationSsecChecksumHeader]; ckSum != "" { | ||||||
| 		if v, err := base64.StdEncoding.DecodeString(userDefined[ReplicationSsecChecksumHeader]); err == nil { | 		if v, err := base64.StdEncoding.DecodeString(ckSum); err == nil { | ||||||
| 			fi.Checksum = v | 			fi.Checksum = v | ||||||
| 		} | 		} | ||||||
| 	} |  | ||||||
| 		delete(userDefined, ReplicationSsecChecksumHeader) | 		delete(userDefined, ReplicationSsecChecksumHeader) | ||||||
|  | 	} | ||||||
| 	uniqueID := mustGetUUID() | 	uniqueID := mustGetUUID() | ||||||
| 	tempObj := uniqueID | 	tempObj := uniqueID | ||||||
| 
 | 
 | ||||||
| @ -1436,15 +1436,6 @@ func (er erasureObjects) putObject(ctx context.Context, bucket string, object st | |||||||
| 	if opts.IndexCB != nil { | 	if opts.IndexCB != nil { | ||||||
| 		compIndex = opts.IndexCB() | 		compIndex = opts.IndexCB() | ||||||
| 	} | 	} | ||||||
| 	if !opts.NoLock { |  | ||||||
| 		lk := er.NewNSLock(bucket, object) |  | ||||||
| 		lkctx, err := lk.GetLock(ctx, globalOperationTimeout) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return ObjectInfo{}, err |  | ||||||
| 		} |  | ||||||
| 		ctx = lkctx.Context() |  | ||||||
| 		defer lk.Unlock(lkctx) |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	modTime := opts.MTime | 	modTime := opts.MTime | ||||||
| 	if opts.MTime.IsZero() { | 	if opts.MTime.IsZero() { | ||||||
| @ -1521,6 +1512,16 @@ func (er erasureObjects) putObject(ctx context.Context, bucket string, object st | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if !opts.NoLock { | ||||||
|  | 		lk := er.NewNSLock(bucket, object) | ||||||
|  | 		lkctx, err := lk.GetLock(ctx, globalOperationTimeout) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return ObjectInfo{}, err | ||||||
|  | 		} | ||||||
|  | 		ctx = lkctx.Context() | ||||||
|  | 		defer lk.Unlock(lkctx) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	// Rename the successfully written temporary object to final location. | 	// Rename the successfully written temporary object to final location. | ||||||
| 	onlineDisks, versions, oldDataDir, err := renameData(ctx, onlineDisks, minioMetaTmpBucket, tempObj, partsMetadata, bucket, object, writeQuorum) | 	onlineDisks, versions, oldDataDir, err := renameData(ctx, onlineDisks, minioMetaTmpBucket, tempObj, partsMetadata, bucket, object, writeQuorum) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | |||||||
| @ -1091,18 +1091,7 @@ func (z *erasureServerPools) PutObject(ctx context.Context, bucket string, objec | |||||||
| 		return z.serverPools[0].PutObject(ctx, bucket, object, data, opts) | 		return z.serverPools[0].PutObject(ctx, bucket, object, data, opts) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if !opts.NoLock { | 	idx, err := z.getPoolIdx(ctx, bucket, object, data.Size()) | ||||||
| 		ns := z.NewNSLock(bucket, object) |  | ||||||
| 		lkctx, err := ns.GetLock(ctx, globalOperationTimeout) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return ObjectInfo{}, err |  | ||||||
| 		} |  | ||||||
| 		ctx = lkctx.Context() |  | ||||||
| 		defer ns.Unlock(lkctx) |  | ||||||
| 		opts.NoLock = true |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	idx, err := z.getPoolIdxNoLock(ctx, bucket, object, data.Size()) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return ObjectInfo{}, err | 		return ObjectInfo{}, err | ||||||
| 	} | 	} | ||||||
| @ -1115,7 +1104,7 @@ func (z *erasureServerPools) PutObject(ctx context.Context, bucket string, objec | |||||||
| 			Err:       errDataMovementSrcDstPoolSame, | 			Err:       errDataMovementSrcDstPoolSame, | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	// Overwrite the object at the right pool | 
 | ||||||
| 	return z.serverPools[idx].PutObject(ctx, bucket, object, data, opts) | 	return z.serverPools[idx].PutObject(ctx, bucket, object, data, opts) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user