scoutfs: remove wrlock and roster

These were interesting experiments in how to manage locks across the
cluster but we'll be going in a more flexible direction.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2016-07-01 21:03:40 -07:00
parent 4689bf0881
commit 5c7ba5ed39
13 changed files with 29 additions and 1338 deletions

View File

@@ -11,7 +11,7 @@ CFLAGS_scoutfs_trace.o = -I$(src) # define_trace.h double include
scoutfs-y += first.o
scoutfs-y += block.o btree.o buddy.o counters.o crc.o dir.o filerw.o \
inode.o ioctl.o msg.o roster.o scoutfs_trace.o super.o trace.o \
trans.o treap.o wrlock.o
inode.o ioctl.o msg.o scoutfs_trace.o super.o trace.o trans.o \
treap.o
scoutfs-y += last.o

View File

@@ -22,7 +22,7 @@
#include "key.h"
#include "super.h"
#include "btree.h"
#include "wrlock.h"
#include "trans.h"
/*
* Directory entries are stored in entries with offsets calculated from
@@ -310,9 +310,7 @@ static int scoutfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
struct scoutfs_key first;
struct scoutfs_key last;
struct scoutfs_key key;
DECLARE_SCOUTFS_WRLOCK_HELD(held);
int bytes;
u64 ino;
int ret;
u64 h;
@@ -323,11 +321,7 @@ static int scoutfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
if (dentry->d_name.len > SCOUTFS_NAME_LEN)
return -ENAMETOOLONG;
ret = scoutfs_alloc_ino(sb, &ino);
if (ret)
return ret;
ret = scoutfs_wrlock_lock(sb, &held, 2, scoutfs_ino(dir), ino);
ret = scoutfs_hold_trans(sb);
if (ret)
return ret;
@@ -335,7 +329,7 @@ static int scoutfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
if (ret)
goto out;
inode = scoutfs_new_inode(sb, dir, ino, mode, rdev);
inode = scoutfs_new_inode(sb, dir, mode, rdev);
if (IS_ERR(inode)) {
ret = PTR_ERR(inode);
goto out;
@@ -392,7 +386,7 @@ out:
/* XXX delete the inode item here */
if (ret && !IS_ERR_OR_NULL(inode))
iput(inode);
scoutfs_wrlock_unlock(sb, &held);
scoutfs_release_trans(sb);
return ret;
}
@@ -417,7 +411,6 @@ static int scoutfs_unlink(struct inode *dir, struct dentry *dentry)
struct super_block *sb = dir->i_sb;
struct inode *inode = dentry->d_inode;
struct timespec ts = current_kernel_time();
DECLARE_SCOUTFS_WRLOCK_HELD(held);
struct dentry_info *di;
struct scoutfs_key key;
int ret = 0;
@@ -429,8 +422,7 @@ static int scoutfs_unlink(struct inode *dir, struct dentry *dentry)
if (S_ISDIR(inode->i_mode) && i_size_read(inode))
return -ENOTEMPTY;
ret = scoutfs_wrlock_lock(sb, &held, 2, scoutfs_ino(dir),
scoutfs_ino(inode));
ret = scoutfs_hold_trans(sb);
if (ret)
return ret;
@@ -459,7 +451,7 @@ static int scoutfs_unlink(struct inode *dir, struct dentry *dentry)
scoutfs_update_inode_item(dir);
out:
scoutfs_wrlock_unlock(sb, &held);
scoutfs_release_trans(sb);
return ret;
}

View File

