mirror of
https://github.com/versity/scoutfs.git
synced 2026-09-06 08:06:56 +00:00
scoutfs: add statfs network message
The ->statfs method was still using the super_block in the super_info that was read during mount. This will get progressively more out of date. We add a network message to ask the server for the current fields that impact statfs. This is always racy and the fields are mostly nonsense, but we try our best. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -681,6 +681,15 @@ int scoutfs_client_get_manifest_root(struct super_block *sb,
|
||||
NULL, 0, root, sizeof(struct scoutfs_btree_root));
|
||||
}
|
||||
|
||||
int scoutfs_client_statfs(struct super_block *sb,
|
||||
struct scoutfs_net_statfs *nstatfs)
|
||||
{
|
||||
struct client_info *client = SCOUTFS_SB(sb)->client_info;
|
||||
|
||||
return client_request(client, SCOUTFS_NET_STATFS, NULL, 0, nstatfs,
|
||||
sizeof(struct scoutfs_net_statfs));
|
||||
}
|
||||
|
||||
int scoutfs_client_setup(struct super_block *sb)
|
||||
{
|
||||
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
|
||||
|
||||
@@ -10,6 +10,8 @@ int scoutfs_client_advance_seq(struct super_block *sb, u64 *seq);
|
||||
int scoutfs_client_get_last_seq(struct super_block *sb, u64 *seq);
|
||||
int scoutfs_client_get_manifest_root(struct super_block *sb,
|
||||
struct scoutfs_btree_root *root);
|
||||
int scoutfs_client_statfs(struct super_block *sb,
|
||||
struct scoutfs_net_statfs *nstatfs);
|
||||
|
||||
int scoutfs_client_setup(struct super_block *sb);
|
||||
void scoutfs_client_destroy(struct super_block *sb);
|
||||
|
||||
@@ -571,6 +571,13 @@ struct scoutfs_net_segnos {
|
||||
__le64 segnos[0];
|
||||
} __packed;
|
||||
|
||||
struct scoutfs_net_statfs {
|
||||
__le64 total_segs; /* total segments in device */
|
||||
__le64 next_ino; /* next unused inode number */
|
||||
__le64 bfree; /* total free small blocks */
|
||||
__u8 uuid[SCOUTFS_UUID_BYTES]; /* logical volume uuid */
|
||||
} __packed;
|
||||
|
||||
/* XXX eventually we'll have net compaction and will need agents to agree */
|
||||
|
||||
/* one upper segment and fanout lower segments */
|
||||
@@ -589,6 +596,7 @@ enum {
|
||||
SCOUTFS_NET_ADVANCE_SEQ,
|
||||
SCOUTFS_NET_GET_LAST_SEQ,
|
||||
SCOUTFS_NET_GET_MANIFEST_ROOT,
|
||||
SCOUTFS_NET_STATFS,
|
||||
SCOUTFS_NET_UNKNOWN,
|
||||
};
|
||||
|
||||
|
||||
@@ -581,6 +581,39 @@ static int process_get_manifest_root(struct server_connection *conn, u64 id,
|
||||
return send_reply(conn, id, type, ret, &root, sizeof(root));
|
||||
}
|
||||
|
||||
/*
|
||||
* Sample the super stats that the client wants for statfs by serializing
|
||||
* with each component.
|
||||
*/
|
||||
static int process_statfs(struct server_connection *conn, u64 id, u8 type,
|
||||
void *data, unsigned data_len)
|
||||
{
|
||||
struct server_info *server = conn->server;
|
||||
struct super_block *sb = server->sb;
|
||||
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
|
||||
struct scoutfs_super_block *super = &sbi->super;
|
||||
struct scoutfs_net_statfs nstatfs;
|
||||
int ret;
|
||||
|
||||
if (data_len == 0) {
|
||||
/* uuid and total_segs are constant, so far */
|
||||
memcpy(nstatfs.uuid, super->uuid, sizeof(nstatfs.uuid));
|
||||
nstatfs.total_segs = super->total_segs;
|
||||
|
||||
spin_lock(&sbi->next_ino_lock);
|
||||
nstatfs.next_ino = super->next_ino;
|
||||
spin_unlock(&sbi->next_ino_lock);
|
||||
|
||||
/* alloc locks the bfree calculation */
|
||||
nstatfs.bfree = cpu_to_le64(scoutfs_alloc_bfree(sb));
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return send_reply(conn, id, type, ret, &nstatfs, sizeof(nstatfs));
|
||||
}
|
||||
|
||||
/*
|
||||
* Eventually we're going to have messages that control compaction.
|
||||
* Each client mount would have long-lived work that sends requests
|
||||
@@ -692,6 +725,7 @@ static void scoutfs_server_process_func(struct work_struct *work)
|
||||
[SCOUTFS_NET_ADVANCE_SEQ] = process_advance_seq,
|
||||
[SCOUTFS_NET_GET_LAST_SEQ] = process_get_last_seq,
|
||||
[SCOUTFS_NET_GET_MANIFEST_ROOT] = process_get_manifest_root,
|
||||
[SCOUTFS_NET_STATFS] = process_statfs,
|
||||
};
|
||||
struct scoutfs_net_header *nh = &req->nh;
|
||||
process_func_t func;
|
||||
|
||||
+18
-8
@@ -44,6 +44,11 @@
|
||||
static struct kset *scoutfs_kset;
|
||||
|
||||
/*
|
||||
* Ask the server for the current statfs fields. The message is very
|
||||
* cheap so we're not worrying about spinning in statfs flooding the
|
||||
* server with requests. We can add a cache and stale results if that
|
||||
* becomes a problem.
|
||||
*
|
||||
* We fake the number of free inodes value by assuming that we can fill
|
||||
* free blocks with a certain number of inodes. We then the number of
|
||||
* current inodes to that free count to determine the total possible
|
||||
@@ -55,20 +60,25 @@ static struct kset *scoutfs_kset;
|
||||
static int scoutfs_statfs(struct dentry *dentry, struct kstatfs *kst)
|
||||
{
|
||||
struct super_block *sb = dentry->d_inode->i_sb;
|
||||
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
|
||||
struct scoutfs_super_block *super = &sbi->super;
|
||||
__le32 * __packed uuid = (void *)super->uuid;
|
||||
struct scoutfs_net_statfs nstatfs;
|
||||
__le32 * __packed uuid;
|
||||
int ret;
|
||||
|
||||
kst->f_bfree = scoutfs_alloc_bfree(sb);
|
||||
ret = scoutfs_client_statfs(sb, &nstatfs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
kst->f_bfree = le64_to_cpu(nstatfs.bfree);
|
||||
kst->f_type = SCOUTFS_SUPER_MAGIC;
|
||||
kst->f_bsize = SCOUTFS_BLOCK_SIZE;
|
||||
kst->f_blocks = le64_to_cpu(super->total_segs) * SCOUTFS_SEGMENT_BLOCKS;
|
||||
kst->f_blocks = le64_to_cpu(nstatfs.total_segs) *
|
||||
SCOUTFS_SEGMENT_BLOCKS;
|
||||
kst->f_bavail = kst->f_bfree;
|
||||
|
||||
kst->f_ffree = kst->f_bfree * 17;
|
||||
kst->f_files = kst->f_ffree + scoutfs_last_ino(sb);
|
||||
kst->f_ffree = kst->f_bfree * 16;
|
||||
kst->f_files = kst->f_ffree + le64_to_cpu(nstatfs.next_ino);
|
||||
|
||||
/* this fsid is constant.. the uuid is different */
|
||||
uuid = (void *)nstatfs.uuid;
|
||||
kst->f_fsid.val[0] = le32_to_cpu(uuid[0]) ^ le32_to_cpu(uuid[1]);
|
||||
kst->f_fsid.val[1] = le32_to_cpu(uuid[2]) ^ le32_to_cpu(uuid[3]);
|
||||
kst->f_namelen = SCOUTFS_NAME_LEN;
|
||||
|
||||
Reference in New Issue
Block a user