9p: add 9P2000.L statfs operation
I made a V2 of this patch on top of my patches for VFS switches. The change was adding v9fs_statfs pointer to v9fs_super_ops_dotl instead of v9fs_super_ops. statfs - get file system statistics size[4] Tstatfs tag[2] fid[4] size[4] Rstatfs tag[2] type[4] bsize[4] blocks[8] bfree[8] bavail[8] files[8] ffree[8] fsid[8] namelen[4] The statfs message is used to request file system information returned by the statfs(2) system call, which is used by df(1) to report file system and disk space usage. Signed-off-by: Jim Garlick <garlick@llnl.gov> Signed-off-by: Sripathi Kodi <sripathik@in.ibm.com> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
This commit is contained in:
parent
9b6533c9b3
commit
bda8e77520
4 changed files with 98 additions and 1 deletions
|
@ -38,6 +38,7 @@
|
|||
#include <linux/idr.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/statfs.h>
|
||||
#include <net/9p/9p.h>
|
||||
#include <net/9p/client.h>
|
||||
|
||||
|
@ -214,6 +215,42 @@ v9fs_umount_begin(struct super_block *sb)
|
|||
v9fs_session_begin_cancel(v9ses);
|
||||
}
|
||||
|
||||
static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
{
|
||||
struct v9fs_session_info *v9ses;
|
||||
struct p9_fid *fid;
|
||||
struct p9_rstatfs rs;
|
||||
int res;
|
||||
|
||||
fid = v9fs_fid_lookup(dentry);
|
||||
if (IS_ERR(fid)) {
|
||||
res = PTR_ERR(fid);
|
||||
goto done;
|
||||
}
|
||||
|
||||
v9ses = v9fs_inode2v9ses(dentry->d_inode);
|
||||
if (v9fs_proto_dotl(v9ses)) {
|
||||
res = p9_client_statfs(fid, &rs);
|
||||
if (res == 0) {
|
||||
buf->f_type = rs.type;
|
||||
buf->f_bsize = rs.bsize;
|
||||
buf->f_blocks = rs.blocks;
|
||||
buf->f_bfree = rs.bfree;
|
||||
buf->f_bavail = rs.bavail;
|
||||
buf->f_files = rs.files;
|
||||
buf->f_ffree = rs.ffree;
|
||||
buf->f_fsid.val[0] = rs.fsid & 0xFFFFFFFFUL;
|
||||
buf->f_fsid.val[1] = (rs.fsid >> 32) & 0xFFFFFFFFUL;
|
||||
buf->f_namelen = rs.namelen;
|
||||
}
|
||||
if (res != -ENOSYS)
|
||||
goto done;
|
||||
}
|
||||
res = simple_statfs(dentry, buf);
|
||||
done:
|
||||
return res;
|
||||
}
|
||||
|
||||
static const struct super_operations v9fs_super_ops = {
|
||||
#ifdef CONFIG_9P_FSCACHE
|
||||
.alloc_inode = v9fs_alloc_inode,
|
||||
|
@ -230,7 +267,7 @@ static const struct super_operations v9fs_super_ops_dotl = {
|
|||
.alloc_inode = v9fs_alloc_inode,
|
||||
.destroy_inode = v9fs_destroy_inode,
|
||||
#endif
|
||||
.statfs = simple_statfs,
|
||||
.statfs = v9fs_statfs,
|
||||
.clear_inode = v9fs_clear_inode,
|
||||
.show_options = generic_show_options,
|
||||
.umount_begin = v9fs_umount_begin,
|
||||
|
|
|
@ -86,6 +86,8 @@ do { \
|
|||
|
||||
/**
|
||||
* enum p9_msg_t - 9P message types
|
||||
* @P9_TSTATFS: file system status request
|
||||
* @P9_RSTATFS: file system status response
|
||||
* @P9_TVERSION: version handshake request
|
||||
* @P9_RVERSION: version handshake response
|
||||
* @P9_TAUTH: request to establish authentication channel
|
||||
|
@ -125,6 +127,8 @@ do { \
|
|||
*/
|
||||
|
||||
enum p9_msg_t {
|
||||
P9_TSTATFS = 8,
|
||||
P9_RSTATFS,
|
||||
P9_TVERSION = 100,
|
||||
P9_RVERSION,
|
||||
P9_TAUTH = 102,
|
||||
|
@ -350,6 +354,22 @@ struct p9_wstat {
|
|||
};
|
||||
|
||||
/* Structures for Protocol Operations */
|
||||
struct p9_tstatfs {
|
||||
u32 fid;
|
||||
};
|
||||
|
||||
struct p9_rstatfs {
|
||||
u32 type;
|
||||
u32 bsize;
|
||||
u64 blocks;
|
||||
u64 bfree;
|
||||
u64 bavail;
|
||||
u64 files;
|
||||
u64 ffree;
|
||||
u64 fsid;
|
||||
u32 namelen;
|
||||
};
|
||||
|
||||
struct p9_tversion {
|
||||
u32 msize;
|
||||
struct p9_str version;
|
||||
|
|
|
@ -195,6 +195,7 @@ struct p9_fid {
|
|||
struct list_head dlist; /* list of all fids attached to a dentry */
|
||||
};
|
||||
|
||||
int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb);
|
||||
int p9_client_version(struct p9_client *);
|
||||
struct p9_client *p9_client_create(const char *dev_name, char *options);
|
||||
void p9_client_destroy(struct p9_client *clnt);
|
||||
|
|
|
@ -1365,3 +1365,42 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
|
|||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(p9_client_wstat);
|
||||
|
||||
int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb)
|
||||
{
|
||||
int err;
|
||||
struct p9_req_t *req;
|
||||
struct p9_client *clnt;
|
||||
|
||||
err = 0;
|
||||
clnt = fid->clnt;
|
||||
|
||||
P9_DPRINTK(P9_DEBUG_9P, ">>> TSTATFS fid %d\n", fid->fid);
|
||||
|
||||
req = p9_client_rpc(clnt, P9_TSTATFS, "d", fid->fid);
|
||||
if (IS_ERR(req)) {
|
||||
err = PTR_ERR(req);
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = p9pdu_readf(req->rc, clnt->proto_version, "ddqqqqqqd", &sb->type,
|
||||
&sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail,
|
||||
&sb->files, &sb->ffree, &sb->fsid, &sb->namelen);
|
||||
if (err) {
|
||||
p9pdu_dump(1, req->rc);
|
||||
p9_free_req(clnt, req);
|
||||
goto error;
|
||||
}
|
||||
|
||||
P9_DPRINTK(P9_DEBUG_9P, "<<< RSTATFS fid %d type 0x%lx bsize %ld "
|
||||
"blocks %llu bfree %llu bavail %llu files %llu ffree %llu "
|
||||
"fsid %llu namelen %ld\n",
|
||||
fid->fid, (long unsigned int)sb->type, (long int)sb->bsize,
|
||||
sb->blocks, sb->bfree, sb->bavail, sb->files, sb->ffree,
|
||||
sb->fsid, (long int)sb->namelen);
|
||||
|
||||
p9_free_req(clnt, req);
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(p9_client_statfs);
|
||||
|
|
Loading…
Reference in a new issue