@@ -18,7 +18,7 @@
#include "inode.h"
#include "key.h"
#include "filerw.h"
#include "wrlock.h"
#include "trans.h"
#include "scoutfs_trace.h"
#include "btree.h"
@@ -130,7 +130,6 @@ static int scoutfs_writepage(struct page *page, struct writeback_control *wbc)
{
struct inode *inode = page->mapping->host;
DECLARE_SCOUTFS_BTREE_CURSOR(curs);
DECLARE_SCOUTFS_WRLOCK_HELD(held);
struct super_block *sb = inode->i_sb;
struct scoutfs_key key;
struct data_region dr;
@@ -140,7 +139,7 @@ static int scoutfs_writepage(struct page *page, struct writeback_control *wbc)
set_page_writeback(page);
ret = scoutfs_wrlock_lock(sb, &held, 1, scoutfs_ino(inode));
ret = scoutfs_hold_trans(sb);
if (ret)
goto out;
@@ -162,7 +161,7 @@ static int scoutfs_writepage(struct page *page, struct writeback_control *wbc)
}
scoutfs_btree_release(&curs);
scoutfs_wrlock_unlock(sb, &held);
scoutfs_release_trans(sb);
out:
if (ret) {
SetPageError(page);
@@ -199,7 +198,6 @@ static int scoutfs_write_end(struct file *file, struct address_space *mapping,
{
struct inode *inode = mapping->host;
struct super_block *sb = inode->i_sb;
DECLARE_SCOUTFS_WRLOCK_HELD(held);
unsigned off;
trace_scoutfs_write_end(scoutfs_ino(inode), pos, len, copied);
@@ -220,10 +218,10 @@ static int scoutfs_write_end(struct file *file, struct address_space *mapping,
* up the robust metadata support that's needed to do a
* good job with the data pats.
*/
if (!scoutfs_wrlock_lock(sb, &held, 1, scoutfs_ino(inode))) {
if (!scoutfs_hold_trans(sb)) {
if (!scoutfs_dirty_inode_item(inode))
scoutfs_update_inode_item(inode);
scoutfs_wrlock_unlock(sb, &held);
scoutfs_release_trans(sb);
}
}

View File

@@ -159,8 +159,6 @@ struct scoutfs_super_block {
} __packed;
#define SCOUTFS_ROOT_INO 1
#define SCOUTFS_INO_BATCH_SHIFT 20
#define SCOUTFS_INO_BATCH (1 << SCOUTFS_INO_BATCH_SHIFT)
struct scoutfs_timespec {
__le64 sec;

View File

@@ -22,7 +22,6 @@
#include "btree.h"
#include "dir.h"
#include "filerw.h"
#include "wrlock.h"
#include "scoutfs_trace.h"
/*
@@ -248,69 +247,24 @@ void scoutfs_update_inode_item(struct inode *inode)
trace_scoutfs_update_inode(inode);
}
/*
* This will need to try and find a mostly idle shard. For now we only
* have one :).
*/
static int get_next_ino_batch(struct super_block *sb)
static int alloc_ino(struct super_block *sb, u64 *ino)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
DECLARE_SCOUTFS_WRLOCK_HELD(held);
struct scoutfs_super_block *super = &sbi->super;
int ret;
ret = scoutfs_wrlock_lock(sb, &held, 1, 1);
if (ret)
return ret;
spin_lock(&sbi->next_ino_lock);
if (!sbi->next_ino_count) {
sbi->next_ino = le64_to_cpu(sbi->super.next_ino);
if (sbi->next_ino + SCOUTFS_INO_BATCH < sbi->next_ino) {
ret = -ENOSPC;
} else {
le64_add_cpu(&sbi->super.next_ino, SCOUTFS_INO_BATCH);
sbi->next_ino_count = SCOUTFS_INO_BATCH;
ret = 0;
}
if (super->next_ino == 0) {
ret = -ENOSPC;
} else {
*ino = le64_to_cpu(super->next_ino);
le64_add_cpu(&super->next_ino, 1);
ret = 0;
}
spin_unlock(&sbi->next_ino_lock);
scoutfs_wrlock_unlock(sb, &held);
return ret;
}
/*
* Inode allocation is at the core of supporting parallel creation.
* Each mount needs to allocate from a pool of free inode numbers which
* map to a shard that it has locked.
*/
int scoutfs_alloc_ino(struct super_block *sb, u64 *ino)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
int ret;
do {
/* don't really care if this is racey */
if (!sbi->next_ino_count) {
ret = get_next_ino_batch(sb);
if (ret)
break;
}
spin_lock(&sbi->next_ino_lock);
if (sbi->next_ino_count) {
*ino = sbi->next_ino++;
sbi->next_ino_count--;
ret = 0;
} else {
ret = -EAGAIN;
}
spin_unlock(&sbi->next_ino_lock);
} while (ret == -EAGAIN);
return ret;
}
@@ -319,14 +273,18 @@ int scoutfs_alloc_ino(struct super_block *sb, u64 *ino)
* creating links to it and updating it. @dir can be null.
*/
struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir,
u64 ino, umode_t mode, dev_t rdev)
umode_t mode, dev_t rdev)
{
DECLARE_SCOUTFS_BTREE_CURSOR(curs);
struct scoutfs_inode_info *ci;
struct scoutfs_key key;
struct inode *inode;
u64 ino;
int ret;
ret = alloc_ino(sb, &ino);
if (ret)
return ERR_PTR(ret);
inode = new_inode(sb);
if (!inode)

View File

@@ -18,8 +18,6 @@ static inline u64 scoutfs_ino(struct inode *inode)
return SCOUTFS_I(inode)->ino;
}
int scoutfs_alloc_ino(struct super_block *sb, u64 *ino);
struct inode *scoutfs_alloc_inode(struct super_block *sb);
void scoutfs_destroy_inode(struct inode *inode);
@@ -27,7 +25,7 @@ struct inode *scoutfs_iget(struct super_block *sb, u64 ino);
int scoutfs_dirty_inode_item(struct inode *inode);
void scoutfs_update_inode_item(struct inode *inode);
struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir,
u64 ino, umode_t mode, dev_t rdev);
umode_t mode, dev_t rdev);
void scoutfs_inode_exit(void);
int scoutfs_inode_init(void);

View File

@@ -1,159 +0,0 @@
/*
* Copyright (C) 2016 Versity Software, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License v2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/random.h>
#include "super.h"
#include "wire.h"
#include "wrlock.h"
#include "roster.h"
/*
* The roster tracks all the mounts on nodes that are working with a
* scoutfs volume.
*
* This trivial first pass lets us test multiple mounts on the same
* node. It'll get a lot more involved as all the nodes manage a roster
* in the shared device.
*/
static DEFINE_MUTEX(roster_mutex);
static u64 roster_next_id = 1;
static LIST_HEAD(roster_list);
/*
* A new mount is adding itself to the roster. It gets a new increasing
* id assigned and all the other mounts are told that it's now a member.
*/
int scoutfs_roster_add(struct super_block *sb)
{
struct scoutfs_sb_info *us = SCOUTFS_SB(sb);
struct scoutfs_sb_info *them;
mutex_lock(&roster_mutex);
list_add_tail(&us->roster_head, &roster_list);
us->roster_id = roster_next_id++;
list_for_each_entry(them, &roster_list, roster_head) {
if (us->roster_id != them->roster_id) {
scoutfs_wrlock_roster_update(them->sb, us->roster_id,
true);
}
}
mutex_unlock(&roster_mutex);
return 0;
}
/*
* A mount is removing itself to the roster. All the other remaining
* mounts are told that it has gone away.
*
* This is safe to call without having called _add.
*/
void scoutfs_roster_remove(struct super_block *sb)
{
struct scoutfs_sb_info *us = SCOUTFS_SB(sb);
struct scoutfs_sb_info *them;
mutex_lock(&roster_mutex);
if (!list_empty(&us->roster_head)) {
list_del_init(&us->roster_head);
list_for_each_entry(them, &roster_list, roster_head)
scoutfs_wrlock_roster_update(them->sb, us->roster_id,
false);
}
mutex_unlock(&roster_mutex);
}
static int process_message(struct super_block *sb, u64 peer_id,
struct scoutfs_message *msg)
{
int ret = 0;
switch (msg->cmd) {
case SCOUTFS_MSG_WRLOCK_REQUEST:
ret = scoutfs_wrlock_process_request(sb, peer_id,
&msg->request);
break;
case SCOUTFS_MSG_WRLOCK_GRANT:
scoutfs_wrlock_process_grant(sb, &msg->grant);
ret = 0;
break;
default:
ret = -EINVAL;
}
return ret;
}
/*
* Send a message to a specific member of the roster identified by its
* id.
*
* We don't actually send anything, we call directly into the receivers
* message processing path with the caller's message.
*/
void scoutfs_roster_send(struct super_block *sb, u64 peer_id,
struct scoutfs_message *msg)
{
struct scoutfs_sb_info *us = SCOUTFS_SB(sb);
struct scoutfs_sb_info *them;
int ret;
mutex_lock(&roster_mutex);
list_for_each_entry(them, &roster_list, roster_head) {
if (them->roster_id == peer_id) {
ret = process_message(them->sb, us->roster_id, msg);
break;
}
}
/* XXX errors? */
mutex_unlock(&roster_mutex);
}
/*
* Send a message to all of the current members which have an id greater
* than the caller's specified id.
*
* We don't actually send anything, we call directly into the receivers
* message processing path with the caller's message.
*/
void scoutfs_roster_broadcast(struct super_block *sb, u64 since_id,
struct scoutfs_message *msg)
{
struct scoutfs_sb_info *us = SCOUTFS_SB(sb);
struct scoutfs_sb_info *them;
int ret;
mutex_lock(&roster_mutex);
list_for_each_entry(them, &roster_list, roster_head) {
if (us->roster_id != them->roster_id &&
them->roster_id > since_id) {
ret = process_message(them->sb, us->roster_id, msg);
if (ret)
break;
}
}
/* XXX errors? */
mutex_unlock(&roster_mutex);
}

View File

