mirror of
https://github.com/versity/scoutfs.git
synced 2026-04-20 13:30:29 +00:00
Add lock coverage for inode index items. Sadly, this isn't trivial. We have to predict the value of the indexed fields before the operation to lock those items. One value in particular we can't reliably predict: the sequence of the transaction we enter after locking. Also operations can create an absolute ton of index item updates -- rename can modify nr_inodes * items_per_inode * 2 items, so maybe 24 today. And these items can be arbitrarily positioned in the key space. So to handle all this we add functions to gather predicted item values we'll need to lock sort and lock them all, then pass appropriate locks down to the item functions during inode updates. The trickiest bit of the index locking code is having to retry if the sequence number changes. Preparing locks has to guess the sequence number of its upcoming trans and then makes item update decisions based on that. If we enter and have a different sequence number then we need to back off and retry with the correct sequence number (we may find that we'll need to update the indexed meta seq and need to have it locked). The use of the functions is straight forward. Sites figure out the predicted sizes, lock, pass the locks to inode updates, and unlock. While we're at it we replace the individual item field tracking variables in the inode info with an array of indexed values. The code ends up a bit nicer. It also gets rid of the indexed time fields that were left behind and were unused. It's worth noting that we're getting exclusive locks on the index updates. Locking the meta/data seq updates results in complete global serialization of all changes. We'll need concurrent writer locks to get concurrency back. Signed-off-by: Zach Brown <zab@versity.com>
59 lines
2.1 KiB
C
59 lines
2.1 KiB
C
#ifndef _SCOUTFS_LOCK_H_
|
|
#define _SCOUTFS_LOCK_H_
|
|
|
|
#include <linux/dlm.h>
|
|
#include "key.h"
|
|
#include "dlmglue.h"
|
|
|
|
#define SCOUTFS_LKF_REFRESH_INODE 0x01 /* update stale inode from item */
|
|
#define SCOUTFS_LKF_TRYLOCK 0x02 /* EAGAIN if contention */
|
|
|
|
/* flags for scoutfs_lock->flags */
|
|
enum {
|
|
SCOUTFS_LOCK_RECLAIM = 0, /* lock is queued for reclaim */
|
|
SCOUTFS_LOCK_DROPPED, /* lock is going away, drop reference */
|
|
};
|
|
|
|
struct scoutfs_lock {
|
|
struct super_block *sb;
|
|
struct scoutfs_lock_name lock_name;
|
|
struct scoutfs_key_buf *start;
|
|
struct scoutfs_key_buf *end;
|
|
struct dlm_lksb lksb;
|
|
unsigned int sequence; /* for debugging and sanity checks */
|
|
struct rb_node node;
|
|
unsigned int refcnt;
|
|
struct ocfs2_lock_res lockres;
|
|
struct list_head lru_entry;
|
|
struct work_struct reclaim_work;
|
|
unsigned int users; /* Tracks active users of this lock */
|
|
unsigned long flags;
|
|
wait_queue_head_t waitq;
|
|
};
|
|
|
|
u64 scoutfs_lock_refresh_gen(struct scoutfs_lock *lock);
|
|
int scoutfs_lock_inode(struct super_block *sb, int mode, int flags,
|
|
struct inode *inode, struct scoutfs_lock **ret_lock);
|
|
int scoutfs_lock_ino(struct super_block *sb, int mode, int flags, u64 ino,
|
|
struct scoutfs_lock **ret_lock);
|
|
void scoutfs_lock_clamp_inode_index(u8 type, u64 *major, u32 *minor, u64 *ino);
|
|
int scoutfs_lock_inode_index(struct super_block *sb, int mode,
|
|
u8 type, u64 major, u64 ino,
|
|
struct scoutfs_lock **ret_lock);
|
|
int scoutfs_lock_inodes(struct super_block *sb, int mode, int flags,
|
|
struct inode *a, struct scoutfs_lock **a_lock,
|
|
struct inode *b, struct scoutfs_lock **b_lock,
|
|
struct inode *c, struct scoutfs_lock **c_lock,
|
|
struct inode *d, struct scoutfs_lock **D_lock);
|
|
int scoutfs_lock_global(struct super_block *sb, int mode, int flags, int type,
|
|
struct scoutfs_lock **lock);
|
|
int scoutfs_lock_node_id(struct super_block *sb, int mode, int flags,
|
|
u64 node_id, struct scoutfs_lock **lock);
|
|
void scoutfs_unlock(struct super_block *sb, struct scoutfs_lock *lock,
|
|
int level);
|
|
|
|
int scoutfs_lock_setup(struct super_block *sb);
|
|
void scoutfs_lock_destroy(struct super_block *sb);
|
|
|
|
#endif
|