mirror of
https://github.com/versity/scoutfs.git
synced 2026-06-08 20:52:35 +00:00
Merge pull request #68 from versity/zab/collection_of_fixes
Zab/collection of fixes
This commit is contained in:
@@ -511,7 +511,7 @@ out:
|
||||
else if (ino == 0)
|
||||
inode = NULL;
|
||||
else
|
||||
inode = scoutfs_iget(sb, ino, 0);
|
||||
inode = scoutfs_iget(sb, ino, 0, 0);
|
||||
|
||||
/*
|
||||
* We can't splice dir aliases into the dcache. dir entries
|
||||
|
||||
@@ -81,7 +81,7 @@ static struct dentry *scoutfs_fh_to_dentry(struct super_block *sb,
|
||||
trace_scoutfs_fh_to_dentry(sb, fh_type, sfid);
|
||||
|
||||
if (scoutfs_valid_fileid(fh_type))
|
||||
inode = scoutfs_iget(sb, le64_to_cpu(sfid->ino), 0);
|
||||
inode = scoutfs_iget(sb, le64_to_cpu(sfid->ino), 0, SCOUTFS_IGF_LINKED);
|
||||
|
||||
return d_obtain_alias(inode);
|
||||
}
|
||||
@@ -100,7 +100,7 @@ static struct dentry *scoutfs_fh_to_parent(struct super_block *sb,
|
||||
|
||||
if (scoutfs_valid_fileid(fh_type) &&
|
||||
fh_type == FILEID_SCOUTFS_WITH_PARENT)
|
||||
inode = scoutfs_iget(sb, le64_to_cpu(sfid->parent_ino), 0);
|
||||
inode = scoutfs_iget(sb, le64_to_cpu(sfid->parent_ino), 0, SCOUTFS_IGF_LINKED);
|
||||
|
||||
return d_obtain_alias(inode);
|
||||
}
|
||||
@@ -123,7 +123,7 @@ static struct dentry *scoutfs_get_parent(struct dentry *child)
|
||||
scoutfs_dir_free_backref_path(sb, &list);
|
||||
trace_scoutfs_get_parent(sb, inode, ino);
|
||||
|
||||
inode = scoutfs_iget(sb, ino, 0);
|
||||
inode = scoutfs_iget(sb, ino, 0, SCOUTFS_IGF_LINKED);
|
||||
|
||||
return d_obtain_alias(inode);
|
||||
}
|
||||
|
||||
@@ -276,7 +276,7 @@ static void load_inode(struct inode *inode, struct scoutfs_inode *cinode)
|
||||
set_item_info(si, cinode);
|
||||
}
|
||||
|
||||
static void init_inode_key(struct scoutfs_key *key, u64 ino)
|
||||
void scoutfs_inode_init_key(struct scoutfs_key *key, u64 ino)
|
||||
{
|
||||
*key = (struct scoutfs_key) {
|
||||
.sk_zone = SCOUTFS_FS_ZONE,
|
||||
@@ -296,8 +296,7 @@ static void init_inode_key(struct scoutfs_key *key, u64 ino)
|
||||
* fields because they should have already had a locked refreshed inode
|
||||
* to be dereferencing its contents.
|
||||
*/
|
||||
int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock,
|
||||
int flags)
|
||||
int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock)
|
||||
{
|
||||
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
|
||||
struct super_block *sb = inode->i_sb;
|
||||
@@ -317,7 +316,7 @@ int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock,
|
||||
if (atomic64_read(&si->last_refreshed) == refresh_gen)
|
||||
return 0;
|
||||
|
||||
init_inode_key(&key, scoutfs_ino(inode));
|
||||
scoutfs_inode_init_key(&key, scoutfs_ino(inode));
|
||||
|
||||
mutex_lock(&si->item_mutex);
|
||||
if (atomic64_read(&si->last_refreshed) < refresh_gen) {
|
||||
@@ -697,21 +696,20 @@ struct inode *scoutfs_ilookup(struct super_block *sb, u64 ino)
|
||||
return ilookup5(sb, ino, scoutfs_iget_test, &ino);
|
||||
}
|
||||
|
||||
struct inode *scoutfs_iget(struct super_block *sb, u64 ino, int lkf)
|
||||
struct inode *scoutfs_iget(struct super_block *sb, u64 ino, int lkf, int igf)
|
||||
{
|
||||
struct scoutfs_lock *lock = NULL;
|
||||
struct scoutfs_inode_info *si;
|
||||
struct inode *inode;
|
||||
struct inode *inode = NULL;
|
||||
int ret;
|
||||
|
||||
ret = scoutfs_lock_ino(sb, SCOUTFS_LOCK_READ, lkf, ino, &lock);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
inode = iget5_locked(sb, ino, scoutfs_iget_test, scoutfs_iget_set,
|
||||
&ino);
|
||||
inode = iget5_locked(sb, ino, scoutfs_iget_test, scoutfs_iget_set, &ino);
|
||||
if (!inode) {
|
||||
inode = ERR_PTR(-ENOMEM);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -721,20 +719,33 @@ struct inode *scoutfs_iget(struct super_block *sb, u64 ino, int lkf)
|
||||
atomic64_set(&si->last_refreshed, 0);
|
||||
inode->i_version = 0;
|
||||
|
||||
ret = scoutfs_inode_refresh(inode, lock, 0);
|
||||
if (ret == 0)
|
||||
ret = scoutfs_omap_inc(sb, ino);
|
||||
if (ret) {
|
||||
iget_failed(inode);
|
||||
inode = ERR_PTR(ret);
|
||||
} else {
|
||||
set_inode_ops(inode);
|
||||
unlock_new_inode(inode);
|
||||
ret = scoutfs_inode_refresh(inode, lock);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if ((igf & SCOUTFS_IGF_LINKED) && inode->i_nlink == 0) {
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = scoutfs_omap_inc(sb, ino);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
set_inode_ops(inode);
|
||||
unlock_new_inode(inode);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_READ);
|
||||
|
||||
if (ret < 0) {
|
||||
if (inode)
|
||||
iget_failed(inode);
|
||||
inode = ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return inode;
|
||||
}
|
||||
|
||||
@@ -803,7 +814,7 @@ int scoutfs_dirty_inode_item(struct inode *inode, struct scoutfs_lock *lock)
|
||||
|
||||
store_inode(&sinode, inode);
|
||||
|
||||
init_inode_key(&key, scoutfs_ino(inode));
|
||||
scoutfs_inode_init_key(&key, scoutfs_ino(inode));
|
||||
|
||||
ret = scoutfs_item_update(sb, &key, &sinode, sizeof(sinode), lock);
|
||||
if (!ret)
|
||||
@@ -1022,7 +1033,7 @@ void scoutfs_update_inode_item(struct inode *inode, struct scoutfs_lock *lock,
|
||||
ret = update_indices(sb, si, ino, inode->i_mode, &sinode, lock_list);
|
||||
BUG_ON(ret);
|
||||
|
||||
init_inode_key(&key, ino);
|
||||
scoutfs_inode_init_key(&key, ino);
|
||||
|
||||
err = scoutfs_item_update(sb, &key, &sinode, sizeof(sinode), lock);
|
||||
if (err) {
|
||||
@@ -1421,7 +1432,7 @@ struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir,
|
||||
set_inode_ops(inode);
|
||||
|
||||
store_inode(&sinode, inode);
|
||||
init_inode_key(&key, scoutfs_ino(inode));
|
||||
scoutfs_inode_init_key(&key, scoutfs_ino(inode));
|
||||
|
||||
ret = scoutfs_omap_inc(sb, ino);
|
||||
if (ret < 0)
|
||||
@@ -1546,7 +1557,7 @@ static int delete_inode_items(struct super_block *sb, u64 ino, struct scoutfs_lo
|
||||
goto out;
|
||||
}
|
||||
|
||||
init_inode_key(&key, ino);
|
||||
scoutfs_inode_init_key(&key, ino);
|
||||
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, &sinode, sizeof(sinode),
|
||||
lock);
|
||||
@@ -1855,7 +1866,7 @@ static void inode_orphan_scan_worker(struct work_struct *work)
|
||||
}
|
||||
|
||||
/* try to cached and evict unused inode to delete, can be racing */
|
||||
inode = scoutfs_iget(sb, ino, 0);
|
||||
inode = scoutfs_iget(sb, ino, 0, 0);
|
||||
if (IS_ERR(inode)) {
|
||||
ret = PTR_ERR(inode);
|
||||
if (ret == -ENOENT)
|
||||
|
||||
@@ -80,9 +80,11 @@ int scoutfs_drop_inode(struct inode *inode);
|
||||
void scoutfs_evict_inode(struct inode *inode);
|
||||
void scoutfs_inode_queue_iput(struct inode *inode);
|
||||
|
||||
struct inode *scoutfs_iget(struct super_block *sb, u64 ino, int lkf);
|
||||
#define SCOUTFS_IGF_LINKED (1 << 0) /* enoent if nlink == 0 */
|
||||
struct inode *scoutfs_iget(struct super_block *sb, u64 ino, int lkf, int igf);
|
||||
struct inode *scoutfs_ilookup(struct super_block *sb, u64 ino);
|
||||
|
||||
void scoutfs_inode_init_key(struct scoutfs_key *key, u64 ino);
|
||||
void scoutfs_inode_init_index_key(struct scoutfs_key *key, u8 type, u64 major,
|
||||
u32 minor, u64 ino);
|
||||
int scoutfs_inode_index_start(struct super_block *sb, u64 *seq);
|
||||
@@ -117,8 +119,7 @@ u64 scoutfs_inode_data_version(struct inode *inode);
|
||||
void scoutfs_inode_get_onoff(struct inode *inode, s64 *on, s64 *off);
|
||||
int scoutfs_complete_truncate(struct inode *inode, struct scoutfs_lock *lock);
|
||||
|
||||
int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock,
|
||||
int flags);
|
||||
int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock);
|
||||
int scoutfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
struct kstat *stat);
|
||||
int scoutfs_setattr(struct dentry *dentry, struct iattr *attr);
|
||||
|
||||
@@ -1320,6 +1320,84 @@ out:
|
||||
return ret ?: count;
|
||||
}
|
||||
|
||||
static long scoutfs_ioc_get_allocated_inos(struct file *file, unsigned long arg)
|
||||
{
|
||||
struct super_block *sb = file_inode(file)->i_sb;
|
||||
struct scoutfs_ioctl_get_allocated_inos __user *ugai = (void __user *)arg;
|
||||
struct scoutfs_ioctl_get_allocated_inos gai;
|
||||
struct scoutfs_lock *lock = NULL;
|
||||
struct scoutfs_key key;
|
||||
struct scoutfs_key end;
|
||||
u64 __user *uinos;
|
||||
u64 bytes;
|
||||
u64 ino;
|
||||
int nr;
|
||||
int ret;
|
||||
|
||||
if (!(file->f_mode & FMODE_READ)) {
|
||||
ret = -EBADF;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN)) {
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (copy_from_user(&gai, ugai, sizeof(gai))) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((gai.inos_ptr & (sizeof(__u64) - 1)) || (gai.inos_bytes < sizeof(__u64))) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
scoutfs_inode_init_key(&key, gai.start_ino);
|
||||
scoutfs_inode_init_key(&end, gai.start_ino | SCOUTFS_LOCK_INODE_GROUP_MASK);
|
||||
uinos = (void __user *)gai.inos_ptr;
|
||||
bytes = gai.inos_bytes;
|
||||
nr = 0;
|
||||
|
||||
ret = scoutfs_lock_ino(sb, SCOUTFS_LOCK_READ, 0, gai.start_ino, &lock);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
while (bytes >= sizeof(*uinos)) {
|
||||
|
||||
ret = scoutfs_item_next(sb, &key, &end, NULL, 0, lock);
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOENT)
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (key.sk_zone != SCOUTFS_FS_ZONE) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* all fs items are owned by allocated inodes, and _first is always ino */
|
||||
ino = le64_to_cpu(key._sk_first);
|
||||
if (put_user(ino, uinos)) {
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
uinos++;
|
||||
bytes -= sizeof(*uinos);
|
||||
if (++nr == INT_MAX)
|
||||
break;
|
||||
|
||||
scoutfs_inode_init_key(&key, ino + 1);
|
||||
}
|
||||
|
||||
scoutfs_unlock(sb, lock, SCOUTFS_LOCK_READ);
|
||||
out:
|
||||
return ret ?: nr;
|
||||
}
|
||||
|
||||
long scoutfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
switch (cmd) {
|
||||
@@ -1353,6 +1431,8 @@ long scoutfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
return scoutfs_ioc_resize_devices(file, arg);
|
||||
case SCOUTFS_IOC_READ_XATTR_TOTALS:
|
||||
return scoutfs_ioc_read_xattr_totals(file, arg);
|
||||
case SCOUTFS_IOC_GET_ALLOCATED_INOS:
|
||||
return scoutfs_ioc_get_allocated_inos(file, arg);
|
||||
}
|
||||
|
||||
return -ENOTTY;
|
||||
|
||||
@@ -520,4 +520,43 @@ struct scoutfs_ioctl_xattr_total {
|
||||
#define SCOUTFS_IOC_READ_XATTR_TOTALS \
|
||||
_IOW(SCOUTFS_IOCTL_MAGIC, 15, struct scoutfs_ioctl_read_xattr_totals)
|
||||
|
||||
/*
|
||||
* This fills the caller's inos array with inode numbers that are in use
|
||||
* after the start ino, within an internal inode group.
|
||||
*
|
||||
* This only makes a promise about the state of the inode numbers within
|
||||
* the first and last numbers returned by one call. At one time, all of
|
||||
* those inodes were still allocated. They could have changed before
|
||||
* the call returned. And any numbers outside of the first and last
|
||||
* (or single) are undefined.
|
||||
*
|
||||
* This doesn't iterate over all allocated inodes, it only probes a
|
||||
* single group that the start inode is within. This interface was
|
||||
* first introduced to support tests that needed to find out about a
|
||||
* specific inode, while having some other similarly niche uses. It is
|
||||
* unsuitable for a consistent iteration over all the inode numbers in
|
||||
* use.
|
||||
*
|
||||
* This test of inode items doesn't serialize with the inode lifetime
|
||||
* mechanism. It only tells you the numbers of inodes that were once
|
||||
* active in the system and haven't yet been fully deleted. The inode
|
||||
* numbers returned could have been in the process of being deleted and
|
||||
* were already unreachable even before the call started.
|
||||
*
|
||||
* @start_ino: the first inode number that could be returned
|
||||
* @inos_ptr: pointer to an aligned array of 64bit inode numbers
|
||||
* @inos_bytes: the number of bytes available in the inos_ptr array
|
||||
*
|
||||
* Returns errors or the count of inode numbers returned, quite possibly
|
||||
* including 0.
|
||||
*/
|
||||
struct scoutfs_ioctl_get_allocated_inos {
|
||||
__u64 start_ino;
|
||||
__u64 inos_ptr;
|
||||
__u64 inos_bytes;
|
||||
};
|
||||
|
||||
#define SCOUTFS_IOC_GET_ALLOCATED_INOS \
|
||||
_IOW(SCOUTFS_IOCTL_MAGIC, 16, struct scoutfs_ioctl_get_allocated_inos)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1050,7 +1050,7 @@ int scoutfs_lock_inode(struct super_block *sb, enum scoutfs_lock_mode mode, int
|
||||
goto out;
|
||||
|
||||
if (flags & SCOUTFS_LKF_REFRESH_INODE) {
|
||||
ret = scoutfs_inode_refresh(inode, *lock, flags);
|
||||
ret = scoutfs_inode_refresh(inode, *lock);
|
||||
if (ret < 0) {
|
||||
scoutfs_unlock(sb, *lock, mode);
|
||||
*lock = NULL;
|
||||
|
||||
@@ -675,28 +675,18 @@ static void scoutfs_net_recv_worker(struct work_struct *work)
|
||||
|
||||
scoutfs_tseq_add(&ninf->msg_tseq_tree, &mrecv->tseq_entry);
|
||||
|
||||
/*
|
||||
* We want to drain the proc_workq in order to ensure that
|
||||
* that the inflight lock recovery work is fully flushed out
|
||||
* so that we can prevent the client/server racing trying to
|
||||
* do lock recovery and processing farewell at the same time.
|
||||
*/
|
||||
if (nh.cmd == SCOUTFS_NET_CMD_FAREWELL && conn->listening_conn)
|
||||
drain_workqueue(conn->proc_workq);
|
||||
|
||||
/*
|
||||
* Initial received greetings and farewell are processed
|
||||
* Initial received greetings are processed
|
||||
* synchronously before any other incoming messages.
|
||||
*
|
||||
* Incoming requests or responses to the lock client are
|
||||
* called synchronously to avoid reordering.
|
||||
*/
|
||||
if (nh.cmd == SCOUTFS_NET_CMD_GREETING ||
|
||||
(nh.cmd == SCOUTFS_NET_CMD_FAREWELL && conn->listening_conn) ||
|
||||
(nh.cmd == SCOUTFS_NET_CMD_LOCK && !conn->listening_conn))
|
||||
scoutfs_net_proc_worker(&mrecv->proc_work);
|
||||
else
|
||||
queue_work(conn->proc_workq, &mrecv->proc_work);
|
||||
queue_work(conn->workq, &mrecv->proc_work);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
@@ -861,7 +851,6 @@ static void scoutfs_net_destroy_worker(struct work_struct *work)
|
||||
}
|
||||
|
||||
destroy_workqueue(conn->workq);
|
||||
destroy_workqueue(conn->proc_workq);
|
||||
scoutfs_tseq_del(&ninf->conn_tseq_tree, &conn->tseq_entry);
|
||||
kfree(conn->info);
|
||||
trace_scoutfs_conn_destroy_free(conn);
|
||||
@@ -1161,8 +1150,6 @@ static void scoutfs_net_shutdown_worker(struct work_struct *work)
|
||||
/* wait for socket and proc work to finish, includes chained work */
|
||||
drain_workqueue(conn->workq);
|
||||
|
||||
drain_workqueue(conn->proc_workq);
|
||||
|
||||
/* tear down the sock now that all work is done */
|
||||
if (conn->sock) {
|
||||
sock_release(conn->sock);
|
||||
@@ -1360,7 +1347,7 @@ scoutfs_net_alloc_conn(struct super_block *sb,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
conn->workq = alloc_workqueue("scoutfs_net_workq_%s",
|
||||
conn->workq = alloc_workqueue("scoutfs_net_%s",
|
||||
WQ_UNBOUND | WQ_NON_REENTRANT, 0,
|
||||
name_suffix);
|
||||
if (!conn->workq) {
|
||||
@@ -1369,16 +1356,6 @@ scoutfs_net_alloc_conn(struct super_block *sb,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
conn->proc_workq = alloc_workqueue("scoutfs_net_proc_workq_%s",
|
||||
WQ_UNBOUND | WQ_NON_REENTRANT, 0,
|
||||
name_suffix);
|
||||
if (!conn->proc_workq) {
|
||||
destroy_workqueue(conn->workq);
|
||||
kfree(conn->info);
|
||||
kfree(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
conn->sb = sb;
|
||||
conn->notify_up = notify_up;
|
||||
conn->notify_down = notify_down;
|
||||
@@ -1411,14 +1388,6 @@ scoutfs_net_alloc_conn(struct super_block *sb,
|
||||
return conn;
|
||||
}
|
||||
|
||||
/* Give the caller the client info of the connection. This is used by
|
||||
* server processing the server_farewell, and lock response/recovery.
|
||||
*/
|
||||
void *scoutfs_net_client_info(struct scoutfs_net_connection *conn)
|
||||
{
|
||||
return conn->info;
|
||||
}
|
||||
|
||||
/*
|
||||
* Give the caller the client rid of the connection. This used by rare
|
||||
* server processing callers who want to send async responses after
|
||||
@@ -1803,23 +1772,6 @@ int scoutfs_net_response_node(struct super_block *sb,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* The response function that was submitted with the request is not
|
||||
* called if the request is canceled here.
|
||||
*/
|
||||
void scoutfs_net_cancel_request(struct super_block *sb,
|
||||
struct scoutfs_net_connection *conn,
|
||||
u8 cmd, u64 id)
|
||||
{
|
||||
struct message_send *msend;
|
||||
|
||||
spin_lock(&conn->lock);
|
||||
msend = find_request(conn, cmd, id);
|
||||
if (msend)
|
||||
complete_send(conn, msend);
|
||||
spin_unlock(&conn->lock);
|
||||
}
|
||||
|
||||
struct sync_request_completion {
|
||||
struct completion comp;
|
||||
void *resp;
|
||||
|
||||
@@ -63,7 +63,6 @@ struct scoutfs_net_connection {
|
||||
atomic64_t recv_seq;
|
||||
|
||||
struct workqueue_struct *workq;
|
||||
struct workqueue_struct *proc_workq;
|
||||
struct work_struct listen_work;
|
||||
struct work_struct connect_work;
|
||||
struct work_struct send_work;
|
||||
@@ -116,7 +115,6 @@ scoutfs_net_alloc_conn(struct super_block *sb,
|
||||
scoutfs_net_notify_t notify_up,
|
||||
scoutfs_net_notify_t notify_down, size_t info_size,
|
||||
scoutfs_net_request_t *req_funcs, char *name_suffix);
|
||||
void *scoutfs_net_client_info(struct scoutfs_net_connection *conn);
|
||||
u64 scoutfs_net_client_rid(struct scoutfs_net_connection *conn);
|
||||
int scoutfs_net_connect(struct super_block *sb,
|
||||
struct scoutfs_net_connection *conn,
|
||||
@@ -136,9 +134,6 @@ int scoutfs_net_submit_request_node(struct super_block *sb,
|
||||
u64 rid, u8 cmd, void *arg, u16 arg_len,
|
||||
scoutfs_net_response_t resp_func,
|
||||
void *resp_data, u64 *id_ret);
|
||||
void scoutfs_net_cancel_request(struct super_block *sb,
|
||||
struct scoutfs_net_connection *conn,
|
||||
u8 cmd, u64 id);
|
||||
int scoutfs_net_sync_request(struct super_block *sb,
|
||||
struct scoutfs_net_connection *conn,
|
||||
u8 cmd, void *arg, unsigned arg_len,
|
||||
|
||||
@@ -262,7 +262,7 @@ void scoutfs_recov_shutdown(struct super_block *sb)
|
||||
recinf->timeout_fn = NULL;
|
||||
spin_unlock(&recinf->lock);
|
||||
|
||||
list_for_each_entry_safe(pend, tmp, &recinf->pending, head) {
|
||||
list_for_each_entry_safe(pend, tmp, &list, head) {
|
||||
list_del(&pend->head);
|
||||
kfree(pend);
|
||||
}
|
||||
|
||||
@@ -122,7 +122,6 @@ struct server_info {
|
||||
struct server_client_info {
|
||||
u64 rid;
|
||||
struct list_head head;
|
||||
bool received_farewell;
|
||||
};
|
||||
|
||||
static __le64 *first_valopt(struct scoutfs_volume_options *valopt)
|
||||
@@ -172,7 +171,7 @@ static bool test_shutting_down(struct server_info *server)
|
||||
static void set_shutting_down(struct server_info *server, bool val)
|
||||
{
|
||||
server->shutting_down = val;
|
||||
smp_rmb();
|
||||
smp_wmb();
|
||||
}
|
||||
|
||||
static void stop_server(struct server_info *server)
|
||||
@@ -1506,15 +1505,11 @@ static int server_lock(struct super_block *sb,
|
||||
struct scoutfs_net_connection *conn,
|
||||
u8 cmd, u64 id, void *arg, u16 arg_len)
|
||||
{
|
||||
struct server_client_info *sci = scoutfs_net_client_info(conn);
|
||||
u64 rid = scoutfs_net_client_rid(conn);
|
||||
|
||||
if (arg_len != sizeof(struct scoutfs_net_lock))
|
||||
return -EINVAL;
|
||||
|
||||
if (sci->received_farewell)
|
||||
return scoutfs_net_response(sb, conn, cmd, id, -EINVAL, NULL, 0);
|
||||
|
||||
return scoutfs_lock_server_request(sb, rid, id, arg);
|
||||
}
|
||||
|
||||
@@ -1523,15 +1518,11 @@ static int lock_response(struct super_block *sb,
|
||||
void *resp, unsigned int resp_len,
|
||||
int error, void *data)
|
||||
{
|
||||
struct server_client_info *sci = scoutfs_net_client_info(conn);
|
||||
u64 rid = scoutfs_net_client_rid(conn);
|
||||
|
||||
if (resp_len != sizeof(struct scoutfs_net_lock))
|
||||
return -EINVAL;
|
||||
|
||||
if (sci->received_farewell)
|
||||
return 0;
|
||||
|
||||
return scoutfs_lock_server_response(sb, rid, resp);
|
||||
}
|
||||
|
||||
@@ -1569,15 +1560,11 @@ static int lock_recover_response(struct super_block *sb,
|
||||
void *resp, unsigned int resp_len,
|
||||
int error, void *data)
|
||||
{
|
||||
struct server_client_info *sci = scoutfs_net_client_info(conn);
|
||||
u64 rid = scoutfs_net_client_rid(conn);
|
||||
|
||||
if (invalid_recover(resp, resp_len))
|
||||
return -EINVAL;
|
||||
|
||||
if (sci->received_farewell)
|
||||
return 0;
|
||||
|
||||
return scoutfs_lock_server_recover_response(sb, rid, resp);
|
||||
}
|
||||
|
||||
@@ -3462,6 +3449,18 @@ static void farewell_worker(struct work_struct *work)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Responses that are ready to send can be further delayed by
|
||||
* moving them back to the reqs list.
|
||||
*/
|
||||
list_for_each_entry_safe(fw, tmp, &send, entry) {
|
||||
/* finish lock recovery before destroying locks, fenced if too long */
|
||||
if (scoutfs_recov_is_pending(sb, fw->rid, SCOUTFS_RECOV_LOCKS)) {
|
||||
list_move_tail(&fw->entry, &reqs);
|
||||
quo_reqs++;
|
||||
}
|
||||
}
|
||||
|
||||
/* clean up resources for mounts before sending responses */
|
||||
list_for_each_entry_safe(fw, tmp, &send, entry) {
|
||||
ret = reclaim_rid(sb, fw->rid);
|
||||
@@ -3529,11 +3528,9 @@ static int server_farewell(struct super_block *sb,
|
||||
struct scoutfs_net_connection *conn,
|
||||
u8 cmd, u64 id, void *arg, u16 arg_len)
|
||||
{
|
||||
struct server_client_info *sci = scoutfs_net_client_info(conn);
|
||||
struct server_info *server = SCOUTFS_SB(sb)->server_info;
|
||||
u64 rid = scoutfs_net_client_rid(conn);
|
||||
struct farewell_request *fw;
|
||||
int ret;
|
||||
|
||||
if (arg_len != 0)
|
||||
return -EINVAL;
|
||||
@@ -3551,20 +3548,6 @@ static int server_farewell(struct super_block *sb,
|
||||
list_add_tail(&fw->entry, &server->farewell_requests);
|
||||
spin_unlock(&server->farewell_lock);
|
||||
|
||||
/*
|
||||
* Tear down client lock server state and set that we recieved farewell
|
||||
* to ensure that we do not race between client and server trying to process
|
||||
* lock recovery at the same time (race). We also want to mark that the recovery
|
||||
* finished so that if client's try to send stuff later; the server doesnt care.
|
||||
*/
|
||||
sci->received_farewell = true;
|
||||
ret = scoutfs_lock_server_farewell(sb, rid);
|
||||
if (ret < 0) {
|
||||
kfree(fw);
|
||||
return ret;
|
||||
}
|
||||
scoutfs_server_recov_finish(sb, rid, SCOUTFS_RECOV_LOCKS);
|
||||
|
||||
queue_farewell_work(server);
|
||||
|
||||
/* response will be sent later */
|
||||
@@ -3656,8 +3639,14 @@ static void finished_recovery(struct super_block *sb)
|
||||
|
||||
void scoutfs_server_recov_finish(struct super_block *sb, u64 rid, int which)
|
||||
{
|
||||
DECLARE_SERVER_INFO(sb, server);
|
||||
|
||||
if (scoutfs_recov_finish(sb, rid, which) > 0)
|
||||
finished_recovery(sb);
|
||||
|
||||
/* rid's farewell response might be sent after it finishes lock recov */
|
||||
if (which & SCOUTFS_RECOV_LOCKS)
|
||||
queue_farewell_work(server);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -601,7 +601,7 @@ static int scoutfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
goto out;
|
||||
|
||||
/* this interruptible iget lets hung mount be aborted with ctl-c */
|
||||
inode = scoutfs_iget(sb, SCOUTFS_ROOT_INO, SCOUTFS_LKF_INTERRUPTIBLE);
|
||||
inode = scoutfs_iget(sb, SCOUTFS_ROOT_INO, SCOUTFS_LKF_INTERRUPTIBLE, 0);
|
||||
if (IS_ERR(inode)) {
|
||||
ret = PTR_ERR(inode);
|
||||
if (ret == -ERESTARTSYS)
|
||||
|
||||
@@ -227,8 +227,9 @@ test "$T_QUORUM" -le "$T_NR_MOUNTS" || \
|
||||
die "-q quorum mmembers must not be greater than -n mounts"
|
||||
|
||||
# top level paths
|
||||
T_KMOD=$(realpath "$(dirname $0)/../kmod")
|
||||
T_UTILS=$(realpath "$T_KMOD/../utils")
|
||||
T_TESTS=$(realpath "$(dirname $0)")
|
||||
T_KMOD=$(realpath "$T_TESTS/../kmod")
|
||||
T_UTILS=$(realpath "$T_TESTS/../utils")
|
||||
|
||||
test -d "$T_KMOD" || die "kmod/ repo dir $T_KMOD not directory"
|
||||
test -d "$T_UTILS" || die "utils/ repo dir $T_UTILS not directory"
|
||||
@@ -382,7 +383,7 @@ cmd grep . /sys/kernel/debug/tracing/options/trace_printk \
|
||||
conf="$T_RESULTS/scoutfs-fencd.conf"
|
||||
cat > $conf << EOF
|
||||
SCOUTFS_FENCED_DELAY=1
|
||||
SCOUTFS_FENCED_RUN=$T_UTILS/fenced/local-force-unmount
|
||||
SCOUTFS_FENCED_RUN=$T_TESTS/fenced-local-force-unmount.sh
|
||||
SCOUTFS_FENCED_RUN_ARGS=""
|
||||
EOF
|
||||
export SCOUTFS_FENCED_CONFIG_FILE="$conf"
|
||||
|
||||
@@ -26,7 +26,8 @@ inode_exists()
|
||||
{
|
||||
local ino="$1"
|
||||
|
||||
handle_cat "$T_M0" "$ino" > "$T_TMP.handle_cat.log" 2>&1
|
||||
scoutfs get-allocated-inos -i "$ino" -s -p "$T_M0" > $T_TMP.inos.log 2>&1
|
||||
test "$?" == 0 -a "$(head -1 $T_TMP.inos.log)" == "$ino"
|
||||
}
|
||||
|
||||
echo "== test our inode existance function"
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# delay, in seconds, between each check for pending fence requests.
|
||||
SCOUTFS_FENCED_DELAY=1
|
||||
SCOUTFS_FENCED_RUN=/usr/libexec/scoutfs-fenced/run/local-force-unmount
|
||||
# path to executable to run to service fence request
|
||||
#SCOUTFS_FENCED_RUN=
|
||||
# arguments to pass to binary
|
||||
SCOUTFS_FENCED_RUN_ARGS=""
|
||||
|
||||
@@ -617,6 +617,33 @@ command is used first.
|
||||
.RE
|
||||
.PD
|
||||
|
||||
.TP
|
||||
.BI "get-allocated-inos [-i|--ino INO] [-s|--single] [-p|--path PATH]"
|
||||
.sp
|
||||
This debugging command prints allocated inode numbers. It only prints
|
||||
inodes
|
||||
found in the group that contains the starting inode. The printed inode
|
||||
numbers aren't necessarily reachable. They could be anywhere in the
|
||||
process from being unlinked to finally deleted when their items
|
||||
were found.
|
||||
.RS 1.0i
|
||||
.PD 0
|
||||
.TP
|
||||
.sp
|
||||
.B "-i, --ino INO"
|
||||
The first 64bit inode number which could be printed.
|
||||
.TP
|
||||
.B "-s, --single"
|
||||
Only print the single starting inode when it is allocated, all other allocated
|
||||
inode numbers will be ignored.
|
||||
.TP
|
||||
.B "-p, --path PATH"
|
||||
A path within a ScoutFS filesystem.
|
||||
.RE
|
||||
.PD
|
||||
|
||||
.TP
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR scoutfs (5),
|
||||
.BR xattr (7),
|
||||
|
||||
@@ -55,7 +55,6 @@ install -m 755 -D src/scoutfs $RPM_BUILD_ROOT%{_sbindir}/scoutfs
|
||||
install -m 644 -D src/ioctl.h $RPM_BUILD_ROOT%{_includedir}/scoutfs/ioctl.h
|
||||
install -m 644 -D src/format.h $RPM_BUILD_ROOT%{_includedir}/scoutfs/format.h
|
||||
install -m 755 -D fenced/scoutfs-fenced $RPM_BUILD_ROOT%{_libexecdir}/scoutfs-fenced/scoutfs-fenced
|
||||
install -m 755 -D fenced/local-force-unmount $RPM_BUILD_ROOT%{_libexecdir}/scoutfs-fenced/run/local-force-unmount
|
||||
install -m 644 -D fenced/scoutfs-fenced.service $RPM_BUILD_ROOT%{_unitdir}/scoutfs-fenced.service
|
||||
install -m 644 -D fenced/scoutfs-fenced.conf.example $RPM_BUILD_ROOT%{_sysconfdir}/scoutfs/scoutfs-fenced.conf.example
|
||||
|
||||
|
||||
137
utils/src/get_allocated_inos.c
Normal file
137
utils/src/get_allocated_inos.c
Normal file
@@ -0,0 +1,137 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <argp.h>
|
||||
|
||||
#include "sparse.h"
|
||||
#include "parse.h"
|
||||
#include "util.h"
|
||||
#include "format.h"
|
||||
#include "ioctl.h"
|
||||
#include "cmd.h"
|
||||
|
||||
struct get_allocated_inos_args {
|
||||
char *path;
|
||||
u64 ino;
|
||||
bool have_ino;
|
||||
bool single;
|
||||
};
|
||||
|
||||
static int do_get_allocated_inos(struct get_allocated_inos_args *args)
|
||||
{
|
||||
struct scoutfs_ioctl_get_allocated_inos gai;
|
||||
u64 *inos = NULL;
|
||||
int fd = -1;
|
||||
u64 bytes;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (args->single)
|
||||
bytes = sizeof(*inos);
|
||||
else
|
||||
bytes = SCOUTFS_LOCK_INODE_GROUP_NR * sizeof(*inos);
|
||||
|
||||
inos = malloc(bytes);
|
||||
if (!inos) {
|
||||
fprintf(stderr, "inode number array allocation failed\n");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd = get_path(args->path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
memset(&gai, 0, sizeof(gai));
|
||||
gai.start_ino = args->ino;
|
||||
gai.inos_ptr = (unsigned long)inos;
|
||||
gai.inos_bytes = bytes;
|
||||
|
||||
ret = ioctl(fd, SCOUTFS_IOC_GET_ALLOCATED_INOS, &gai);
|
||||
if (ret < 0) {
|
||||
ret = -errno;
|
||||
fprintf(stderr, "get_allocated_inos ioctl failed: "
|
||||
"%s (%d)\n", strerror(errno), errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (args->single && ret > 0 && inos[0] != args->ino)
|
||||
ret = 0;
|
||||
|
||||
for (i = 0; i < ret; i++)
|
||||
printf("%llu\n", inos[i]);
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
free(inos);
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
static int parse_opt(int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
struct get_allocated_inos_args *args = state->input;
|
||||
int ret;
|
||||
|
||||
switch (key) {
|
||||
case 'i':
|
||||
ret = parse_u64(arg, &args->ino);
|
||||
if (ret)
|
||||
return ret;
|
||||
args->have_ino = true;
|
||||
case 'p':
|
||||
args->path = strdup_or_error(state, arg);
|
||||
break;
|
||||
case 's':
|
||||
args->single = true;
|
||||
break;
|
||||
case ARGP_KEY_FINI:
|
||||
if (!args->have_ino)
|
||||
argp_error(state, "must provide --ino starting inode number option");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct argp_option options[] = {
|
||||
{ "ino", 'i', "NUMBER", 0, "Start from 64bit inode number (required)"},
|
||||
{ "path", 'p', "PATH", 0, "Path to ScoutFS filesystem"},
|
||||
{ "single", 's', NULL, 0, "Only print single specific inode number argument"},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static struct argp argp = {
|
||||
options,
|
||||
parse_opt,
|
||||
NULL,
|
||||
"Print allocated inode numbers from starting inode number"
|
||||
};
|
||||
|
||||
static int get_allocated_inos_cmd(int argc, char **argv)
|
||||
{
|
||||
|
||||
struct get_allocated_inos_args get_allocated_inos_args = {NULL};
|
||||
int ret;
|
||||
|
||||
ret = argp_parse(&argp, argc, argv, 0, NULL, &get_allocated_inos_args);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return do_get_allocated_inos(&get_allocated_inos_args);
|
||||
}
|
||||
|
||||
static void __attribute__((constructor)) get_allocated_inos_ctor(void)
|
||||
{
|
||||
cmd_register_argp("get-allocated-inos", &argp, GROUP_DEBUG, get_allocated_inos_cmd);
|
||||
}
|
||||
@@ -278,6 +278,8 @@ static int print_log_trees_item(struct scoutfs_key *key, u64 seq, u8 flags, void
|
||||
" data_freed: "ALCROOT_F"\n"
|
||||
" srch_file: "SRF_FMT"\n"
|
||||
" inode_count_delta: %lld\n"
|
||||
" get_trans_seq: %lld\n"
|
||||
" commit_trans_seq: %lld\n"
|
||||
" max_item_seq: %llu\n"
|
||||
" finalize_seq: %llu\n"
|
||||
" rid: %016llx\n"
|
||||
@@ -296,6 +298,8 @@ static int print_log_trees_item(struct scoutfs_key *key, u64 seq, u8 flags, void
|
||||
ALCROOT_A(<->data_freed),
|
||||
SRF_A(<->srch_file),
|
||||
le64_to_cpu(lt->inode_count_delta),
|
||||
le64_to_cpu(lt->get_trans_seq),
|
||||
le64_to_cpu(lt->commit_trans_seq),
|
||||
le64_to_cpu(lt->max_item_seq),
|
||||
le64_to_cpu(lt->finalize_seq),
|
||||
le64_to_cpu(lt->rid),
|
||||
|
||||
Reference in New Issue
Block a user