@@ -1,14 +0,0 @@
#ifndef _SCOUTFS_ROSTER_H_
#define _SCOUTFS_ROSTER_H_
struct scoutfs_message;
int scoutfs_roster_add(struct super_block *sb);
void scoutfs_roster_remove(struct super_block *sb);
void scoutfs_roster_send(struct super_block *sb, u64 peer_id,
struct scoutfs_message *msg);
void scoutfs_roster_broadcast(struct super_block *sb, u64 since_id,
struct scoutfs_message *msg);
#endif

View File

@@ -26,8 +26,6 @@
#include "block.h"
#include "counters.h"
#include "trans.h"
#include "roster.h"
#include "wrlock.h"
#include "trace.h"
#include "scoutfs_trace.h"
@@ -162,7 +160,6 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent)
spin_lock_init(&sbi->trans_write_lock);
INIT_WORK(&sbi->trans_write_work, scoutfs_trans_write_func);
init_waitqueue_head(&sbi->trans_write_wq);
INIT_LIST_HEAD(&sbi->roster_head);
sbi->ctr = atomic64_inc_return(&scoutfs_sb_ctr);
@@ -174,8 +171,6 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent)
ret = scoutfs_setup_counters(sb) ?:
read_supers(sb) ?:
scoutfs_setup_trans(sb) ?:
scoutfs_wrlock_setup(sb) ?:
scoutfs_roster_add(sb) ?:
scoutfs_read_buddy_chunks(sb);
if (ret)
return ret;
@@ -206,8 +201,6 @@ static void scoutfs_kill_sb(struct super_block *sb)
kill_block_super(sb);
if (sbi) {
scoutfs_roster_remove(sb);
scoutfs_wrlock_teardown(sb);
scoutfs_shutdown_trans(sb);
scoutfs_destroy_counters(sb);
if (sbi->kset)

View File

@@ -9,7 +9,6 @@
struct scoutfs_counters;
struct buddy_alloc;
struct wrlock_context;
struct scoutfs_sb_info {
struct super_block *sb;
@@ -19,8 +18,6 @@ struct scoutfs_sb_info {
struct scoutfs_super_block super;
spinlock_t next_ino_lock;
u64 next_ino;
u64 next_ino_count;
spinlock_t block_lock;
struct radix_tree_root block_radix;
@@ -48,11 +45,6 @@ struct scoutfs_sb_info {
struct kset *kset;
struct scoutfs_counters *counters;
struct list_head roster_head;
u64 roster_id;
struct wrlock_context *wrlock_context;
};
static inline struct scoutfs_sb_info *SCOUTFS_SB(struct super_block *sb)

View File

@@ -1,36 +0,0 @@
#ifndef _SCOUTFS_WIRE_H_
#define _SCOUTFS_WIRE_H_
/* an arbitrarily small number to keep things reasonable */
#define SCOUTFS_WRLOCK_MAX_SHARDS 5
enum {
SCOUTFS_MSG_WRLOCK_REQUEST = 1,
SCOUTFS_MSG_WRLOCK_GRANT = 2,
};
struct scoutfs_wrlock_id {
__le64 counter;
__le32 jitter;
} __packed;
struct scoutfs_wrlock_request {
struct scoutfs_wrlock_id wid;
u8 nr_shards;
__le32 shards[SCOUTFS_WRLOCK_MAX_SHARDS];
} __packed;
struct scoutfs_wrlock_grant {
struct scoutfs_wrlock_id wid;
} __packed;
struct scoutfs_message {
u8 cmd;
u8 len;
union {
struct scoutfs_wrlock_grant grant;
struct scoutfs_wrlock_request request;
} __packed;
} __packed;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +0,0 @@
#ifndef _SCOUTFS_WRLOCK_H_
#define _SCOUTFS_WRLOCK_H_
#include "wire.h"
struct scoutfs_wrlock_held {
u8 nr_shards;
u32 shards[SCOUTFS_WRLOCK_MAX_SHARDS];
};
#define DECLARE_SCOUTFS_WRLOCK_HELD(held) \
struct scoutfs_wrlock_held held = {0, }
int scoutfs_wrlock_lock(struct super_block *sb,
struct scoutfs_wrlock_held *held, int nr_inos, ...);
void scoutfs_wrlock_unlock(struct super_block *sb,
struct scoutfs_wrlock_held *held);
void scoutfs_wrlock_roster_update(struct super_block *sb, u64 peer_id,
bool join);
int scoutfs_wrlock_process_request(struct super_block *sb, u64 peer_id,
struct scoutfs_wrlock_request *req);
void scoutfs_wrlock_process_grant(struct super_block *sb,
struct scoutfs_wrlock_grant *grant);
int scoutfs_wrlock_setup(struct super_block *sb);
void scoutfs_wrlock_teardown(struct super_block *sb);
#endif