Re: monitor exclusive lock when rbd client died abruptly

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 11:10 Wed 22 Jul, Ilya Dryomov wrote:
> On Wed, Jul 22, 2020 at 7:46 AM Liu, Changcheng
> <changcheng.liu@xxxxxxxxx> wrote:
> >
> > Hi all,
> >    I've checked below document:
> >    https://docs.ceph.com/docs/master/rbd/rbd-exclusive-locks/
> >
> >    The content is contradictory to the result shown in below experiment:
> >    The experient shows that another process could still write data to rbd
> >    volume while there already has a process write to the same rbd volume
> >    continuously.
> 
> This is the expected behaviour.  Exclusive lock is a cooperative
> mechanism that ensures that only a single client is able to write
> to the image and update its metadata (such as the object map)
> at any given moment, not until the client exits.  It is acquired
> automatically and the ownership is transparently transitioned between
> clients.  In your example, "second" wakes up and requests the lock
> from "first", "first" releases it, "second" performs its write,
> "first" reacquires the lock and goes on.
> 
> If you want to disable transparent lock transitions, you need to
> acquire the lock manually with RBD_LOCK_MODE_EXCLUSIVE:
@Ilya:
    Thanks for your info. The transparent lock transition could be
    disabled by acquring the lock with RBD_LOCK_MODE_EXCLUSIVE.

    After "first" process acquire the lock with "RBD_LOCK_MODE_EXCLUSIVE",
    is it possible for another process to be notified that the lock is
    released whatever the "first" process exit gracefully or be killed?

    I write below program to run "another process". If I manully remove
    the lock, "another process" could be notified. However, if the
    "first" process exit gracefully or be killed, "another process"'s
    handle_notify won't be called at all.
        1 #include <rbd/librbd.hpp>
        2 #include <rados/librados.hpp>
        3 
        4 #include <cstring>
        5 #include <iostream>
        6 #include <string>
        7 
        8 class TestWatcher {
        9 public:
       10     librados::Rados rados;
       11     librbd::RBD rbd;
       12     librbd::Image image;
       13     librados::IoCtx io_ctx;
       14 
       15     std::string pool_name;
       16     std::string image_name;
       17 
       18     TestWatcher(std::string pool_name = "rbd",
       19                 std::string image_name = "fio_test")
       20         : pool_name(pool_name), image_name(image_name) {
       21         int ret = rados.init("admin");
       22         if (ret < 0) {
       23             std::cout << "failed to initialize rados" << std::endl;
       24             exit(1);
       25         }
       26 
       27         ret = rados.conf_read_file("ceph.conf");
       28         if (ret < 0) {
       29             std::cout << "failed to parse ceph.conf" << std::endl;
       30             exit(1);
       31         }
       32 
       33         ret = rados.connect();
       34         if (ret < 0) {
       35             std::cout << "failed to connect to rados cluster" << std::endl;
       36             exit(1);
       37         }
       38 
       39         ret = rados.ioctx_create(pool_name.c_str(), io_ctx);
       40         if (ret < 0) {
       41             rados.shutdown();
       42             std::cout << "failed to create ioctx" << std::endl;
       43             exit(1);
       44         }
       45 
       46         ret = rbd.open(io_ctx, image, image_name.c_str());
       47         if (ret < 0) {
       48             io_ctx.close();
       49             rados.shutdown();
       50             std::cout << "failed to open rbd image" << std::endl;
       51             exit(1);
       52         } else {
       53             std::cout << "open image succeeded" << std::endl;
       54         }
       55     }
       56 
       57     ~TestWatcher() {
       58         image.close();
       59         io_ctx.close();
       60         rados.shutdown();
       61 
       62         if (watch_ctx != nullptr) {
       63             delete watch_ctx;
       64             watch_ctx = nullptr;
       65         }
       66     }
       67 
       68     class WatchCtx: public librbd::UpdateWatchCtx {
       69     private:
       70         TestWatcher &_test_watcher;
       71     public:
       72         explicit WatchCtx(TestWatcher &test_watcher):
       73             _test_watcher(test_watcher) {
       74         }
       75 
       76         int list_watchers() {
       77             std::list<librbd::image_watcher_t> watcher_list;
       78             int r = _test_watcher.image.list_watchers(watcher_list);
       79             if (r >= 0) {
       80                 for (auto it = watcher_list.cbegin(); it != watcher_list.cend(); ++it) {
       81                     std::cout << "addr: " << it->addr.c_str() << ", "
       82                               << "id: " << it->id << ", "
       83                               << "cookie: " << it->cookie << std::endl;
       84                 }
       85             }
       86             return r;
       87         }
       88 
       89         int list_lockers() {
       90             std::list<librbd::locker_t> lockers;
       91             std::string tag;
       92             bool exclusive;
       93             int r = _test_watcher.image.list_lockers(&lockers, &exclusive, &tag);
       94             if (r >= 0) {
       95               for (auto it = lockers.cbegin(); it != lockers.cend(); ++it) {
       96                     std::cout << "client: " << it->client.c_str() << ", "
       97                               << "cookie: " << it->cookie.c_str() << ", "
       98                               << "address: " << it->address.c_str() << std::endl;
       99               }
      100             }
      101             return r;
      102         }
      103         void handle_notify() override {
      104             std::cout << "event comming" << std::endl;
      105         }
      106     };
      107 
      108     int list_watchers() {
      109         watch_ctx = new WatchCtx(*this);
      110         int r = watch_ctx->list_watchers();
      111         delete watch_ctx;
      112         watch_ctx = nullptr;
      113         return r;
      114     }
      115 
      116     int list_lockers() {
      117         watch_ctx = new WatchCtx(*this);
      118         int r = watch_ctx->list_lockers();
      119         delete watch_ctx;
      120         watch_ctx = nullptr;
      121         return r;
      122     }
      123 
      124 
      125     int update_watch(uint64_t *phandle) {
      126         watch_ctx = new WatchCtx(*this);
      127         return image.update_watch(watch_ctx, phandle);
      128     }
      129     WatchCtx* watch_ctx = nullptr;
      130 };
      131 
      132 int main(void) {
      133     TestWatcher testwatcher;
      134     testwatcher.list_watchers();
      135     testwatcher.list_lockers();
      136     uint64_t handle = 0;
      137     testwatcher.update_watch(&handle);
      138     while(1);
      139 }

B.R.
Changcheng
> 
> 
> Thanks,
> 
>                 Ilya
_______________________________________________
Dev mailing list -- dev@xxxxxxx
To unsubscribe send an email to dev-leave@xxxxxxx



[Index of Archives]     [CEPH Users]     [Ceph Devel]     [Ceph Large]     [Information on CEPH]     [Linux BTRFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux