Compare commits

...
28 changed files with 293 additions and 101 deletions
+14
View File
@@ -13,6 +13,7 @@ affect their interaction with the cluster.
- [client_retry_interval](#client_retry_interval) - [client_retry_interval](#client_retry_interval)
- [client_eio_retry_interval](#client_eio_retry_interval) - [client_eio_retry_interval](#client_eio_retry_interval)
- [client_retry_enospc](#client_retry_enospc) - [client_retry_enospc](#client_retry_enospc)
- [client_wait_up_timeout](#client_wait_up_timeout)
- [client_max_dirty_bytes](#client_max_dirty_bytes) - [client_max_dirty_bytes](#client_max_dirty_bytes)
- [client_max_dirty_ops](#client_max_dirty_ops) - [client_max_dirty_ops](#client_max_dirty_ops)
- [client_enable_writeback](#client_enable_writeback) - [client_enable_writeback](#client_enable_writeback)
@@ -70,6 +71,19 @@ and clients are not blocked and just get EIO error code instead.
Retry writes on out of space errors to wait until some space is freed on Retry writes on out of space errors to wait until some space is freed on
OSDs. OSDs.
## client_wait_up_timeout
- Type: seconds
- Default: 16
- Can be changed online: yes
Wait for this number of seconds until PGs are up when doing operations
which require all PGs to be up. Currently only used by object listings
in delete and merge-based commands ([vitastor-cli rm](../usage/cli.en.md#rm), merge and so on).
The default value is calculated as `1 + OSD lease timeout`, which is
`1 + etcd_report_interval + max_etcd_attempts*2*etcd_quick_timeout`.
## client_max_dirty_bytes ## client_max_dirty_bytes
- Type: integer - Type: integer
+14
View File
@@ -13,6 +13,7 @@
- [client_retry_interval](#client_retry_interval) - [client_retry_interval](#client_retry_interval)
- [client_eio_retry_interval](#client_eio_retry_interval) - [client_eio_retry_interval](#client_eio_retry_interval)
- [client_retry_enospc](#client_retry_enospc) - [client_retry_enospc](#client_retry_enospc)
- [client_wait_up_timeout](#client_wait_up_timeout)
- [client_max_dirty_bytes](#client_max_dirty_bytes) - [client_max_dirty_bytes](#client_max_dirty_bytes)
- [client_max_dirty_ops](#client_max_dirty_ops) - [client_max_dirty_ops](#client_max_dirty_ops)
- [client_enable_writeback](#client_enable_writeback) - [client_enable_writeback](#client_enable_writeback)
@@ -72,6 +73,19 @@ RDMA и хотите повысить пиковую производитель
Повторять запросы записи, завершившиеся с ошибками нехватки места, т.е. Повторять запросы записи, завершившиеся с ошибками нехватки места, т.е.
ожидать, пока на OSD не освободится место. ожидать, пока на OSD не освободится место.
## client_wait_up_timeout
- Тип: секунды
- Значение по умолчанию: 16
- Можно менять на лету: да
Время ожидания поднятия PG при операциях, требующих активности всех PG.
В данный момент используется листингами объектов в командах, использующих
удаление и слияние ([vitastor-cli rm](../usage/cli.ru.md#rm), merge и подобные).
Значение по умолчанию вычисляется как `1 + время lease OSD`, равное
`1 + etcd_report_interval + max_etcd_attempts*2*etcd_quick_timeout`.
## client_max_dirty_bytes ## client_max_dirty_bytes
- Тип: целое число - Тип: целое число
+1 -1
View File
@@ -316,7 +316,7 @@ for hot data and slower disks - HDDs and maybe SATA SSDs - but will slightly
decrease write performance for fast disks because page cache is an overhead decrease write performance for fast disks because page cache is an overhead
itself. itself.
Choose "directsync" to use [immediate_commit](layout-cluster.ru.md#immediate_commit) Choose "directsync" to use [immediate_commit](layout-cluster.en.md#immediate_commit)
(which requires disable_data_fsync) with drives having write-back cache (which requires disable_data_fsync) with drives having write-back cache
which can't be turned off, for example, Intel Optane. Also note that *some* which can't be turned off, for example, Intel Optane. Also note that *some*
desktop SSDs (for example, HP EX950) may ignore O_SYNC thus making desktop SSDs (for example, HP EX950) may ignore O_SYNC thus making
+23 -10
View File
@@ -43,7 +43,7 @@ Parameters:
- [osd_tags](#osd_tags) - [osd_tags](#osd_tags)
- [primary_affinity_tags](#primary_affinity_tags) - [primary_affinity_tags](#primary_affinity_tags)
- [scrub_interval](#scrub_interval) - [scrub_interval](#scrub_interval)
- [used_for_fs](#used_for_fs) - [used_for_app](#used_for_app)
Examples: Examples:
@@ -377,24 +377,37 @@ of the OSDs containing a data chunk for a PG.
Automatic scrubbing interval for this pool. Overrides Automatic scrubbing interval for this pool. Overrides
[global scrub_interval setting](osd.en.md#scrub_interval). [global scrub_interval setting](osd.en.md#scrub_interval).
## used_for_fs ## used_for_app
- Type: string - Type: string
If non-empty, the pool is marked as used for VitastorFS with metadata stored If non-empty, the pool is marked as used for a separate application, for example,
in block image (regular Vitastor volume) named as the value of this pool parameter. VitastorFS or S3, which allocates Vitastor volume IDs by itself and does not use
image/inode metadata in etcd.
When a pool is marked as used for VitastorFS, regular block volume creation in it When a pool is marked as used for such app, regular block volume creation in it
is disabled (vitastor-cli refuses to create images without --force) to protect is disabled (vitastor-cli refuses to create images without --force) to protect
the user from block volume and FS file ID collisions and data loss. the user from block volume and FS/S3 volume ID collisions and data loss.
[vitastor-nfs](../usage/nfs.ru.md), in its turn, refuses to use pools not marked Also such pools do not calculate per-inode space usage statistics in etcd because
using it for an external application implies that it may contain a very large
number of volumes and their statistics may take too much space in etcd.
Setting used_for_app to `fs:<name>` tells Vitastor that the pool is used for VitastorFS
with VitastorKV metadata base stored in a block image (regular Vitastor volume) named
`<name>`.
[vitastor-nfs](../usage/nfs.en.md), in its turn, refuses to use pools not marked
for the corresponding FS when starting. This also implies that you can use one for the corresponding FS when starting. This also implies that you can use one
pool only for one VitastorFS. pool only for one VitastorFS.
The second thing that is disabled for VitastorFS pools is reporting per-inode space If you plan to use the pool for S3, set its used_for_app to `s3:<name>`. `<name>` may
usage statistics in etcd because a FS pool may store a very large number of files be basically anything you want (for example, `s3:standard`) - it's not validated
and statistics for them all would take a lot of space in etcd. by Vitastor S3 components in any way.
All other values except prefixed with `fs:` or `s3:` may be used freely and don't
mean anything special for Vitastor core components. For now, you can use them as
you wish.
# Examples # Examples
+29 -16
View File
@@ -42,7 +42,7 @@
- [osd_tags](#osd_tags) - [osd_tags](#osd_tags)
- [primary_affinity_tags](#primary_affinity_tags) - [primary_affinity_tags](#primary_affinity_tags)
- [scrub_interval](#scrub_interval) - [scrub_interval](#scrub_interval)
- [used_for_fs](#used_for_fs) - [used_for_app](#used_for_app)
Примеры: Примеры:
@@ -256,7 +256,7 @@ PG в Vitastor эферемерны, то есть вы можете менят
## raw_placement ## raw_placement
- Type: string - Тип: строка
Низкоуровневые правила генерации PG в форме DSL (доменно-специфичного языка). Низкоуровневые правила генерации PG в форме DSL (доменно-специфичного языка).
Используйте, только если действительно знаете, зачем вам это надо :) Используйте, только если действительно знаете, зачем вам это надо :)
@@ -383,26 +383,39 @@ OSD с "all".
Интервал скраба, то есть, автоматической фоновой проверки данных для данного пула. Интервал скраба, то есть, автоматической фоновой проверки данных для данного пула.
Переопределяет [глобальную настройку scrub_interval](osd.ru.md#scrub_interval). Переопределяет [глобальную настройку scrub_interval](osd.ru.md#scrub_interval).
## used_for_fs ## used_for_app
- Type: string - Тип: строка
Если непусто, пул помечается как используемый для файловой системы VitastorFS с Если непусто, пул помечается как используемый для отдельного приложения, например,
метаданными, хранимыми в блочном образе Vitastor с именем, равным значению для VitastorFS или S3, которое распределяет ID образов в пуле само и не использует
этого параметра. метаданные образов/инодов в etcd.
Когда пул помечается как используемый для VitastorFS, создание обычных блочных Когда пул помечается используемым для такого приложения, создание обычных блочных
образов в нём отключается (vitastor-cli отказывается создавать образы без --force), образов в нём запрещается (vitastor-cli отказывается создавать образы без --force),
чтобы защитить пользователя от коллизий ID файлов и блочных образов и, таким чтобы защитить пользователя от коллизий ID блочных образов и томов ФС/S3, и,
образом, от потери данных. таким образом, от потери данных.
Также для таких пулов отключается передача статистики в etcd по отдельным инодам,
так как использование для внешнего приложения подразумевает, что пул может содержать
очень много томов и их статистика может занять слишком много места в etcd.
Установка used_for_app в значение `fs:<name>` сообщает о том, что пул используется
для VitastorFS с базой метаданных VitastorKV, хранимой в блочном образе с именем
`<name>`.
[vitastor-nfs](../usage/nfs.ru.md), в свою очередь, при запуске отказывается [vitastor-nfs](../usage/nfs.ru.md), в свою очередь, при запуске отказывается
использовать для ФС пулы, не выделенные для неё. Это также означает, что один использовать для ФС пулы, не помеченные, как используемые для неё. Это также
пул может использоваться только для одной VitastorFS. означает, что один пул может использоваться только для одной VitastorFS.
Также для ФС-пулов отключается передача статистики в etcd по отдельным инодам, Если же вы планируете использовать пул для данных S3, установите его used_for_app
так как ФС-пул может содержать очень много файлов и статистика по ним всем в значение `s3:<name>`, где `<name>` - любое название по вашему усмотрению
заняла бы очень много места в etcd. (например, `s3:standard`) - конкретное содержимое `<name>` пока никак не проверяется
компонентами Vitastor S3.
Все остальные значения used_for_app, кроме начинающихся на `fs:` или `s3:`, не
означают ничего особенного для основных компонентов Vitastor. Поэтому сейчас вы
можете использовать их свободно любым желаемым способом.
# Примеры # Примеры
+1 -1
View File
@@ -315,7 +315,7 @@
decrease write performance for fast disks because page cache is an overhead decrease write performance for fast disks because page cache is an overhead
itself. itself.
Choose "directsync" to use [immediate_commit](layout-cluster.ru.md#immediate_commit) Choose "directsync" to use [immediate_commit](layout-cluster.en.md#immediate_commit)
(which requires disable_data_fsync) with drives having write-back cache (which requires disable_data_fsync) with drives having write-back cache
which can't be turned off, for example, Intel Optane. Also note that *some* which can't be turned off, for example, Intel Optane. Also note that *some*
desktop SSDs (for example, HP EX950) may ignore O_SYNC thus making desktop SSDs (for example, HP EX950) may ignore O_SYNC thus making
+2 -1
View File
@@ -398,7 +398,8 @@ Optional parameters:
| `--raw_placement <rules>` | Specify raw PG generation rules ([details](../config/pool.en.md#raw_placement)) | | `--raw_placement <rules>` | Specify raw PG generation rules ([details](../config/pool.en.md#raw_placement)) |
| `--primary_affinity_tags tags` | Prefer to put primary copies on OSDs with all specified tags | | `--primary_affinity_tags tags` | Prefer to put primary copies on OSDs with all specified tags |
| `--scrub_interval <time>` | Enable regular scrubbing for this pool. Format: number + unit s/m/h/d/M/y | | `--scrub_interval <time>` | Enable regular scrubbing for this pool. Format: number + unit s/m/h/d/M/y |
| `--used_for_fs <name>` | Mark pool as used for VitastorFS with metadata in image <name> | | `--used_for_app fs:<name>` | Mark pool as used for VitastorFS with metadata in image `<name>` |
| `--used_for_app s3:<name>` | Mark pool as used for S3 location with name `<name>` |
| `--pg_stripe_size <number>` | Increase object grouping stripe | | `--pg_stripe_size <number>` | Increase object grouping stripe |
| `--max_osd_combinations 10000` | Maximum number of random combinations for LP solver input | | `--max_osd_combinations 10000` | Maximum number of random combinations for LP solver input |
| `--wait` | Wait for the new pool to come online | | `--wait` | Wait for the new pool to come online |
+1 -1
View File
@@ -58,7 +58,7 @@ To use VitastorFS:
2. Create an image for FS metadata, preferably in a faster (SSD or replica-HDD) pool, 2. Create an image for FS metadata, preferably in a faster (SSD or replica-HDD) pool,
but you can create it in the data pool too if you want (image size doesn't matter): but you can create it in the data pool too if you want (image size doesn't matter):
`vitastor-cli create -s 10G -p fastpool testfs` `vitastor-cli create -s 10G -p fastpool testfs`
3. Mark data pool as an FS pool: `vitastor-cli modify-pool --used-for-fs testfs data-pool` 3. Mark data pool as an FS pool: `vitastor-cli modify-pool --used-for-app fs:testfs data-pool`
4. Either mount the FS: `vitastor-nfs mount --fs testfs --pool data-pool /mnt/vita` 4. Either mount the FS: `vitastor-nfs mount --fs testfs --pool data-pool /mnt/vita`
5. Or start the NFS server: `vitastor-nfs start --fs testfs --pool data-pool` 5. Or start the NFS server: `vitastor-nfs start --fs testfs --pool data-pool`
+1 -1
View File
@@ -60,7 +60,7 @@ JSON-формате :-). Для инспекции содержимого БД
или по крайней мере на HDD, но без EC), но можно и в том же пуле, что данные или по крайней мере на HDD, но без EC), но можно и в том же пуле, что данные
(размер образа значения не имеет): (размер образа значения не имеет):
`vitastor-cli create -s 10G -p fastpool testfs` `vitastor-cli create -s 10G -p fastpool testfs`
3. Пометьте пул данных как ФС-пул: `vitastor-cli modify-pool --used-for-fs testfs data-pool` 3. Пометьте пул данных как ФС-пул: `vitastor-cli modify-pool --used-for-app fs:testfs data-pool`
4. Либо примонтируйте ФС: `vitastor-nfs mount --fs testfs --pool data-pool /mnt/vita` 4. Либо примонтируйте ФС: `vitastor-nfs mount --fs testfs --pool data-pool /mnt/vita`
5. Либо запустите сетевой NFS-сервер: `vitastor-nfs start --fs testfs --pool data-pool` 5. Либо запустите сетевой NFS-сервер: `vitastor-nfs start --fs testfs --pool data-pool`
+36
View File
@@ -155,7 +155,9 @@ NAN_METHOD(NodeVitastor::Read)
self->Ref(); self->Ref();
vitastor_c_read(self->c, ((pool << (64-POOL_ID_BITS)) | inode), req->offset, req->len, &req->iov, 1, on_read_finish, req); vitastor_c_read(self->c, ((pool << (64-POOL_ID_BITS)) | inode), req->offset, req->len, &req->iov, 1, on_read_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(self->c); vitastor_c_uring_handle_events(self->c);
#endif
} }
NodeVitastorRequest* NodeVitastor::get_write_request(const Nan::FunctionCallbackInfo<v8::Value> & info, int argpos) NodeVitastorRequest* NodeVitastor::get_write_request(const Nan::FunctionCallbackInfo<v8::Value> & info, int argpos)
@@ -224,7 +226,9 @@ NAN_METHOD(NodeVitastor::Write)
req->iov_list.size() ? req->iov_list.data() : &req->iov, req->iov_list.size() ? req->iov_list.data() : &req->iov,
req->iov_list.size() ? req->iov_list.size() : 1, req->iov_list.size() ? req->iov_list.size() : 1,
on_write_finish, req); on_write_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(self->c); vitastor_c_uring_handle_events(self->c);
#endif
} }
NodeVitastorRequest* NodeVitastor::get_delete_request(const Nan::FunctionCallbackInfo<v8::Value> & info, int argpos) NodeVitastorRequest* NodeVitastor::get_delete_request(const Nan::FunctionCallbackInfo<v8::Value> & info, int argpos)
@@ -271,7 +275,9 @@ NAN_METHOD(NodeVitastor::Delete)
self->Ref(); self->Ref();
vitastor_c_delete(self->c, ((pool << (64-POOL_ID_BITS)) | inode), req->offset, req->len, req->version, vitastor_c_delete(self->c, ((pool << (64-POOL_ID_BITS)) | inode), req->offset, req->len, req->version,
on_write_finish, req); on_write_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(self->c); vitastor_c_uring_handle_events(self->c);
#endif
} }
// sync(callback(err)) // sync(callback(err))
@@ -288,7 +294,9 @@ NAN_METHOD(NodeVitastor::Sync)
self->Ref(); self->Ref();
vitastor_c_sync(self->c, on_write_finish, req); vitastor_c_sync(self->c, on_write_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(self->c); vitastor_c_uring_handle_events(self->c);
#endif
} }
// read_bitmap(pool, inode, offset, length, with_parents, callback(err, bitmap_buffer)) // read_bitmap(pool, inode, offset, length, with_parents, callback(err, bitmap_buffer))
@@ -310,7 +318,9 @@ NAN_METHOD(NodeVitastor::ReadBitmap)
auto req = new NodeVitastorRequest(self, callback); auto req = new NodeVitastorRequest(self, callback);
self->Ref(); self->Ref();
vitastor_c_read_bitmap(self->c, ((pool << (64-POOL_ID_BITS)) | inode), offset, len, with_parents, on_read_bitmap_finish, req); vitastor_c_read_bitmap(self->c, ((pool << (64-POOL_ID_BITS)) | inode), offset, len, with_parents, on_read_bitmap_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(self->c); vitastor_c_uring_handle_events(self->c);
#endif
} }
static void on_error(NodeVitastorRequest *req, Nan::Callback & nanCallback, long retval) static void on_error(NodeVitastorRequest *req, Nan::Callback & nanCallback, long retval)
@@ -335,7 +345,9 @@ NAN_METHOD(NodeVitastor::OnReady)
auto req = new NodeVitastorRequest(self, callback); auto req = new NodeVitastorRequest(self, callback);
self->Ref(); self->Ref();
vitastor_c_on_ready(self->c, on_ready_finish, req); vitastor_c_on_ready(self->c, on_ready_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(self->c); vitastor_c_uring_handle_events(self->c);
#endif
} }
void NodeVitastor::on_ready_finish(void *opaque, long retval) void NodeVitastor::on_ready_finish(void *opaque, long retval)
@@ -480,7 +492,9 @@ NAN_METHOD(NodeVitastorImage::Create)
img->Ref(); img->Ref();
cli->Ref(); cli->Ref();
vitastor_c_watch_inode(cli->c, (char*)img->name.c_str(), on_watch_start, img); vitastor_c_watch_inode(cli->c, (char*)img->name.c_str(), on_watch_start, img);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(cli->c); vitastor_c_uring_handle_events(cli->c);
#endif
info.GetReturnValue().Set(info.This()); info.GetReturnValue().Set(info.This());
} }
@@ -621,7 +635,9 @@ void NodeVitastorImage::exec_request(NodeVitastorRequest *req)
uint64_t ino = vitastor_c_inode_get_num(watch); uint64_t ino = vitastor_c_inode_get_num(watch);
cli->Ref(); cli->Ref();
vitastor_c_read(cli->c, ino, req->offset, req->len, &req->iov, 1, NodeVitastor::on_read_finish, req); vitastor_c_read(cli->c, ino, req->offset, req->len, &req->iov, 1, NodeVitastor::on_read_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(cli->c); vitastor_c_uring_handle_events(cli->c);
#endif
} }
else if (req->op == NODE_VITASTOR_WRITE) else if (req->op == NODE_VITASTOR_WRITE)
{ {
@@ -631,7 +647,9 @@ void NodeVitastorImage::exec_request(NodeVitastorRequest *req)
req->iov_list.size() ? req->iov_list.data() : &req->iov, req->iov_list.size() ? req->iov_list.data() : &req->iov,
req->iov_list.size() ? req->iov_list.size() : 1, req->iov_list.size() ? req->iov_list.size() : 1,
NodeVitastor::on_write_finish, req); NodeVitastor::on_write_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(cli->c); vitastor_c_uring_handle_events(cli->c);
#endif
} }
else if (req->op == NODE_VITASTOR_DELETE) else if (req->op == NODE_VITASTOR_DELETE)
{ {
@@ -639,7 +657,9 @@ void NodeVitastorImage::exec_request(NodeVitastorRequest *req)
cli->Ref(); cli->Ref();
vitastor_c_delete(cli->c, ino, req->offset, req->len, req->version, vitastor_c_delete(cli->c, ino, req->offset, req->len, req->version,
NodeVitastor::on_write_finish, req); NodeVitastor::on_write_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(cli->c); vitastor_c_uring_handle_events(cli->c);
#endif
} }
else if (req->op == NODE_VITASTOR_SYNC) else if (req->op == NODE_VITASTOR_SYNC)
{ {
@@ -649,7 +669,9 @@ void NodeVitastorImage::exec_request(NodeVitastorRequest *req)
if (imm != IMMEDIATE_ALL) if (imm != IMMEDIATE_ALL)
{ {
vitastor_c_sync(cli->c, NodeVitastor::on_write_finish, req); vitastor_c_sync(cli->c, NodeVitastor::on_write_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(cli->c); vitastor_c_uring_handle_events(cli->c);
#endif
} }
else else
{ {
@@ -661,7 +683,9 @@ void NodeVitastorImage::exec_request(NodeVitastorRequest *req)
uint64_t ino = vitastor_c_inode_get_num(watch); uint64_t ino = vitastor_c_inode_get_num(watch);
cli->Ref(); cli->Ref();
vitastor_c_read_bitmap(cli->c, ino, req->offset, req->len, req->with_parents, NodeVitastor::on_read_bitmap_finish, req); vitastor_c_read_bitmap(cli->c, ino, req->offset, req->len, req->with_parents, NodeVitastor::on_read_bitmap_finish, req);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(cli->c); vitastor_c_uring_handle_events(cli->c);
#endif
} }
else if (req->op == NODE_VITASTOR_GET_INFO) else if (req->op == NODE_VITASTOR_GET_INFO)
{ {
@@ -793,7 +817,9 @@ NAN_METHOD(NodeVitastorKV::Open)
delete req; delete req;
kv->Unref(); kv->Unref();
}); });
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(kv->cli->c); vitastor_c_uring_handle_events(kv->cli->c);
#endif
} }
// close(callback(err)) // close(callback(err))
@@ -817,7 +843,9 @@ NAN_METHOD(NodeVitastorKV::Close)
delete req; delete req;
kv->Unref(); kv->Unref();
}); });
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(kv->cli->c); vitastor_c_uring_handle_events(kv->cli->c);
#endif
} }
// set_config({ ...config }) // set_config({ ...config })
@@ -876,7 +904,9 @@ void NodeVitastorKV::get_impl(const Nan::FunctionCallbackInfo<v8::Value> & info,
delete req; delete req;
kv->Unref(); kv->Unref();
}, allow_cache); }, allow_cache);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(kv->cli->c); vitastor_c_uring_handle_events(kv->cli->c);
#endif
} }
// get(key, callback(err, value)) // get(key, callback(err, value))
@@ -949,7 +979,9 @@ NAN_METHOD(NodeVitastorKV::Set)
delete cas_req; delete cas_req;
kv->Unref(); kv->Unref();
}, cas_cb); }, cas_cb);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(kv->cli->c); vitastor_c_uring_handle_events(kv->cli->c);
#endif
} }
// del(key, callback(err), cas_compare(old_value)?) // del(key, callback(err), cas_compare(old_value)?)
@@ -988,7 +1020,9 @@ NAN_METHOD(NodeVitastorKV::Del)
delete cas_req; delete cas_req;
kv->Unref(); kv->Unref();
}, cas_cb); }, cas_cb);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(kv->cli->c); vitastor_c_uring_handle_events(kv->cli->c);
#endif
} }
// list(start_key?) // list(start_key?)
@@ -1109,7 +1143,9 @@ NAN_METHOD(NodeVitastorKVListing::Next)
list->iter = req; list->iter = req;
list->kv->Unref(); list->kv->Unref();
}); });
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_c_uring_handle_events(list->kv->cli->c); vitastor_c_uring_handle_events(list->kv->cli->c);
#endif
} }
// close() // close()
+13 -5
View File
@@ -9,7 +9,7 @@ writeback_cache_t::~writeback_cache_t()
{ {
for (auto & bp: dirty_buffers) for (auto & bp: dirty_buffers)
{ {
if (!--(*bp.second.refcnt)) if (bp.second.buf && !--(*bp.second.refcnt))
{ {
free(bp.second.refcnt); // refcnt is allocated with the buffer free(bp.second.refcnt); // refcnt is allocated with the buffer
} }
@@ -115,7 +115,10 @@ void writeback_cache_t::copy_write(cluster_op_t *op, int state, uint64_t new_flu
.flush_id = dirty_it->second.flush_id, .flush_id = dirty_it->second.flush_id,
.refcnt = dirty_it->second.refcnt, .refcnt = dirty_it->second.refcnt,
}); });
(*dirty_it->second.refcnt)++; if (dirty_it->second.buf)
{
(*dirty_it->second.refcnt)++;
}
if (dirty_it->second.state == CACHE_DIRTY) if (dirty_it->second.state == CACHE_DIRTY)
{ {
if (dirty_it->second.buf) if (dirty_it->second.buf)
@@ -193,7 +196,7 @@ void writeback_cache_t::copy_write(cluster_op_t *op, int state, uint64_t new_flu
writeback_queue_size++; writeback_queue_size++;
} }
} }
if (!--(*dirty_it->second.refcnt)) if (dirty_it->second.buf && !--(*dirty_it->second.refcnt))
{ {
free(dirty_it->second.refcnt); free(dirty_it->second.refcnt);
} }
@@ -204,7 +207,10 @@ void writeback_cache_t::copy_write(cluster_op_t *op, int state, uint64_t new_flu
bool is_del = op->opcode == OSD_OP_DELETE; bool is_del = op->opcode == OSD_OP_DELETE;
uint64_t *refcnt = is_del ? NULL : (uint64_t*)malloc_or_die(sizeof(uint64_t) + op->len); uint64_t *refcnt = is_del ? NULL : (uint64_t*)malloc_or_die(sizeof(uint64_t) + op->len);
uint8_t *buf = is_del ? NULL : ((uint8_t*)refcnt + sizeof(uint64_t)); uint8_t *buf = is_del ? NULL : ((uint8_t*)refcnt + sizeof(uint64_t));
*refcnt = 1; if (!is_del)
{
*refcnt = 1;
}
dirty_it = dirty_buffers.emplace_hint(dirty_it, (object_id){ dirty_it = dirty_buffers.emplace_hint(dirty_it, (object_id){
.inode = op->inode, .inode = op->inode,
.stripe = op->offset, .stripe = op->offset,
@@ -560,8 +566,10 @@ void writeback_cache_t::fsync_ok()
{ {
if (uw_it->second.state == CACHE_FLUSHING) if (uw_it->second.state == CACHE_FLUSHING)
{ {
if (!--(*uw_it->second.refcnt)) if (uw_it->second.buf && !--(*uw_it->second.refcnt))
{
free(uw_it->second.refcnt); free(uw_it->second.refcnt);
}
dirty_buffers.erase(uw_it++); dirty_buffers.erase(uw_it++);
} }
else else
+5 -1
View File
@@ -889,7 +889,11 @@ void etcd_state_client_t::parse_state(const etcd_kv_t & kv)
if (!pc.scrub_interval) if (!pc.scrub_interval)
pc.scrub_interval = 0; pc.scrub_interval = 0;
// Mark pool as VitastorFS pool (disable per-inode stats and block volume creation) // Mark pool as VitastorFS pool (disable per-inode stats and block volume creation)
pc.used_for_fs = pool_item.second["used_for_fs"].as_string(); pc.used_for_app = pool_item.second["used_for_fs"].as_string();
if (pc.used_for_app != "")
pc.used_for_app = "fs:"+pc.used_for_app;
else
pc.used_for_app = pool_item.second["used_for_app"].as_string();
// Immediate Commit Mode // Immediate Commit Mode
pc.immediate_commit = pool_item.second["immediate_commit"].is_string() pc.immediate_commit = pool_item.second["immediate_commit"].is_string()
? parse_immediate_commit(pool_item.second["immediate_commit"].string_value(), IMMEDIATE_ALL) ? parse_immediate_commit(pool_item.second["immediate_commit"].string_value(), IMMEDIATE_ALL)
+1 -1
View File
@@ -61,7 +61,7 @@ struct pool_config_t
uint64_t pg_stripe_size; uint64_t pg_stripe_size;
std::map<pg_num_t, pg_config_t> pg_config; std::map<pg_num_t, pg_config_t> pg_config;
uint64_t scrub_interval; uint64_t scrub_interval;
std::string used_for_fs; std::string used_for_app;
int backfillfull; int backfillfull;
}; };
+13 -1
View File
@@ -294,7 +294,9 @@ static void coroutine_fn vitastor_co_get_metadata(VitastorRPC *task)
qemu_mutex_lock(&client->mutex); qemu_mutex_lock(&client->mutex);
vitastor_c_watch_inode(client->proxy, client->image, vitastor_co_generic_cb, task); vitastor_c_watch_inode(client->proxy, client->image, vitastor_co_generic_cb, task);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_schedule_uring_handler(client); vitastor_schedule_uring_handler(client);
#endif
qemu_mutex_unlock(&client->mutex); qemu_mutex_unlock(&client->mutex);
while (!task->complete) while (!task->complete)
@@ -566,6 +568,7 @@ static int vitastor_file_open(BlockDriverState *bs, QDict *options, int flags, E
static void vitastor_close(BlockDriverState *bs) static void vitastor_close(BlockDriverState *bs)
{ {
VitastorClient *client = bs->opaque; VitastorClient *client = bs->opaque;
qemu_mutex_lock(&client->mutex);
vitastor_c_destroy(client->proxy); vitastor_c_destroy(client->proxy);
if (client->fds) if (client->fds)
{ {
@@ -573,7 +576,6 @@ static void vitastor_close(BlockDriverState *bs)
client->fds = NULL; client->fds = NULL;
client->fd_alloc = client->fd_count = 0; client->fd_alloc = client->fd_count = 0;
} }
qemu_mutex_destroy(&client->mutex);
if (client->config_path) if (client->config_path)
g_free(client->config_path); g_free(client->config_path);
if (client->etcd_host) if (client->etcd_host)
@@ -584,6 +586,8 @@ static void vitastor_close(BlockDriverState *bs)
g_free(client->image); g_free(client->image);
free(client->last_bitmap); free(client->last_bitmap);
client->last_bitmap = NULL; client->last_bitmap = NULL;
qemu_mutex_unlock(&client->mutex);
qemu_mutex_destroy(&client->mutex);
} }
#if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 2 #if QEMU_VERSION_MAJOR >= 3 || QEMU_VERSION_MAJOR == 2 && QEMU_VERSION_MINOR > 2
@@ -749,7 +753,9 @@ static int coroutine_fn vitastor_co_preadv(BlockDriverState *bs,
uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode; uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode;
qemu_mutex_lock(&client->mutex); qemu_mutex_lock(&client->mutex);
vitastor_c_read(client->proxy, inode, offset, bytes, iov->iov, iov->niov, vitastor_co_read_cb, &task); vitastor_c_read(client->proxy, inode, offset, bytes, iov->iov, iov->niov, vitastor_co_read_cb, &task);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_schedule_uring_handler(client); vitastor_schedule_uring_handler(client);
#endif
qemu_mutex_unlock(&client->mutex); qemu_mutex_unlock(&client->mutex);
while (!task.complete) while (!task.complete)
@@ -783,7 +789,9 @@ static int coroutine_fn vitastor_co_pwritev(BlockDriverState *bs,
uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode; uint64_t inode = client->watch ? vitastor_c_inode_get_num(client->watch) : client->inode;
qemu_mutex_lock(&client->mutex); qemu_mutex_lock(&client->mutex);
vitastor_c_write(client->proxy, inode, offset, bytes, 0, iov->iov, iov->niov, vitastor_co_generic_cb, &task); vitastor_c_write(client->proxy, inode, offset, bytes, 0, iov->iov, iov->niov, vitastor_co_generic_cb, &task);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_schedule_uring_handler(client); vitastor_schedule_uring_handler(client);
#endif
qemu_mutex_unlock(&client->mutex); qemu_mutex_unlock(&client->mutex);
while (!task.complete) while (!task.complete)
@@ -863,7 +871,9 @@ static int coroutine_fn vitastor_co_block_status(
task.bitmap = client->last_bitmap = NULL; task.bitmap = client->last_bitmap = NULL;
qemu_mutex_lock(&client->mutex); qemu_mutex_lock(&client->mutex);
vitastor_c_read_bitmap(client->proxy, task.inode, task.offset, task.len, !client->skip_parents, vitastor_co_read_bitmap_cb, &task); vitastor_c_read_bitmap(client->proxy, task.inode, task.offset, task.len, !client->skip_parents, vitastor_co_read_bitmap_cb, &task);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_schedule_uring_handler(client); vitastor_schedule_uring_handler(client);
#endif
qemu_mutex_unlock(&client->mutex); qemu_mutex_unlock(&client->mutex);
while (!task.complete) while (!task.complete)
{ {
@@ -950,7 +960,9 @@ static int coroutine_fn vitastor_co_flush(BlockDriverState *bs)
qemu_mutex_lock(&client->mutex); qemu_mutex_lock(&client->mutex);
vitastor_c_sync(client->proxy, vitastor_co_generic_cb, &task); vitastor_c_sync(client->proxy, vitastor_co_generic_cb, &task);
#if !defined VITASTOR_C_API_VERSION || VITASTOR_C_API_VERSION < 5
vitastor_schedule_uring_handler(client); vitastor_schedule_uring_handler(client);
#endif
qemu_mutex_unlock(&client->mutex); qemu_mutex_unlock(&client->mutex);
while (!task.complete) while (!task.complete)
+31
View File
@@ -127,6 +127,7 @@ vitastor_c *vitastor_c_create_qemu_uring(QEMUSetFDHandler *aio_set_fd_handler, v
auto self = vitastor_c_create_qemu_common(aio_set_fd_handler, aio_context); auto self = vitastor_c_create_qemu_common(aio_set_fd_handler, aio_context);
self->ringloop = ringloop; self->ringloop = ringloop;
self->cli = new cluster_client_t(self->ringloop, self->tfd, cfg_json); self->cli = new cluster_client_t(self->ringloop, self->tfd, cfg_json);
ringloop->loop();
return self; return self;
} }
@@ -150,6 +151,7 @@ vitastor_c *vitastor_c_create_uring(const char *config_path, const char *etcd_ho
self->ringloop = ringloop; self->ringloop = ringloop;
self->epmgr = new epoll_manager_t(self->ringloop); self->epmgr = new epoll_manager_t(self->ringloop);
self->cli = new cluster_client_t(self->ringloop, self->epmgr->tfd, cfg_json); self->cli = new cluster_client_t(self->ringloop, self->epmgr->tfd, cfg_json);
ringloop->loop();
return self; return self;
} }
@@ -183,6 +185,7 @@ vitastor_c *vitastor_c_create_uring_json(const char **options, int options_len)
self->ringloop = ringloop; self->ringloop = ringloop;
self->epmgr = new epoll_manager_t(self->ringloop); self->epmgr = new epoll_manager_t(self->ringloop);
self->cli = new cluster_client_t(self->ringloop, self->epmgr->tfd, cfg_json); self->cli = new cluster_client_t(self->ringloop, self->epmgr->tfd, cfg_json);
ringloop->loop();
return self; return self;
} }
@@ -228,6 +231,10 @@ void vitastor_c_on_ready(vitastor_c *client, VitastorIOHandler cb, void *opaque)
{ {
cb(opaque, 0); cb(opaque, 0);
}); });
if (client->ringloop)
{
client->ringloop->loop();
}
} }
void vitastor_c_uring_wait_ready(vitastor_c *client) void vitastor_c_uring_wait_ready(vitastor_c *client)
@@ -284,6 +291,10 @@ void vitastor_c_read(vitastor_c *client, uint64_t inode, uint64_t offset, uint64
delete op; delete op;
}; };
client->cli->execute(op); client->cli->execute(op);
if (client->ringloop)
{
client->ringloop->loop();
}
} }
void vitastor_c_write(vitastor_c *client, uint64_t inode, uint64_t offset, uint64_t len, uint64_t check_version, void vitastor_c_write(vitastor_c *client, uint64_t inode, uint64_t offset, uint64_t len, uint64_t check_version,
@@ -305,6 +316,10 @@ void vitastor_c_write(vitastor_c *client, uint64_t inode, uint64_t offset, uint6
delete op; delete op;
}; };
client->cli->execute(op); client->cli->execute(op);
if (client->ringloop)
{
client->ringloop->loop();
}
} }
void vitastor_c_delete(vitastor_c *client, uint64_t inode, uint64_t offset, uint64_t len, uint64_t check_version, void vitastor_c_delete(vitastor_c *client, uint64_t inode, uint64_t offset, uint64_t len, uint64_t check_version,
@@ -322,6 +337,10 @@ void vitastor_c_delete(vitastor_c *client, uint64_t inode, uint64_t offset, uint
delete op; delete op;
}; };
client->cli->execute(op); client->cli->execute(op);
if (client->ringloop)
{
client->ringloop->loop();
}
} }
void vitastor_c_read_bitmap(vitastor_c *client, uint64_t inode, uint64_t offset, uint64_t len, void vitastor_c_read_bitmap(vitastor_c *client, uint64_t inode, uint64_t offset, uint64_t len,
@@ -344,6 +363,10 @@ void vitastor_c_read_bitmap(vitastor_c *client, uint64_t inode, uint64_t offset,
delete op; delete op;
}; };
client->cli->execute(op); client->cli->execute(op);
if (client->ringloop)
{
client->ringloop->loop();
}
} }
void vitastor_c_sync(vitastor_c *client, VitastorIOHandler cb, void *opaque) void vitastor_c_sync(vitastor_c *client, VitastorIOHandler cb, void *opaque)
@@ -356,6 +379,10 @@ void vitastor_c_sync(vitastor_c *client, VitastorIOHandler cb, void *opaque)
delete op; delete op;
}; };
client->cli->execute(op); client->cli->execute(op);
if (client->ringloop)
{
client->ringloop->loop();
}
} }
void vitastor_c_watch_inode(vitastor_c *client, char *image, VitastorIOHandler cb, void *opaque) void vitastor_c_watch_inode(vitastor_c *client, char *image, VitastorIOHandler cb, void *opaque)
@@ -365,6 +392,10 @@ void vitastor_c_watch_inode(vitastor_c *client, char *image, VitastorIOHandler c
auto watch = client->cli->st_cli.watch_inode(std::string(image)); auto watch = client->cli->st_cli.watch_inode(std::string(image));
cb(opaque, (long)watch); cb(opaque, (long)watch);
}); });
if (client->ringloop)
{
client->ringloop->loop();
}
} }
void vitastor_c_close_watch(vitastor_c *client, void *handle) void vitastor_c_close_watch(vitastor_c *client, void *handle)
+1 -1
View File
@@ -7,7 +7,7 @@
#define VITASTOR_QEMU_PROXY_H #define VITASTOR_QEMU_PROXY_H
// C API wrapper version // C API wrapper version
#define VITASTOR_C_API_VERSION 4 #define VITASTOR_C_API_VERSION 5
#ifndef POOL_ID_BITS #ifndef POOL_ID_BITS
#define POOL_ID_BITS 16 #define POOL_ID_BITS 16
+3 -2
View File
@@ -186,7 +186,8 @@ static const char* help_text =
" --raw_placement <rules> Specify raw PG generation rules (see documentation for details)\n" " --raw_placement <rules> Specify raw PG generation rules (see documentation for details)\n"
" --primary_affinity_tags tags Prefer to put primary copies on OSDs with all specified tags\n" " --primary_affinity_tags tags Prefer to put primary copies on OSDs with all specified tags\n"
" --scrub_interval <time> Enable regular scrubbing for this pool. Format: number + unit s/m/h/d/M/y\n" " --scrub_interval <time> Enable regular scrubbing for this pool. Format: number + unit s/m/h/d/M/y\n"
" --used_for_fs <name> Mark pool as used for VitastorFS with metadata in image <name>\n" " --used_for_app fs:<name> Mark pool as used for VitastorFS with metadata in image <name>\n"
" --used_for_app s3:<name> Mark pool as used for S3 location with name <name>\n"
" --pg_stripe_size <number> Increase object grouping stripe\n" " --pg_stripe_size <number> Increase object grouping stripe\n"
" --max_osd_combinations 10000 Maximum number of random combinations for LP solver input\n" " --max_osd_combinations 10000 Maximum number of random combinations for LP solver input\n"
" --wait Wait for the new pool to come online\n" " --wait Wait for the new pool to come online\n"
@@ -198,7 +199,7 @@ static const char* help_text =
"vitastor-cli modify-pool|pool-modify <id|name> [--name <new_name>] [PARAMETERS...]\n" "vitastor-cli modify-pool|pool-modify <id|name> [--name <new_name>] [PARAMETERS...]\n"
" Modify an existing pool. Modifiable parameters:\n" " Modify an existing pool. Modifiable parameters:\n"
" [-s|--pg_size <number>] [--pg_minsize <number>] [-n|--pg_count <count>]\n" " [-s|--pg_size <number>] [--pg_minsize <number>] [-n|--pg_count <count>]\n"
" [--failure_domain <level>] [--root_node <node>] [--osd_tags <tags>] [--used_for_fs <name>]\n" " [--failure_domain <level>] [--root_node <node>] [--osd_tags <tags>] [--used_for_app <type>:<name>]\n"
" [--max_osd_combinations <number>] [--primary_affinity_tags <tags>] [--scrub_interval <time>]\n" " [--max_osd_combinations <number>] [--primary_affinity_tags <tags>] [--scrub_interval <time>]\n"
" [--level_placement <rules>] [--raw_placement <rules>]\n" " [--level_placement <rules>] [--raw_placement <rules>]\n"
" Non-modifiable parameters (changing them WILL lead to data loss):\n" " Non-modifiable parameters (changing them WILL lead to data loss):\n"
+2 -2
View File
@@ -92,12 +92,12 @@ struct image_creator_t
{ {
new_pool_id = pools.begin()->first; new_pool_id = pools.begin()->first;
} }
if (new_pool_id && !pools.at(new_pool_id).used_for_fs.empty() && !force) if (new_pool_id && !pools.at(new_pool_id).used_for_app.empty() && !force)
{ {
result = (cli_result_t){ result = (cli_result_t){
.err = EINVAL, .err = EINVAL,
.text = "Pool "+pools.at(new_pool_id).name+ .text = "Pool "+pools.at(new_pool_id).name+
" is used for VitastorFS "+pools.at(new_pool_id).used_for_fs+ " is used for application "+pools.at(new_pool_id).used_for_app+
". Use --force if you really know what you are doing", ". Use --force if you really know what you are doing",
}; };
state = 100; state = 100;
+8 -3
View File
@@ -90,8 +90,8 @@ std::string validate_pool_config(json11::Json::object & new_cfg, json11::Json ol
value = sz; value = sz;
} }
else if (key == "name" || key == "scheme" || key == "immediate_commit" || else if (key == "name" || key == "scheme" || key == "immediate_commit" ||
key == "failure_domain" || key == "root_node" || key == "scrub_interval" || key == "used_for_fs" || key == "failure_domain" || key == "root_node" || key == "scrub_interval" || key == "used_for_app" ||
key == "raw_placement") key == "used_for_fs" || key == "raw_placement")
{ {
if (!value.is_string()) if (!value.is_string())
{ {
@@ -156,8 +156,13 @@ std::string validate_pool_config(json11::Json::object & new_cfg, json11::Json ol
{ {
new_cfg.erase("parity_chunks"); new_cfg.erase("parity_chunks");
} }
if (new_cfg.find("used_for_fs") != new_cfg.end() && new_cfg["used_for_fs"].string_value() == "") if (new_cfg.find("used_for_app") != new_cfg.end() && new_cfg["used_for_app"].string_value() == "")
{ {
new_cfg.erase("used_for_app");
}
if (new_cfg.find("used_for_app") == new_cfg.end() && new_cfg.find("used_for_fs") != new_cfg.end())
{
new_cfg["used_for_app"] = "fs:"+new_cfg["used_for_fs"].string_value();
new_cfg.erase("used_for_fs"); new_cfg.erase("used_for_fs");
} }
+4 -2
View File
@@ -199,7 +199,9 @@ resume_1:
auto & st = pool_stats[pool_id]; auto & st = pool_stats[pool_id];
for (auto & kv: pp.second.object_items()) for (auto & kv: pp.second.object_items())
{ {
if (st.find(kv.first) == st.end()) if (kv.first == "used_for_fs" && st.find("used_for_app") == st.end())
st["used_for_app"] = "fs:"+kv.second.string_value();
else if (st.find(kv.first) == st.end())
st[kv.first] = kv.second; st[kv.first] = kv.second;
} }
} }
@@ -493,7 +495,7 @@ resume_3:
{ "name", "Name" }, { "name", "Name" },
{ "id", "ID" }, { "id", "ID" },
{ "scheme_name", "Scheme" }, { "scheme_name", "Scheme" },
{ "used_for_fs", "Used for VitastorFS" }, { "used_for_app", "Used for app" },
{ "status", "Status" }, { "status", "Status" },
{ "backfillfull_fmt", "Backfillfull" }, { "backfillfull_fmt", "Backfillfull" },
{ "pg_count_fmt", "PGs" }, { "pg_count_fmt", "PGs" },
+6 -4
View File
@@ -112,19 +112,21 @@ resume_1:
return; return;
} }
if (new_cfg.find("used_for_fs") != new_cfg.end() && !force) if (new_cfg.find("used_for_app") != new_cfg.end() && !force)
{ {
// Check that pool doesn't have images // Check that pool doesn't have images
auto img_it = parent->cli->st_cli.inode_config.lower_bound(INODE_WITH_POOL(pool_id, 0)); auto img_it = parent->cli->st_cli.inode_config.lower_bound(INODE_WITH_POOL(pool_id, 0));
if (img_it != parent->cli->st_cli.inode_config.end() && INODE_POOL(img_it->first) == pool_id && if (img_it != parent->cli->st_cli.inode_config.end() &&
img_it->second.name == new_cfg["used_for_fs"].string_value()) INODE_POOL(img_it->first) == pool_id &&
new_cfg["used_for_app"].string_value().substr(0, 3) == "fs:" &&
img_it->second.name == new_cfg["used_for_app"].string_value().substr(3))
{ {
// Only allow metadata image to exist in the FS pool // Only allow metadata image to exist in the FS pool
img_it++; img_it++;
} }
if (img_it != parent->cli->st_cli.inode_config.end() && INODE_POOL(img_it->first) == pool_id) if (img_it != parent->cli->st_cli.inode_config.end() && INODE_POOL(img_it->first) == pool_id)
{ {
result = (cli_result_t){ .err = ENOENT, .text = "Pool "+pool_name+" has block images, delete them before using it for VitastorFS" }; result = (cli_result_t){ .err = ENOENT, .text = "Pool "+pool_name+" has block images, delete them before using it for VitastorFS, S3 or another app" };
state = 100; state = 100;
return; return;
} }
+3 -3
View File
@@ -245,10 +245,10 @@ void kv_fs_state_t::init(nfs_proxy_t *proxy, json11::Json cfg)
if (proxy->cli->st_cli.inode_config.find(fs_kv_inode) != proxy->cli->st_cli.inode_config.end()) if (proxy->cli->st_cli.inode_config.find(fs_kv_inode) != proxy->cli->st_cli.inode_config.end())
{ {
auto & name = proxy->cli->st_cli.inode_config.at(fs_kv_inode).name; auto & name = proxy->cli->st_cli.inode_config.at(fs_kv_inode).name;
if (pool_cfg.used_for_fs != name) if (pool_cfg.used_for_app != "fs:"+name)
{ {
fprintf(stderr, "Please mark pool as used for this file system with `vitastor-cli modify-pool --used-for-fs %s %s`\n", fprintf(stderr, "Please mark pool as used for this file system with `vitastor-cli modify-pool --used-for-app fs:%s %s`\n",
name.c_str(), cfg["fs"].string_value().c_str()); name.c_str(), pool_cfg.name.c_str());
exit(1); exit(1);
} }
} }
+1 -1
View File
@@ -673,7 +673,7 @@ void osd_t::apply_no_inode_stats()
std::vector<uint64_t> no_inode_stats; std::vector<uint64_t> no_inode_stats;
for (auto & pool_item: st_cli.pool_config) for (auto & pool_item: st_cli.pool_config)
{ {
if (!pool_item.second.used_for_fs.empty()) if (!pool_item.second.used_for_app.empty())
{ {
no_inode_stats.push_back(pool_item.first); no_inode_stats.push_back(pool_item.first);
} }
+47 -43
View File
@@ -722,54 +722,58 @@ resume_3:
cur_op->reply.rw.version = op_data->fact_ver; cur_op->reply.rw.version = op_data->fact_ver;
goto continue_others; goto continue_others;
} }
// Save version override for parallel reads // If not already deleted:
pg.ver_override[op_data->oid] = op_data->fact_ver; if (op_data->fact_ver)
// Submit deletes {
op_data->fact_ver++; // Save version override for parallel reads
submit_primary_del_subops(cur_op, NULL, 0, op_data->object_state ? op_data->object_state->osd_set : pg.cur_loc_set); pg.ver_override[op_data->oid] = op_data->fact_ver;
// Submit deletes
op_data->fact_ver++;
submit_primary_del_subops(cur_op, NULL, 0, op_data->object_state ? op_data->object_state->osd_set : pg.cur_loc_set);
resume_4: resume_4:
op_data->st = 4; op_data->st = 4;
return;
resume_5:
if (op_data->errors > 0)
{
deref_object_state(pg, &op_data->object_state, true);
pg_cancel_write_queue(pg, cur_op, op_data->oid, op_data->errcode);
return; return;
} resume_5:
// Remove version override if (op_data->errors > 0)
pg.ver_override.erase(op_data->oid);
// Adjust PG stats after "instant stabilize", because we need object_state above
if (!op_data->object_state)
{
pg.clean_count--;
}
else
{
remove_object_from_state(op_data->oid, &op_data->object_state, pg);
deref_object_state(pg, &op_data->object_state, true);
}
// Mark PG and OSDs as dirty
for (auto & chunk: (op_data->object_state ? op_data->object_state->osd_set : pg.cur_loc_set))
{
this->dirty_osds.insert(chunk.osd_num);
}
for (auto cl_it = msgr.clients.find(cur_op->peer_fd); cl_it != msgr.clients.end(); )
{
cl_it->second->dirty_pgs.insert({ .pool_id = pg.pool_id, .pg_num = pg.pg_num });
break;
}
dirty_pgs.insert({ .pool_id = pg.pool_id, .pg_num = pg.pg_num });
if (immediate_commit == IMMEDIATE_NONE)
{
unstable_write_count++;
if (unstable_write_count >= autosync_writes)
{ {
unstable_write_count = 0; deref_object_state(pg, &op_data->object_state, true);
autosync(); pg_cancel_write_queue(pg, cur_op, op_data->oid, op_data->errcode);
return;
} }
// Remove version override
pg.ver_override.erase(op_data->oid);
// Adjust PG stats after "instant stabilize", because we need object_state above
if (!op_data->object_state)
{
pg.clean_count--;
}
else
{
remove_object_from_state(op_data->oid, &op_data->object_state, pg);
deref_object_state(pg, &op_data->object_state, true);
}
// Mark PG and OSDs as dirty
for (auto & chunk: (op_data->object_state ? op_data->object_state->osd_set : pg.cur_loc_set))
{
this->dirty_osds.insert(chunk.osd_num);
}
for (auto cl_it = msgr.clients.find(cur_op->peer_fd); cl_it != msgr.clients.end(); )
{
cl_it->second->dirty_pgs.insert({ .pool_id = pg.pool_id, .pg_num = pg.pg_num });
break;
}
dirty_pgs.insert({ .pool_id = pg.pool_id, .pg_num = pg.pg_num });
if (immediate_commit == IMMEDIATE_NONE)
{
unstable_write_count++;
if (unstable_write_count >= autosync_writes)
{
unstable_write_count = 0;
autosync();
}
}
pg.total_count--;
} }
pg.total_count--;
cur_op->reply.hdr.retval = 0; cur_op->reply.hdr.retval = 0;
// indicate possibly unfinished (left_on_dead) deletions // indicate possibly unfinished (left_on_dead) deletions
cur_op->reply.del.flags = OSD_DEL_SUPPORT_LEFT_ON_DEAD; cur_op->reply.del.flags = OSD_DEL_SUPPORT_LEFT_ON_DEAD;
+22
View File
@@ -3,6 +3,7 @@
#include <sys/epoll.h> #include <sys/epoll.h>
#include <sys/poll.h> #include <sys/poll.h>
#include <poll.h>
#include <unistd.h> #include <unistd.h>
#include <stdexcept> #include <stdexcept>
@@ -74,6 +75,27 @@ void epoll_manager_t::set_fd_handler(int fd, bool wr, std::function<void(int, in
throw std::runtime_error(std::string("epoll_ctl: ") + strerror(errno)); throw std::runtime_error(std::string("epoll_ctl: ") + strerror(errno));
} }
epoll_handlers[fd] = handler; epoll_handlers[fd] = handler;
// We use edge-triggered epoll so it may miss events which already happened
// on the FD at the moment of adding it to epoll. So check for these with poll()
struct pollfd initpoll = { .fd = fd, .events = (short)((wr ? POLLOUT : 0) | POLLIN | POLLRDHUP) };
int r = poll(&initpoll, 1, 0);
if (r < 0)
throw std::runtime_error(std::string("poll: ") + strerror(errno));
if (r > 0)
{
auto events = ((initpoll.revents & POLLOUT) ? EPOLLOUT : 0) |
((initpoll.revents & POLLIN) ? EPOLLIN : 0) |
((initpoll.revents & POLLRDHUP) ? EPOLLRDHUP : 0);
tfd->set_timer_us(1, false, [this, fd, events](int)
{
auto cb_it = epoll_handlers.find(fd);
if (cb_it != epoll_handlers.end())
{
auto & cb = cb_it->second;
cb(fd, events);
}
});
}
} }
else else
{ {
+9
View File
@@ -29,6 +29,7 @@ ring_loop_t::ring_loop_t(int qd, bool multithreaded)
{ {
free_ring_data[i] = i; free_ring_data[i] = i;
} }
in_loop = false;
} }
ring_loop_t::~ring_loop_t() ring_loop_t::~ring_loop_t()
@@ -86,6 +87,11 @@ io_uring_sqe* ring_loop_t::get_sqe()
void ring_loop_t::loop() void ring_loop_t::loop()
{ {
if (in_loop)
{
return;
}
in_loop = true;
if (ring_eventfd >= 0) if (ring_eventfd >= 0)
{ {
// Reset eventfd counter // Reset eventfd counter
@@ -140,6 +146,7 @@ void ring_loop_t::loop()
} }
} }
} while (loop_again); } while (loop_again);
in_loop = false;
} }
unsigned ring_loop_t::save() unsigned ring_loop_t::save()
@@ -189,5 +196,7 @@ int ring_loop_t::register_eventfd()
ring_eventfd = -1; ring_eventfd = -1;
return r; return r;
} }
// Loop once to prevent skipping events happened before eventfd was registered
loop();
return ring_eventfd; return ring_eventfd;
} }
+1
View File
@@ -129,6 +129,7 @@ class ring_loop_t
bool mt; bool mt;
int *free_ring_data; int *free_ring_data;
unsigned free_ring_data_ptr; unsigned free_ring_data_ptr;
bool in_loop;
bool loop_again; bool loop_again;
struct io_uring ring; struct io_uring ring;
int ring_eventfd = -1; int ring_eventfd = -1;
+1 -1
View File
@@ -4,7 +4,7 @@ PG_COUNT=16
. `dirname $0`/run_3osds.sh . `dirname $0`/run_3osds.sh
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create -s 10G fsmeta build/src/cmd/vitastor-cli --etcd_address $ETCD_URL create -s 10G fsmeta
build/src/cmd/vitastor-cli --etcd_address $ETCD_URL modify-pool --used-for-fs fsmeta testpool build/src/cmd/vitastor-cli --etcd_address $ETCD_URL modify-pool --used-for-app fs:fsmeta testpool
build/src/nfs/vitastor-nfs start --fs fsmeta --etcd_address $ETCD_URL --portmap 0 --port 2050 --foreground 1 --trace 1 >>./testdata/nfs.log 2>&1 & build/src/nfs/vitastor-nfs start --fs fsmeta --etcd_address $ETCD_URL --portmap 0 --port 2050 --foreground 1 --trace 1 >>./testdata/nfs.log 2>&1 &
NFS_PID=$! NFS_PID=$!