diff --git a/hgext/share.py b/hgext/share.py
--- a/hgext/share.py
+++ b/hgext/share.py
@@ -125,6 +125,10 @@
 
 def _hassharedbookmarks(repo):
     """Returns whether this repo has shared bookmarks"""
+    if bookmarks.bookmarksinstore(repo):
+        # Kind of a lie, but it means that we skip our custom reads and writes
+        # from/to the source repo.
+        return False
     try:
         shared = repo.vfs.read('shared').splitlines()
     except IOError as inst:
diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py
--- a/mercurial/bookmarks.py
+++ b/mercurial/bookmarks.py
@@ -33,6 +33,14 @@
 # custom styles
 activebookmarklabel = 'bookmarks.active bookmarks.current'
 
+BOOKMARKS_IN_STORE_REQUIREMENT = 'bookmarksinstore'
+
+def bookmarksinstore(repo):
+    return BOOKMARKS_IN_STORE_REQUIREMENT in repo.requirements
+
+def bookmarksvfs(repo):
+    return repo.svfs if bookmarksinstore(repo) else repo.vfs
+
 def _getbkfile(repo):
     """Hook so that extensions that mess with the store can hook bm storage.
 
@@ -40,7 +48,7 @@
     bookmarks or the committed ones. Other extensions (like share)
     may need to tweak this behavior further.
     """
-    fp, pending = txnutil.trypending(repo.root, repo.vfs, 'bookmarks')
+    fp, pending = txnutil.trypending(repo.root, bookmarksvfs(repo), 'bookmarks')
     return fp
 
 class bmstore(object):
@@ -91,8 +99,11 @@
                         # ValueError:
                         # - node in nm, for non-20-bytes entry
                         # - split(...), for string without ' '
-                        repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n')
-                                     % pycompat.bytestr(line))
+                        bookmarkspath = '.hg/bookmarks'
+                        if bookmarksinstore(repo):
+                            bookmarkspath = '.hg/store/bookmarks'
+                        repo.ui.warn(_('malformed line in %s: %r\n')
+                                     % (bookmarkspath, pycompat.bytestr(line)))
         except IOError as inst:
             if inst.errno != errno.ENOENT:
                 raise
@@ -192,8 +203,9 @@
         """record that bookmarks have been changed in a transaction
 
         The transaction is then responsible for updating the file content."""
+        location = '' if bookmarksinstore(self._repo) else 'plain'
         tr.addfilegenerator('bookmarks', ('bookmarks',), self._write,
-                            location='plain')
+                            location=location)
         tr.hookargs['bookmark_moved'] = '1'
 
     def _writerepo(self, repo):
@@ -203,9 +215,14 @@
             rbm.active = None
             rbm._writeactive()
 
-        with repo.wlock():
-            with repo.vfs('bookmarks', 'w', atomictemp=True,
-                          checkambig=True) as f:
+        if bookmarksinstore(repo):
+            vfs = repo.svfs
+            lock = repo.lock()
+        else:
+            vfs = repo.vfs
+            lock = repo.wlock()
+        with lock:
+            with vfs('bookmarks', 'w', atomictemp=True, checkambig=True) as f:
                 self._write(f)
 
     def _writeactive(self):
@@ -428,7 +445,11 @@
     return d
 
 def pushbookmark(repo, key, old, new):
-    with repo.wlock(), repo.lock(), repo.transaction('bookmarks') as tr:
+    if bookmarksinstore(repo):
+        wlock = util.nullcontextmanager()
+    else:
+        wlock = repo.wlock()
+    with wlock, repo.lock(), repo.transaction('bookmarks') as tr:
         marks = repo._bookmarks
         existing = hex(marks.get(key, ''))
         if existing != old and existing != new:
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -676,6 +676,9 @@
     default=None,
     generic=True,
 )
+coreconfigitem('format', 'bookmarks-in-store',
+    default=False,
+)
 coreconfigitem('format', 'chunkcachesize',
     default=None,
 )
diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
--- a/mercurial/help/config.txt
+++ b/mercurial/help/config.txt
@@ -879,6 +879,15 @@
 
     On some system, Mercurial installation may lack `zstd` supports. Default is `zlib`.
 
