Re: monitor exclusive lock when rbd client died abruptly

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

 



On Wed, Jul 22, 2020 at 12:34 PM Liu, Changcheng
<changcheng.liu@xxxxxxxxx> wrote:
>
> 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?

No.  Theoretically, "second" could block, waiting for the lock
to be released by "first" (whether gracefully or not), but I don't
think librbd does that.  (And if it did, it would have been based
on periodic retries, not notifies, because if the process is killed
there is nowhere for that notify to come from.)

>
>     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.

If you are going to use exclusive lock API, you shouldn't be
poking at the underlying watches and notifies.

>         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 }

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