You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2014/05/16 08:03:33 UTC
svn commit: r1595112 - in /subversion/trunk/subversion/libsvn_fs_x: ./ fs.c
fs.h fs_x.c hotcopy.c recovery.c transaction.c transaction.h util.c util.h
Author: stefan2
Date: Fri May 16 06:03:32 2014
New Revision: 1595112
URL: http://svn.apache.org/r1595112
Log:
Sync'ing FSX with FSFS:
Merge r1588815,1589243,1589250,1589252,1589284,1589368,1589373,
1589376, 1591919 and 1593015 from /subversion/libsvn_fs_fs into
subversion/libsvn_fs_x. Conflicts were due to the locking code
being moved to transaction.* in FSX.
This ports the locking improvements.
Modified:
subversion/trunk/subversion/libsvn_fs_x/ (props changed)
subversion/trunk/subversion/libsvn_fs_x/fs.c
subversion/trunk/subversion/libsvn_fs_x/fs.h
subversion/trunk/subversion/libsvn_fs_x/fs_x.c
subversion/trunk/subversion/libsvn_fs_x/hotcopy.c
subversion/trunk/subversion/libsvn_fs_x/recovery.c
subversion/trunk/subversion/libsvn_fs_x/transaction.c
subversion/trunk/subversion/libsvn_fs_x/transaction.h
subversion/trunk/subversion/libsvn_fs_x/util.c
subversion/trunk/subversion/libsvn_fs_x/util.h
Propchange: subversion/trunk/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
Merged /subversion/trunk/subversion/libsvn_fs_fs:r1588815,1589243,1589250,1589252,1589368,1589373,1589376,1591919,1593015
Modified: subversion/trunk/subversion/libsvn_fs_x/fs.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/fs.c?rev=1595112&r1=1595111&r2=1595112&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/fs.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/fs.c Fri May 16 06:03:32 2014
@@ -97,11 +97,15 @@ x_serialized_init(svn_fs_t *fs, apr_pool
intra-process synchronization when grabbing the repository write
lock. */
SVN_ERR(svn_mutex__init(&ffsd->fs_write_lock,
- SVN_FS_X__USE_LOCK_MUTEX, TRUE, common_pool));
+ TRUE, TRUE, common_pool));
+
+ /* ... the pack lock ... */
+ SVN_ERR(svn_mutex__init(&ffsd->fs_pack_lock,
+ TRUE, TRUE, common_pool));
/* ... not to mention locking the txn-current file. */
SVN_ERR(svn_mutex__init(&ffsd->txn_current_lock,
- SVN_FS_X__USE_LOCK_MUTEX, TRUE, common_pool));
+ TRUE, TRUE, common_pool));
/* We also need a mutex for synchronizing access to the active
transaction list and free transaction pointer. This one is
Modified: subversion/trunk/subversion/libsvn_fs_x/fs.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/fs.h?rev=1595112&r1=1595111&r2=1595112&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/fs.h (original)
+++ subversion/trunk/subversion/libsvn_fs_x/fs.h Fri May 16 06:03:32 2014
@@ -55,6 +55,7 @@ extern "C" {
#define PATH_UUID "uuid" /* Contains UUID */
#define PATH_CURRENT "current" /* Youngest revision */
#define PATH_LOCK_FILE "write-lock" /* Revision lock file */
+#define PATH_PACK_LOCK_FILE "pack-lock" /* Pack lock file */
#define PATH_REVS_DIR "revs" /* Directory of revisions */
#define PATH_REVPROPS_DIR "revprops" /* Directory of revprops */
#define PATH_TXNS_DIR "transactions" /* Directory of transactions */
@@ -147,17 +148,6 @@ typedef struct fs_x_shared_txn_data_t
apr_pool_t *pool;
} fs_x_shared_txn_data_t;
-/* On most operating systems apr implements file locks per process, not
- per file. On Windows apr implements the locking as per file handle
- locks, so we don't have to add our own mutex for just in-process
- synchronization. */
-/* Compare ../libsvn_subr/named_atomic.c:USE_THREAD_MUTEX */
-#if APR_HAS_THREADS && !defined(WIN32)
-#define SVN_FS_X__USE_LOCK_MUTEX 1
-#else
-#define SVN_FS_X__USE_LOCK_MUTEX 0
-#endif
-
/* Private FSX-specific data shared between all svn_fs_t objects that
relate to a particular filesystem, as identified by filesystem UUID.
Objects of this type are allocated in the common pool. */
@@ -173,6 +163,12 @@ typedef struct fs_x_shared_data_t
Access to this object is synchronised under TXN_LIST_LOCK. */
fs_x_shared_txn_data_t *free_txn;
+ /* The following lock must be taken out in reverse order of their
+ declaration here. Any subset may be acquired and held at any given
+ time but their relative acquisition order must not change.
+
+ (lock 'txn-current' before 'pack' before 'write' before 'txn-list') */
+
/* A lock for intra-process synchronization when accessing the TXNS list. */
svn_mutex__t *txn_list_lock;
@@ -180,6 +176,10 @@ typedef struct fs_x_shared_data_t
repository write lock. */
svn_mutex__t *fs_write_lock;
+ /* A lock for intra-process synchronization when grabbing the
+ repository pack operation lock. */
+ svn_mutex__t *fs_pack_lock;
+
/* A lock for intra-process synchronization when locking the
txn-current file. */
svn_mutex__t *txn_current_lock;
Modified: subversion/trunk/subversion/libsvn_fs_x/fs_x.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/fs_x.c?rev=1595112&r1=1595111&r2=1595112&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/fs_x.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/fs_x.c Fri May 16 06:03:32 2014
@@ -525,7 +525,7 @@ svn_fs_x__upgrade(svn_fs_t *fs,
baton.cancel_func = cancel_func;
baton.cancel_baton = cancel_baton;
- return svn_fs_x__with_write_lock(fs, upgrade_body, (void *)&baton, pool);
+ return svn_fs_x__with_all_locks(fs, upgrade_body, (void *)&baton, pool);
}
Modified: subversion/trunk/subversion/libsvn_fs_x/hotcopy.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/hotcopy.c?rev=1595112&r1=1595111&r2=1595112&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/hotcopy.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/hotcopy.c Fri May 16 06:03:32 2014
@@ -910,7 +910,8 @@ hotcopy_locking_src_body(void *baton, ap
struct hotcopy_body_baton *hbb = baton;
fs_x_data_t *src_ffd = hbb->src_fs->fsap_data;
- return hotcopy_body(baton, pool);
+ return svn_error_trace(svn_fs_x__with_pack_lock(hbb->src_fs, hotcopy_body,
+ baton, pool));
}
/* Create an empty filesystem at DST_FS at DST_PATH with the same
Modified: subversion/trunk/subversion/libsvn_fs_x/recovery.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/recovery.c?rev=1595112&r1=1595111&r2=1595112&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/recovery.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/recovery.c Fri May 16 06:03:32 2014
@@ -234,5 +234,5 @@ svn_fs_x__recover(svn_fs_t *fs,
b.fs = fs;
b.cancel_func = cancel_func;
b.cancel_baton = cancel_baton;
- return svn_fs_x__with_write_lock(fs, recover_body, &b, pool);
+ return svn_fs_x__with_all_locks(fs, recover_body, &b, pool);
}
Modified: subversion/trunk/subversion/libsvn_fs_x/transaction.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/transaction.c?rev=1595112&r1=1595111&r2=1595112&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/transaction.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/transaction.c Fri May 16 06:03:32 2014
@@ -212,31 +212,77 @@ reset_lock_flag(void *baton_void)
return APR_SUCCESS;
}
-/* Obtain a write lock on the file LOCK_FILENAME (protecting with
- LOCK_MUTEX if APR is threaded) in a subpool of POOL, call BODY with
- BATON and that subpool, destroy the subpool (releasing the write
- lock) and return what BODY returned. If IS_GLOBAL_LOCK is set,
- set the HAS_WRITE_LOCK flag while we keep the write lock. */
-static svn_error_t *
-with_some_lock_file(svn_fs_t *fs,
- svn_error_t *(*body)(void *baton,
- apr_pool_t *pool),
- void *baton,
- const char *lock_filename,
- svn_boolean_t is_global_lock,
- apr_pool_t *pool)
+/* Structure defining a file system lock to be acquired and the function
+ to be executed while the lock is held.
+
+ Instances of this structure may be nested to allow for multiple locks to
+ be taken out before executing the user-provided body. In that case, BODY
+ and BATON of the outer instances will be with_lock and a with_lock_baton_t
+ instance (transparently, no special treatment is required.). It is
+ illegal to attempt to acquire the same lock twice within the same lock
+ chain or via nesting calls using separate lock chains.
+
+ All instances along the chain share the same LOCK_POOL such that only one
+ pool needs to be created and cleared for all locks. We also allocate as
+ much data from that lock pool as possible to minimize memory usage in
+ caller pools. */
+typedef struct with_lock_baton_t
{
- apr_pool_t *subpool = svn_pool_create(pool);
- svn_error_t *err = get_lock_on_filesystem(lock_filename, subpool);
+ /* The filesystem we operate on. Same for all instances along the chain. */
+ svn_fs_t *fs;
+
+ /* Mutex to complement the lock file in an APR threaded process.
+ No-op object for non-threaded processes but never NULL. */
+ svn_mutex__t *mutex;
+
+ /* Path to the file to lock. */
+ const char *lock_path;
+
+ /* If true, set FS->HAS_WRITE_LOCK after we acquired the lock. */
+ svn_boolean_t is_global_lock;
+
+ /* Function body to execute after we acquired the lock.
+ This may be user-provided or a nested call to with_lock(). */
+ svn_error_t *(*body)(void *baton,
+ apr_pool_t *pool);
+
+ /* Baton to pass to BODY; possibly NULL.
+ This may be user-provided or a nested lock baton instance. */
+ void *baton;
+
+ /* Pool for all allocations along the lock chain and BODY. Will hold the
+ file locks and gets destroyed after the outermost BODY returned,
+ releasing all file locks.
+ Same for all instances along the chain. */
+ apr_pool_t *lock_pool;
+
+ /* TRUE, iff BODY is the user-provided body. */
+ svn_boolean_t is_inner_most_lock;
+
+ /* TRUE, iff this is not a nested lock.
+ Then responsible for destroying LOCK_POOL. */
+ svn_boolean_t is_outer_most_lock;
+} with_lock_baton_t;
+
+/* Obtain a write lock on the file BATON->LOCK_PATH and call BATON->BODY
+ with BATON->BATON. If this is the outermost lock call, release all file
+ locks after the body returned. If BATON->IS_GLOBAL_LOCK is set, set the
+ HAS_WRITE_LOCK flag while we keep the write lock. */
+static svn_error_t *
+with_some_lock_file(with_lock_baton_t *baton)
+{
+ apr_pool_t *pool = baton->lock_pool;
+ svn_error_t *err = get_lock_on_filesystem(baton->lock_path, pool);
if (!err)
{
+ svn_fs_t *fs = baton->fs;
fs_x_data_t *ffd = fs->fsap_data;
- if (is_global_lock)
+ if (baton->is_global_lock)
{
/* set the "got the lock" flag and register reset function */
- apr_pool_cleanup_register(subpool,
+ apr_pool_cleanup_register(pool,
ffd,
reset_lock_flag,
apr_pool_cleanup_null);
@@ -245,16 +291,151 @@ with_some_lock_file(svn_fs_t *fs,
/* nobody else will modify the repo state
=> read HEAD & pack info once */
- SVN_ERR(svn_fs_x__update_min_unpacked_rev(fs, pool));
- SVN_ERR(svn_fs_x__youngest_rev(&ffd->youngest_rev_cache, fs, pool));
- err = body(baton, subpool);
+ if (baton->is_inner_most_lock)
+ {
+ err = svn_fs_x__update_min_unpacked_rev(fs, pool);
+ if (!err)
+ err = svn_fs_x__youngest_rev(&ffd->youngest_rev_cache, fs, pool);
+ }
+
+ if (!err)
+ err = baton->body(baton->baton, pool);
}
- svn_pool_destroy(subpool);
+ if (baton->is_outer_most_lock)
+ svn_pool_destroy(pool);
return svn_error_trace(err);
}
+/* Wraps with_some_lock_file, protecting it with BATON->MUTEX.
+
+ POOL is unused here and only provided for signature compatibility with
+ WITH_LOCK_BATON_T.BODY. */
+static svn_error_t *
+with_lock(void *baton,
+ apr_pool_t *pool)
+{
+ with_lock_baton_t *lock_baton = baton;
+ SVN_MUTEX__WITH_LOCK(lock_baton->mutex, with_some_lock_file(lock_baton));
+
+ return SVN_NO_ERROR;
+}
+
+/* Enum identifying a filesystem lock. */
+typedef enum lock_id_t
+{
+ write_lock,
+ txn_lock,
+ pack_lock
+} lock_id_t;
+
+/* Initialize BATON->MUTEX, BATON->LOCK_PATH and BATON->IS_GLOBAL_LOCK
+ according to the LOCK_ID. All other members of BATON must already be
+ valid. */
+static void
+init_lock_baton(with_lock_baton_t *baton,
+ lock_id_t lock_id)
+{
+ fs_x_data_t *ffd = baton->fs->fsap_data;
+ fs_x_shared_data_t *ffsd = ffd->shared;
+
+ switch (lock_id)
+ {
+ case write_lock:
+ baton->mutex = ffsd->fs_write_lock;
+ baton->lock_path = svn_fs_x__path_lock(baton->fs, baton->lock_pool);
+ baton->is_global_lock = TRUE;
+ break;
+
+ case txn_lock:
+ baton->mutex = ffsd->txn_current_lock;
+ baton->lock_path = svn_fs_x__path_txn_current_lock(baton->fs,
+ baton->lock_pool);
+ baton->is_global_lock = FALSE;
+ break;
+
+ case pack_lock:
+ baton->mutex = ffsd->fs_pack_lock;
+ baton->lock_path = svn_fs_x__path_pack_lock(baton->fs,
+ baton->lock_pool);
+ baton->is_global_lock = FALSE;
+ break;
+ }
+}
+
+/* Return the baton for the innermost lock of a (potential) lock chain.
+ The baton shall take out LOCK_ID from FS and execute BODY with BATON
+ while the lock is being held. Allocate the result in a sub-pool of POOL.
+ */
+static with_lock_baton_t *
+create_lock_baton(svn_fs_t *fs,
+ lock_id_t lock_id,
+ svn_error_t *(*body)(void *baton,
+ apr_pool_t *pool),
+ void *baton,
+ apr_pool_t *pool)
+{
+ /* Allocate everything along the lock chain into a single sub-pool.
+ This minimizes memory usage and cleanup overhead. */
+ apr_pool_t *lock_pool = svn_pool_create(pool);
+ with_lock_baton_t *result = apr_pcalloc(lock_pool, sizeof(*result));
+
+ /* Store parameters. */
+ result->fs = fs;
+ result->body = body;
+ result->baton = baton;
+
+ /* File locks etc. will use this pool as well for easy cleanup. */
+ result->lock_pool = lock_pool;
+
+ /* Right now, we are the first, (only, ) and last struct in the chain. */
+ result->is_inner_most_lock = TRUE;
+ result->is_outer_most_lock = TRUE;
+
+ /* Select mutex and lock file path depending on LOCK_ID.
+ Also, initialize dependent members (IS_GLOBAL_LOCK only, ATM). */
+ init_lock_baton(result, lock_id);
+
+ return result;
+}
+
+/* Return a baton that wraps NESTED and requests LOCK_ID as additional lock.
+ *
+ * That means, when you create a lock chain, start with the last / innermost
+ * lock to take out and add the first / outermost lock last.
+ */
+static with_lock_baton_t *
+chain_lock_baton(lock_id_t lock_id,
+ with_lock_baton_t *nested)
+{
+ /* Use the same pool for batons along the lock chain. */
+ apr_pool_t *lock_pool = nested->lock_pool;
+ with_lock_baton_t *result = apr_pcalloc(lock_pool, sizeof(*result));
+
+ /* All locks along the chain operate on the same FS. */
+ result->fs = nested->fs;
+
+ /* Execution of this baton means acquiring the nested lock and its
+ execution. */
+ result->body = with_lock;
+ result->baton = nested;
+
+ /* Shared among all locks along the chain. */
+ result->lock_pool = lock_pool;
+
+ /* We are the new outermost lock but surely not the innermost lock. */
+ result->is_inner_most_lock = FALSE;
+ result->is_outer_most_lock = TRUE;
+ nested->is_outer_most_lock = FALSE;
+
+ /* Select mutex and lock file path depending on LOCK_ID.
+ Also, initialize dependent members (IS_GLOBAL_LOCK only, ATM). */
+ init_lock_baton(result, lock_id);
+
+ return result;
+}
+
svn_error_t *
svn_fs_x__with_write_lock(svn_fs_t *fs,
svn_error_t *(*body)(void *baton,
@@ -262,39 +443,57 @@ svn_fs_x__with_write_lock(svn_fs_t *fs,
void *baton,
apr_pool_t *pool)
{
- fs_x_data_t *ffd = fs->fsap_data;
- fs_x_shared_data_t *ffsd = ffd->shared;
+ return svn_error_trace(
+ with_lock(create_lock_baton(fs, write_lock, body, baton, pool),
+ pool));
+}
- SVN_MUTEX__WITH_LOCK(ffsd->fs_write_lock,
- with_some_lock_file(fs, body, baton,
- svn_fs_x__path_lock(fs, pool),
- TRUE,
- pool));
+svn_error_t *
+svn_fs_x__with_pack_lock(svn_fs_t *fs,
+ svn_error_t *(*body)(void *baton,
+ apr_pool_t *pool),
+ void *baton,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(
+ with_lock(create_lock_baton(fs, pack_lock, body, baton, pool),
+ pool));
+}
- return SVN_NO_ERROR;
+svn_error_t *
+svn_fs_x__with_txn_current_lock(svn_fs_t *fs,
+ svn_error_t *(*body)(void *baton,
+ apr_pool_t *pool),
+ void *baton,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(
+ with_lock(create_lock_baton(fs, txn_lock, body, baton, pool),
+ pool));
}
-/* Run BODY (with BATON and POOL) while the txn-current file
- of FS is locked. */
-static svn_error_t *
-with_txn_current_lock(svn_fs_t *fs,
- svn_error_t *(*body)(void *baton,
- apr_pool_t *pool),
- void *baton,
- apr_pool_t *pool)
+svn_error_t *
+svn_fs_x__with_all_locks(svn_fs_t *fs,
+ svn_error_t *(*body)(void *baton,
+ apr_pool_t *pool),
+ void *baton,
+ apr_pool_t *pool)
{
fs_x_data_t *ffd = fs->fsap_data;
- fs_x_shared_data_t *ffsd = ffd->shared;
- SVN_MUTEX__WITH_LOCK(ffsd->txn_current_lock,
- with_some_lock_file(fs, body, baton,
- svn_fs_x__path_txn_current_lock(fs, pool),
- FALSE,
- pool));
+ /* Be sure to use the correct lock ordering as documented in
+ fs_fs_shared_data_t. The lock chain is being created in
+ innermost (last to acquire) -> outermost (first to acquire) order. */
+ with_lock_baton_t *lock_baton
+ = create_lock_baton(fs, write_lock, body, baton, pool);
- return SVN_NO_ERROR;
+ lock_baton = chain_lock_baton(pack_lock, lock_baton);
+ lock_baton = chain_lock_baton(txn_lock, lock_baton);
+
+ return svn_error_trace(with_lock(lock_baton, pool));
}
+
/* A structure used by unlock_proto_rev() and unlock_proto_rev_body(),
which see. */
struct unlock_proto_rev_baton
@@ -1015,10 +1214,10 @@ create_txn_dir(const char **id_p,
number the transaction is based off into the transaction id. */
cb.pool = pool;
cb.fs = fs;
- SVN_ERR(with_txn_current_lock(fs,
- get_and_increment_txn_key_body,
- &cb,
- pool));
+ SVN_ERR(svn_fs_x__with_txn_current_lock(fs,
+ get_and_increment_txn_key_body,
+ &cb,
+ pool));
*txn_id = cb.txn_number;
*id_p = svn_fs_x__txn_name(*txn_id, pool);
Modified: subversion/trunk/subversion/libsvn_fs_x/transaction.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/transaction.h?rev=1595112&r1=1595111&r2=1595112&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/transaction.h (original)
+++ subversion/trunk/subversion/libsvn_fs_x/transaction.h Fri May 16 06:03:32 2014
@@ -40,6 +40,38 @@ svn_fs_x__with_write_lock(svn_fs_t *fs,
void *baton,
apr_pool_t *pool);
+/* Obtain a pack operation lock on the filesystem FS in a subpool of POOL,
+ call BODY with BATON and that subpool, destroy the subpool (releasing the
+ write lock) and return what BODY returned. */
+svn_error_t *
+svn_fs_x__with_pack_lock(svn_fs_t *fs,
+ svn_error_t *(*body)(void *baton,
+ apr_pool_t *pool),
+ void *baton,
+ apr_pool_t *pool);
+
+/* Run BODY (with BATON and POOL) while the txn-current file
+ of FS is locked. */
+svn_error_t *
+svn_fs_x__with_txn_current_lock(svn_fs_t *fs,
+ svn_error_t *(*body)(void *baton,
+ apr_pool_t *pool),
+ void *baton,
+ apr_pool_t *pool);
+
+/* Obtain all locks on the filesystem FS in a subpool of POOL, call BODY
+ with BATON and that subpool, destroy the subpool (releasing the locks)
+ and return what BODY returned.
+
+ This combines svn_fs_fs__with_write_lock, svn_fs_fs__with_pack_lock,
+ and svn_fs_fs__with_txn_current_lock, ensuring correct lock ordering. */
+svn_error_t *
+svn_fs_x__with_all_locks(svn_fs_t *fs,
+ svn_error_t *(*body)(void *baton,
+ apr_pool_t *pool),
+ void *baton,
+ apr_pool_t *pool);
+
/* Store NODEREV as the node-revision for the node whose id is ID in
FS, after setting its is_fresh_txn_root to FRESH_TXN_ROOT. Do any
necessary temporary allocation in POOL. */
Modified: subversion/trunk/subversion/libsvn_fs_x/util.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/util.c?rev=1595112&r1=1595111&r2=1595112&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/util.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/util.c Fri May 16 06:03:32 2014
@@ -125,6 +125,13 @@ svn_fs_x__path_lock(svn_fs_t *fs, apr_po
}
const char *
+svn_fs_x__path_pack_lock(svn_fs_t *fs,
+ apr_pool_t *pool)
+{
+ return svn_dirent_join(fs->path, PATH_PACK_LOCK_FILE, pool);
+}
+
+const char *
svn_fs_x__path_revprop_generation(svn_fs_t *fs, apr_pool_t *pool)
{
return svn_dirent_join(fs->path, PATH_REVPROP_GENERATION, pool);
Modified: subversion/trunk/subversion/libsvn_fs_x/util.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/util.h?rev=1595112&r1=1595111&r2=1595112&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/util.h (original)
+++ subversion/trunk/subversion/libsvn_fs_x/util.h Fri May 16 06:03:32 2014
@@ -107,6 +107,13 @@ const char *
svn_fs_x__path_lock(svn_fs_t *fs,
apr_pool_t *pool);
+/* Return the full path of the pack operation lock file in FS.
+ * The result will be allocated in POOL.
+ */
+const char *
+svn_fs_x__path_pack_lock(svn_fs_t *fs,
+ apr_pool_t *pool);
+
const char *
svn_fs_x__path_revprop_generation(svn_fs_t *fs,
apr_pool_t *pool);