+``bookmarks-in-store``
+    Store bookmarks in .hg/store/. This means that bookmarks are shared when
+    using `hg share` regardless of the `-B` option.
+
+    Repositories with this on-disk format require Mercurial version 5.1.
+
+    Disabled by default.
+
+
 ``graph``
 ---------
 
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -122,6 +122,25 @@
     def join(self, obj, fname):
         return obj.sjoin(fname)
 
+class mixedrepostorecache(_basefilecache):
+    """filecache for a mix files in .hg/store and outside"""
+    def __init__(self, *pathsandlocations):
+        # scmutil.filecache only uses the path for passing back into our
+        # join(), so we can safely pass a list of paths and locations
+        super(mixedrepostorecache, self).__init__(*pathsandlocations)
+        for path, location in pathsandlocations:
+            _cachedfiles.update(pathsandlocations)
+
+    def join(self, obj, fnameandlocation):
+        fname, location = fnameandlocation
+        if location == '':
+            return obj.vfs.join(fname)
+        else:
+            if location != 'store':
+                raise error.ProgrammingError('unexpected location: %s' %
+                                             location)
+            return obj.sjoin(fname)
+
 def isfilecached(repo, name):
     """check if a repo has already cached "name" filecache-ed property
 
@@ -891,6 +910,7 @@
         'treemanifest',
         REVLOGV2_REQUIREMENT,
         SPARSEREVLOG_REQUIREMENT,
+        bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT,
     }
     _basesupported = supportedformats | {
         'store',
@@ -1205,7 +1225,8 @@
         cls = repoview.newtype(self.unfiltered().__class__)
         return cls(self, name, visibilityexceptions)
 
-    @repofilecache('bookmarks', 'bookmarks.current')
+    @mixedrepostorecache(('bookmarks', ''), ('bookmarks.current', ''),
+                         ('bookmarks', 'store'))
     def _bookmarks(self):
         return bookmarks.bmstore(self)
 
@@ -1962,7 +1983,7 @@
                 (self.vfs, 'journal.dirstate'),
                 (self.vfs, 'journal.branch'),
                 (self.vfs, 'journal.desc'),
-                (self.vfs, 'journal.bookmarks'),
+                (bookmarks.bookmarksvfs(self), 'journal.bookmarks'),
                 (self.svfs, 'journal.phaseroots'))
 
     def undofiles(self):
@@ -1977,8 +1998,9 @@
                           encoding.fromlocal(self.dirstate.branch()))
         self.vfs.write("journal.desc",
                           "%d\n%s\n" % (len(self), desc))
-        self.vfs.write("journal.bookmarks",
-                          self.vfs.tryread("bookmarks"))
+        bookmarksvfs = bookmarks.bookmarksvfs(self)
+        bookmarksvfs.write("journal.bookmarks",
+                           bookmarksvfs.tryread("bookmarks"))
         self.svfs.write("journal.phaseroots",
                            self.svfs.tryread("phaseroots"))
 
@@ -2048,8 +2070,9 @@
         vfsmap = {'plain': self.vfs, '': self.svfs}
         transaction.rollback(self.svfs, vfsmap, 'undo', ui.warn,
                              checkambigfiles=_cachedfiles)
-        if self.vfs.exists('undo.bookmarks'):
-            self.vfs.rename('undo.bookmarks', 'bookmarks', checkambig=True)
+        bookmarksvfs = bookmarks.bookmarksvfs(self)
+        if bookmarksvfs.exists('undo.bookmarks'):
+            bookmarksvfs.rename('undo.bookmarks', 'bookmarks', checkambig=True)
         if self.svfs.exists('undo.phaseroots'):
             self.svfs.rename('undo.phaseroots', 'phaseroots', checkambig=True)
         self.invalidate()
@@ -3003,6 +3026,9 @@
     if createopts.get('lfs'):
         requirements.add('lfs')
 
+    if ui.configbool('format', 'bookmarks-in-store'):
+        requirements.add(bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT)
+
     return requirements
 
 def filterknowncreateopts(ui, createopts):
diff --git a/mercurial/store.py b/mercurial/store.py
--- a/mercurial/store.py
+++ b/mercurial/store.py
@@ -337,7 +337,7 @@
         mode = None
     return mode
 
-_data = ('narrowspec data meta 00manifest.d 00manifest.i'
+_data = ('bookmarks narrowspec data meta 00manifest.d 00manifest.i'
          ' 00changelog.d 00changelog.i phaseroots obsstore')
 
 def isrevlog(f, kind, st):
@@ -612,7 +612,7 @@
                     raise
 
     def copylist(self):
-        d = ('narrowspec data meta dh fncache phaseroots obsstore'
+        d = ('bookmarks narrowspec data meta dh fncache phaseroots obsstore'
              ' 00manifest.d 00manifest.i 00changelog.d 00changelog.i')
         return (['requires', '00changelog.i'] +
                 ['store/' + f for f in d.split()])
diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -1513,6 +1513,8 @@
   
       "revlog-compression"
   
+      "bookmarks-in-store"
+  
       "profiling"
       -----------
   
diff --git a/tests/test-share-bookmarks.t b/tests/test-share-bookmarks.t
--- a/tests/test-share-bookmarks.t
+++ b/tests/test-share-bookmarks.t
@@ -1,6 +1,13 @@
+#testcases vfs svfs
+
   $ echo "[extensions]"      >> $HGRCPATH
   $ echo "share = "          >> $HGRCPATH
 
+#if svfs
+  $ echo "[format]"                  >> $HGRCPATH
+  $ echo "bookmarks-in-store = yes " >> $HGRCPATH
+#endif
+
 prepare repo1
 
   $ hg init repo1
@@ -33,17 +40,21 @@
   $ cd ../repo2
   $ hg book bm2
   $ hg bookmarks
+     bm1                       2:c2e0ac586386 (svfs !)
    * bm2                       2:c2e0ac586386
   $ cd ../repo3
   $ hg bookmarks
      bm1                       2:c2e0ac586386
+     bm2                       2:c2e0ac586386 (svfs !)
   $ hg book bm3
   $ hg bookmarks
      bm1                       2:c2e0ac586386
+     bm2                       2:c2e0ac586386 (svfs !)
    * bm3                       2:c2e0ac586386
   $ cd ../repo1
   $ hg bookmarks
    * bm1                       2:c2e0ac586386
+     bm2                       2:c2e0ac586386 (svfs !)
      bm3                       2:c2e0ac586386
 
 check whether HG_PENDING makes pending changes only in relatd
@@ -70,14 +81,18 @@
   $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX
   @repo1
      bm1                       2:c2e0ac586386
+     bm2                       2:c2e0ac586386 (svfs !)
      bm3                       2:c2e0ac586386
    * bmX                       2:c2e0ac586386
   @repo2
+     bm1                       2:c2e0ac586386 (svfs !)
    * bm2                       2:c2e0ac586386
+     bm3                       2:c2e0ac586386 (svfs !)
   @repo3
      bm1                       2:c2e0ac586386
+     bm2                       2:c2e0ac586386 (svfs !)
    * bm3                       2:c2e0ac586386
-     bmX                       2:c2e0ac586386
+     bmX                       2:c2e0ac586386 (vfs !)
   transaction abort!
   rollback completed
   abort: pretxnclose hook exited with status 1
@@ -92,11 +107,15 @@
   $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX
   @repo1
    * bm1                       2:c2e0ac586386
+     bm2                       2:c2e0ac586386 (svfs !)
      bm3                       2:c2e0ac586386
   @repo2
+     bm1                       2:c2e0ac586386 (svfs !)
    * bm2                       2:c2e0ac586386
+     bm3                       2:c2e0ac586386 (svfs !)
   @repo3
      bm1                       2:c2e0ac586386
+     bm2                       2:c2e0ac586386 (svfs !)
      bm3                       2:c2e0ac586386
    * bmX                       2:c2e0ac586386
   transaction abort!
@@ -105,6 +124,11 @@
   [255]
   $ hg book bm3
 
+clean up bm2 since it's uninteresting (not shared in the vfs case and
+same as bm3 in the svfs case)
+  $ cd ../repo2
+  $ hg book -d bm2
+
   $ cd ../repo1
 
 test that commits work