mirror of
https://github.com/versity/scoutfs.git
synced 2026-07-24 00:53:01 +00:00
We had a simple mechanism for ensuring that transaction didn't create more items than would fit in a single written segment. We calculated the most dirty items that a holder could generate and assumed that all holders dirtied that much. This had two big problems. The first was that it wasn't accounting for nested holds. write_begin/end calls the generic inode dirtying path whild holding a transaction. This ended up deadlocking as the dirty inode waited to be able to write while its trans held back in write_begin prevented writeout. The second was that the worst case (full size xattr) item dirtying is enormous and meaningfully restricts concurrent transaction holders. With no currently dirty items you can have less than 16 full size xattr writes. This concurrency limit only gets worse as the transaction fills up with dirty items. This fixes those problems. It adds precise accounting of the dirty items that can be created while a transaction is held. These reservations are tracked in journal_info so that they can be used by nested holds. The precision allows much greater concurrency as something like a create will try to reserve a few hundreds bytes instead of 64k. Normal sized xattr operations won't try to reserve the largest possible space. We add some feedback from the item cache to the transaction to issue warnings if a holder dirties more items than it reserved. Now that we have precise item/key/value counts (segment space consumption is a function of all three :/) we can't have a single atomic track transaction holders. We add a long-overdue trans_info and put a proper lock and fields there and much more clearly track transaction serialization amongst the holders and writer. Signed-off-by: Zach Brown <zab@versity.com>
23 lines
765 B
C
23 lines
765 B
C
#ifndef _SCOUTFS_TRANS_H_
|
|
#define _SCOUTFS_TRANS_H_
|
|
|
|
#include "net.h"
|
|
#include "count.h"
|
|
|
|
void scoutfs_trans_write_func(struct work_struct *work);
|
|
int scoutfs_sync_fs(struct super_block *sb, int wait);
|
|
int scoutfs_file_fsync(struct file *file, loff_t start, loff_t end,
|
|
int datasync);
|
|
void scoutfs_trans_restart_sync_deadline(struct super_block *sb);
|
|
|
|
int scoutfs_hold_trans(struct super_block *sb, struct scoutfs_item_count *cnt);
|
|
void scoutfs_release_trans(struct super_block *sb);
|
|
void scoutfs_trans_wake_holders(struct super_block *sb);
|
|
void scoutfs_trans_track_item(struct super_block *sb, signed items,
|
|
signed keys, signed vals);
|
|
|
|
int scoutfs_setup_trans(struct super_block *sb);
|
|
void scoutfs_shutdown_trans(struct super_block *sb);
|
|
|
|
#endif
|