| 
									
										
										
										
											2016-04-29 16:29:09 +08:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2019-04-10 02:39:42 +08:00
										 |  |  |  * MinIO Cloud Storage, (C) 2016, 2017, 2018, 2019 MinIO, Inc. | 
					
						
							| 
									
										
										
										
											2016-04-29 16:29:09 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-19 07:23:42 +08:00
										 |  |  | package cmd | 
					
						
							| 
									
										
										
										
											2016-04-29 16:29:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-30 02:39:20 +08:00
										 |  |  | import ( | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2016-05-17 05:31:28 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2016-08-24 10:19:24 +08:00
										 |  |  | 	pathutil "path" | 
					
						
							| 
									
										
										
										
											2018-01-17 23:24:46 +08:00
										 |  |  | 	"runtime" | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 	"sort" | 
					
						
							| 
									
										
										
										
											2018-01-17 23:24:46 +08:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2016-04-30 02:39:20 +08:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2016-08-11 04:08:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:29:22 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2017-10-13 18:01:15 +08:00
										 |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:29:22 +08:00
										 |  |  | 	"github.com/minio/lsync" | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 	"github.com/minio/minio/cmd/logger" | 
					
						
							| 
									
										
										
										
											2019-11-14 04:17:45 +08:00
										 |  |  | 	"github.com/minio/minio/pkg/dsync" | 
					
						
							| 
									
										
										
										
											2016-04-30 02:39:20 +08:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2016-04-29 16:29:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-14 04:17:45 +08:00
										 |  |  | // local lock servers
 | 
					
						
							|  |  |  | var globalLockServers = make(map[Endpoint]*localLocker) | 
					
						
							| 
									
										
										
										
											2017-06-06 03:25:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:29:22 +08:00
										 |  |  | // RWLocker - locker interface to introduce GetRLock, RUnlock.
 | 
					
						
							| 
									
										
										
										
											2017-01-17 09:05:00 +08:00
										 |  |  | type RWLocker interface { | 
					
						
							| 
									
										
										
										
											2017-09-01 02:29:22 +08:00
										 |  |  | 	GetLock(timeout *dynamicTimeout) (timedOutErr error) | 
					
						
							|  |  |  | 	Unlock() | 
					
						
							|  |  |  | 	GetRLock(timeout *dynamicTimeout) (timedOutErr error) | 
					
						
							|  |  |  | 	RUnlock() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-13 12:34:52 +08:00
										 |  |  | // newNSLock - return a new name space lock map.
 | 
					
						
							|  |  |  | func newNSLock(isDistXL bool) *nsLockMap { | 
					
						
							|  |  |  | 	nsMutex := nsLockMap{ | 
					
						
							| 
									
										
										
										
											2016-12-11 08:15:12 +08:00
										 |  |  | 		isDistXL: isDistXL, | 
					
						
							| 
									
										
										
										
											2016-08-11 04:08:11 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-04-03 03:27:20 +08:00
										 |  |  | 	if isDistXL { | 
					
						
							|  |  |  | 		return &nsMutex | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 	nsMutex.lockMap = make(map[string]*nsLock) | 
					
						
							| 
									
										
										
										
											2018-01-13 12:34:52 +08:00
										 |  |  | 	return &nsMutex | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-29 16:29:09 +08:00
										 |  |  | // nsLock - provides primitives for locking critical namespace regions.
 | 
					
						
							|  |  |  | type nsLock struct { | 
					
						
							| 
									
										
										
										
											2019-04-03 03:27:20 +08:00
										 |  |  | 	*lsync.LRWMutex | 
					
						
							| 
									
										
										
										
											2016-09-16 15:30:55 +08:00
										 |  |  | 	ref uint | 
					
						
							| 
									
										
										
										
											2016-04-29 16:29:09 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // nsLockMap - namespace lock map, provides primitives to Lock,
 | 
					
						
							|  |  |  | // Unlock, RLock and RUnlock.
 | 
					
						
							|  |  |  | type nsLockMap struct { | 
					
						
							| 
									
										
										
										
											2017-01-17 09:05:00 +08:00
										 |  |  | 	// Indicates if namespace is part of a distributed setup.
 | 
					
						
							| 
									
										
										
										
											2016-12-11 08:15:12 +08:00
										 |  |  | 	isDistXL     bool | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 	lockMap      map[string]*nsLock | 
					
						
							| 
									
										
										
										
											2018-08-06 11:25:25 +08:00
										 |  |  | 	lockMapMutex sync.RWMutex | 
					
						
							| 
									
										
										
										
											2016-04-29 16:29:09 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-30 02:39:20 +08:00
										 |  |  | // Lock the namespace resource.
 | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | func (n *nsLockMap) lock(ctx context.Context, volume string, path string, lockSource, opsID string, readLock bool, timeout time.Duration) (locked bool) { | 
					
						
							| 
									
										
										
										
											2016-08-11 04:08:11 +08:00
										 |  |  | 	var nsLk *nsLock | 
					
						
							| 
									
										
										
										
											2016-04-29 16:29:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 	resource := pathJoin(volume, path) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-06 11:25:25 +08:00
										 |  |  | 	n.lockMapMutex.Lock() | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 	nsLk, found := n.lockMap[resource] | 
					
						
							| 
									
										
										
										
											2016-04-29 16:29:09 +08:00
										 |  |  | 	if !found { | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 		nsLk = &nsLock{ | 
					
						
							| 
									
										
										
										
											2019-06-29 13:09:17 +08:00
										 |  |  | 			LRWMutex: lsync.NewLRWMutex(ctx), | 
					
						
							| 
									
										
										
										
											2019-04-03 03:27:20 +08:00
										 |  |  | 			ref:      1, | 
					
						
							| 
									
										
										
										
											2016-04-29 16:29:09 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 		n.lockMap[resource] = nsLk | 
					
						
							| 
									
										
										
										
											2018-08-06 11:25:25 +08:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		// Update ref count here to avoid multiple races.
 | 
					
						
							|  |  |  | 		nsLk.ref++ | 
					
						
							| 
									
										
										
										
											2016-04-29 16:29:09 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-08-11 04:08:11 +08:00
										 |  |  | 	n.lockMapMutex.Unlock() | 
					
						
							| 
									
										
										
										
											2016-04-30 02:39:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:29:22 +08:00
										 |  |  | 	// Locking here will block (until timeout).
 | 
					
						
							| 
									
										
										
										
											2016-04-30 02:39:20 +08:00
										 |  |  | 	if readLock { | 
					
						
							| 
									
										
										
										
											2019-01-24 23:22:14 +08:00
										 |  |  | 		locked = nsLk.GetRLock(opsID, lockSource, timeout) | 
					
						
							| 
									
										
										
										
											2016-04-30 02:39:20 +08:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2019-01-24 23:22:14 +08:00
										 |  |  | 		locked = nsLk.GetLock(opsID, lockSource, timeout) | 
					
						
							| 
									
										
										
										
											2017-09-01 02:29:22 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !locked { // We failed to get the lock
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-06 11:25:25 +08:00
										 |  |  | 		// Decrement ref count since we failed to get the lock
 | 
					
						
							|  |  |  | 		n.lockMapMutex.Lock() | 
					
						
							|  |  |  | 		nsLk.ref-- | 
					
						
							| 
									
										
										
										
											2017-09-01 02:29:22 +08:00
										 |  |  | 		if nsLk.ref == 0 { | 
					
						
							|  |  |  | 			// Remove from the map if there are no more references.
 | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 			delete(n.lockMap, resource) | 
					
						
							| 
									
										
										
										
											2017-09-01 02:29:22 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-08-06 11:25:25 +08:00
										 |  |  | 		n.lockMapMutex.Unlock() | 
					
						
							| 
									
										
										
										
											2016-04-30 02:39:20 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-01 02:29:22 +08:00
										 |  |  | 	return | 
					
						
							| 
									
										
										
										
											2016-04-29 16:29:09 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-30 02:39:20 +08:00
										 |  |  | // Unlock the namespace resource.
 | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | func (n *nsLockMap) unlock(volume string, path string, readLock bool) { | 
					
						
							|  |  |  | 	resource := pathJoin(volume, path) | 
					
						
							| 
									
										
										
										
											2018-08-06 11:25:25 +08:00
										 |  |  | 	n.lockMapMutex.RLock() | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 	nsLk, found := n.lockMap[resource] | 
					
						
							| 
									
										
										
										
											2018-08-06 11:25:25 +08:00
										 |  |  | 	n.lockMapMutex.RUnlock() | 
					
						
							|  |  |  | 	if !found { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if readLock { | 
					
						
							|  |  |  | 		nsLk.RUnlock() | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		nsLk.Unlock() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	n.lockMapMutex.Lock() | 
					
						
							|  |  |  | 	if nsLk.ref == 0 { | 
					
						
							|  |  |  | 		logger.LogIf(context.Background(), errors.New("Namespace reference count cannot be 0")) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		nsLk.ref-- | 
					
						
							| 
									
										
										
										
											2016-04-30 02:39:20 +08:00
										 |  |  | 		if nsLk.ref == 0 { | 
					
						
							|  |  |  | 			// Remove from the map if there are no more references.
 | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 			delete(n.lockMap, resource) | 
					
						
							| 
									
										
										
										
											2016-04-29 16:29:09 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-08-06 11:25:25 +08:00
										 |  |  | 	n.lockMapMutex.Unlock() | 
					
						
							| 
									
										
										
										
											2016-04-29 16:29:09 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-03 03:27:20 +08:00
										 |  |  | // dsync's distributed lock instance.
 | 
					
						
							|  |  |  | type distLockInstance struct { | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 	rwMutex *dsync.DRWMutex | 
					
						
							|  |  |  | 	opsID   string | 
					
						
							| 
									
										
										
										
											2019-04-03 03:27:20 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Lock - block until write lock is taken or timeout has occurred.
 | 
					
						
							|  |  |  | func (di *distLockInstance) GetLock(timeout *dynamicTimeout) (timedOutErr error) { | 
					
						
							|  |  |  | 	lockSource := getSource() | 
					
						
							|  |  |  | 	start := UTCNow() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !di.rwMutex.GetLock(di.opsID, lockSource, timeout.Timeout()) { | 
					
						
							|  |  |  | 		timeout.LogFailure() | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 		return OperationTimedOut{} | 
					
						
							| 
									
										
										
										
											2019-04-03 03:27:20 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	timeout.LogSuccess(UTCNow().Sub(start)) | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Unlock - block until write lock is released.
 | 
					
						
							|  |  |  | func (di *distLockInstance) Unlock() { | 
					
						
							|  |  |  | 	di.rwMutex.Unlock() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RLock - block until read lock is taken or timeout has occurred.
 | 
					
						
							|  |  |  | func (di *distLockInstance) GetRLock(timeout *dynamicTimeout) (timedOutErr error) { | 
					
						
							|  |  |  | 	lockSource := getSource() | 
					
						
							|  |  |  | 	start := UTCNow() | 
					
						
							|  |  |  | 	if !di.rwMutex.GetRLock(di.opsID, lockSource, timeout.Timeout()) { | 
					
						
							|  |  |  | 		timeout.LogFailure() | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 		return OperationTimedOut{} | 
					
						
							| 
									
										
										
										
											2019-04-03 03:27:20 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	timeout.LogSuccess(UTCNow().Sub(start)) | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RUnlock - block until read lock is released.
 | 
					
						
							|  |  |  | func (di *distLockInstance) RUnlock() { | 
					
						
							|  |  |  | 	di.rwMutex.RUnlock() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // localLockInstance - frontend/top-level interface for namespace locks.
 | 
					
						
							|  |  |  | type localLockInstance struct { | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 	ctx    context.Context | 
					
						
							|  |  |  | 	ns     *nsLockMap | 
					
						
							|  |  |  | 	volume string | 
					
						
							|  |  |  | 	paths  []string | 
					
						
							|  |  |  | 	opsID  string | 
					
						
							| 
									
										
										
										
											2016-11-10 02:58:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewNSLock - returns a lock instance for a given volume and
 | 
					
						
							|  |  |  | // path. The returned lockInstance object encapsulates the nsLockMap,
 | 
					
						
							|  |  |  | // volume, path and operation ID.
 | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | func (n *nsLockMap) NewNSLock(ctx context.Context, lockersFn func() []dsync.NetLocker, volume string, paths ...string) RWLocker { | 
					
						
							| 
									
										
										
										
											2018-08-03 01:39:42 +08:00
										 |  |  | 	opsID := mustGetUUID() | 
					
						
							| 
									
										
										
										
											2019-04-03 03:27:20 +08:00
										 |  |  | 	if n.isDistXL { | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 		drwmutex := dsync.NewDRWMutex(ctx, &dsync.Dsync{ | 
					
						
							| 
									
										
										
										
											2019-11-20 09:42:27 +08:00
										 |  |  | 			GetLockersFn: lockersFn, | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 		}, pathsJoinPrefix(volume, paths...)...) | 
					
						
							|  |  |  | 		return &distLockInstance{drwmutex, opsID} | 
					
						
							| 
									
										
										
										
											2019-04-03 03:27:20 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 	sort.Strings(paths) | 
					
						
							|  |  |  | 	return &localLockInstance{ctx, n, volume, paths, opsID} | 
					
						
							| 
									
										
										
										
											2016-11-10 02:58:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:29:22 +08:00
										 |  |  | // Lock - block until write lock is taken or timeout has occurred.
 | 
					
						
							| 
									
										
										
										
											2019-04-03 03:27:20 +08:00
										 |  |  | func (li *localLockInstance) GetLock(timeout *dynamicTimeout) (timedOutErr error) { | 
					
						
							| 
									
										
										
										
											2017-03-24 07:36:00 +08:00
										 |  |  | 	lockSource := getSource() | 
					
						
							| 
									
										
										
										
											2017-09-01 02:29:22 +08:00
										 |  |  | 	start := UTCNow() | 
					
						
							| 
									
										
										
										
											2016-11-10 02:58:41 +08:00
										 |  |  | 	readLock := false | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 	var success []int | 
					
						
							|  |  |  | 	for i, path := range li.paths { | 
					
						
							|  |  |  | 		if !li.ns.lock(li.ctx, li.volume, path, lockSource, li.opsID, readLock, timeout.Timeout()) { | 
					
						
							|  |  |  | 			timeout.LogFailure() | 
					
						
							|  |  |  | 			for _, sint := range success { | 
					
						
							|  |  |  | 				li.ns.unlock(li.volume, li.paths[sint], readLock) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return OperationTimedOut{} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		success = append(success, i) | 
					
						
							| 
									
										
										
										
											2017-09-01 02:29:22 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	timeout.LogSuccess(UTCNow().Sub(start)) | 
					
						
							|  |  |  | 	return | 
					
						
							| 
									
										
										
										
											2016-11-10 02:58:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Unlock - block until write lock is released.
 | 
					
						
							| 
									
										
										
										
											2019-04-03 03:27:20 +08:00
										 |  |  | func (li *localLockInstance) Unlock() { | 
					
						
							| 
									
										
										
										
											2016-11-10 02:58:41 +08:00
										 |  |  | 	readLock := false | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 	for _, path := range li.paths { | 
					
						
							|  |  |  | 		li.ns.unlock(li.volume, path, readLock) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-11-10 02:58:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 02:29:22 +08:00
										 |  |  | // RLock - block until read lock is taken or timeout has occurred.
 | 
					
						
							| 
									
										
										
										
											2019-04-03 03:27:20 +08:00
										 |  |  | func (li *localLockInstance) GetRLock(timeout *dynamicTimeout) (timedOutErr error) { | 
					
						
							| 
									
										
										
										
											2017-03-24 07:36:00 +08:00
										 |  |  | 	lockSource := getSource() | 
					
						
							| 
									
										
										
										
											2017-09-01 02:29:22 +08:00
										 |  |  | 	start := UTCNow() | 
					
						
							| 
									
										
										
										
											2016-11-10 02:58:41 +08:00
										 |  |  | 	readLock := true | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 	var success []int | 
					
						
							|  |  |  | 	for i, path := range li.paths { | 
					
						
							|  |  |  | 		if !li.ns.lock(li.ctx, li.volume, path, lockSource, li.opsID, readLock, timeout.Timeout()) { | 
					
						
							|  |  |  | 			timeout.LogFailure() | 
					
						
							|  |  |  | 			for _, sint := range success { | 
					
						
							|  |  |  | 				li.ns.unlock(li.volume, li.paths[sint], readLock) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return OperationTimedOut{} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		success = append(success, i) | 
					
						
							| 
									
										
										
										
											2017-09-01 02:29:22 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	timeout.LogSuccess(UTCNow().Sub(start)) | 
					
						
							|  |  |  | 	return | 
					
						
							| 
									
										
										
										
											2016-11-10 02:58:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RUnlock - block until read lock is released.
 | 
					
						
							| 
									
										
										
										
											2019-04-03 03:27:20 +08:00
										 |  |  | func (li *localLockInstance) RUnlock() { | 
					
						
							| 
									
										
										
										
											2016-11-10 02:58:41 +08:00
										 |  |  | 	readLock := true | 
					
						
							| 
									
										
										
										
											2020-02-21 13:59:57 +08:00
										 |  |  | 	for _, path := range li.paths { | 
					
						
							|  |  |  | 		li.ns.unlock(li.volume, path, readLock) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-11-10 02:58:41 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-01-17 23:24:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func getSource() string { | 
					
						
							|  |  |  | 	var funcName string | 
					
						
							|  |  |  | 	pc, filename, lineNum, ok := runtime.Caller(2) | 
					
						
							|  |  |  | 	if ok { | 
					
						
							|  |  |  | 		filename = pathutil.Base(filename) | 
					
						
							|  |  |  | 		funcName = strings.TrimPrefix(runtime.FuncForPC(pc).Name(), | 
					
						
							|  |  |  | 			"github.com/minio/minio/cmd.") | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		filename = "<unknown>" | 
					
						
							|  |  |  | 		lineNum = 0 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return fmt.Sprintf("[%s:%d:%s()]", filename, lineNum, funcName) | 
					
						
							|  |  |  | } |