From: Jorge Mora <jmora1300@gmail.com>
To: linux-nfs@vger.kernel.org
Cc: trond.myklebust@hammerspace.com, Anna.Schumaker@netapp.com
Subject: [PATCH v1 1/2] NFS: add IO_ADVISE operation
Date: Tue, 10 Jan 2023 11:46:40 -0700 [thread overview]
Message-ID: <20230110184641.13334-2-mora@netapp.com> (raw)
In-Reply-To: <20230110184641.13334-1-mora@netapp.com>
Adds support for using the NFS v4.2 operation IO_ADVISE to
send client I/O access pattern hints to the server.
There is a one-to-one correspondence between the advice
(POSIX_FADV_*) given in fadvise64() and the bitmap mask sent
to the server. Any other advice given results in just
calling generic_fadvise().
The bitmap mask given by the server reply is just ignored
since the fadvise64() returns 0 on success. If server
replies with more than one bitmap word, only the first word
is stored on the nfs42_io_advise_res struct and all other
words are ignored.
Signed-off-by: Jorge Mora <mora@netapp.com>
---
fs/nfs/nfs42.h | 1 +
fs/nfs/nfs42proc.c | 67 +++++++++++++++++++++++++++++++
fs/nfs/nfs42xdr.c | 84 +++++++++++++++++++++++++++++++++++++++
fs/nfs/nfs4file.c | 37 +++++++++++++++++
fs/nfs/nfs4proc.c | 1 +
fs/nfs/nfs4xdr.c | 1 +
include/linux/nfs4.h | 1 +
include/linux/nfs_fs_sb.h | 1 +
include/linux/nfs_xdr.h | 28 +++++++++++++
9 files changed, 221 insertions(+)
diff --git a/fs/nfs/nfs42.h b/fs/nfs/nfs42.h
index 0fe5aacbcfdf..c3e9fcd54c72 100644
--- a/fs/nfs/nfs42.h
+++ b/fs/nfs/nfs42.h
@@ -20,6 +20,7 @@ int nfs42_proc_allocate(struct file *, loff_t, loff_t);
ssize_t nfs42_proc_copy(struct file *, loff_t, struct file *, loff_t, size_t,
struct nl4_server *, nfs4_stateid *, bool);
int nfs42_proc_deallocate(struct file *, loff_t, loff_t);
+int nfs42_proc_io_advise(struct file *, loff_t, u64, u32);
loff_t nfs42_proc_llseek(struct file *, loff_t, int);
int nfs42_proc_layoutstats_generic(struct nfs_server *,
struct nfs42_layoutstat_data *);
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
index ecb428512fe1..af40f705386a 100644
--- a/fs/nfs/nfs42proc.c
+++ b/fs/nfs/nfs42proc.c
@@ -172,6 +172,73 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
return err;
}
+static loff_t _nfs42_proc_io_advise(struct file *filep,
+ struct nfs_lock_context *lock, loff_t offset,
+ u64 count, u32 hints)
+{
+ struct inode *inode = file_inode(filep);
+ struct nfs42_io_advise_args args = {
+ .fh = NFS_FH(inode),
+ .offset = offset,
+ .count = count,
+ .hints = hints,
+ };
+ struct nfs42_io_advise_res res;
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_IO_ADVISE],
+ .rpc_argp = &args,
+ .rpc_resp = &res,
+ };
+ struct nfs_server *server = NFS_SERVER(inode);
+ int status;
+
+ if (!nfs_server_capable(inode, NFS_CAP_IO_ADVISE))
+ return -ENOTSUPP;
+
+ status = nfs4_set_rw_stateid(&args.stateid, lock->open_context,
+ lock, FMODE_READ);
+ if (status) {
+ if (status == -EAGAIN)
+ status = -NFS4ERR_BAD_STATEID;
+ return status;
+ }
+
+ status = nfs4_call_sync(server->client, server, &msg,
+ &args.seq_args, &res.seq_res, 0);
+ if (status == -ENOTSUPP)
+ server->caps &= ~NFS_CAP_IO_ADVISE;
+ return status;
+}
+
+int nfs42_proc_io_advise(struct file *filep, loff_t offset, u64 count, u32 hints)
+{
+ struct nfs_server *server = NFS_SERVER(file_inode(filep));
+ struct nfs4_exception exception = { };
+ struct nfs_lock_context *lock;
+ loff_t err;
+
+ lock = nfs_get_lock_context(nfs_file_open_context(filep));
+ if (IS_ERR(lock))
+ return PTR_ERR(lock);
+
+ exception.inode = file_inode(filep);
+ exception.state = lock->open_context->state;
+
+ do {
+ err = _nfs42_proc_io_advise(filep, lock, offset, count, hints);
+ if (err >= 0)
+ break;
+ if (err == -ENOTSUPP) {
+ err = -EOPNOTSUPP;
+ break;
+ }
+ err = nfs4_handle_exception(server, err, &exception);
+ } while (exception.retry);
+
+ nfs_put_lock_context(lock);
+ return err;
+}
+
static int handle_async_copy(struct nfs42_copy_res *res,
struct nfs_server *dst_server,
struct nfs_server *src_server,
diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c
index d80ee88ca996..1e30729b0ed5 100644
--- a/fs/nfs/nfs42xdr.c
+++ b/fs/nfs/nfs42xdr.c
@@ -45,6 +45,14 @@
#define encode_deallocate_maxsz (op_encode_hdr_maxsz + \
encode_fallocate_maxsz)
#define decode_deallocate_maxsz (op_decode_hdr_maxsz)
+#define nfs42_io_advise_bitmap_maxsz 2 /* bitmap length and hints mask */
+#define encode_io_advise_maxsz (op_encode_hdr_maxsz + \
+ encode_stateid_maxsz + \
+ 2 /* offset */ + \
+ 2 /* count */ + \
+ nfs42_io_advise_bitmap_maxsz /* hints */)
+#define decode_io_advise_maxsz (op_decode_hdr_maxsz + \
+ nfs42_io_advise_bitmap_maxsz /* hints */)
#define encode_read_plus_maxsz (op_encode_hdr_maxsz + \
encode_stateid_maxsz + 3)
#define NFS42_READ_PLUS_DATA_SEGMENT_SIZE \
@@ -138,6 +146,14 @@
decode_putfh_maxsz + \
decode_deallocate_maxsz + \
decode_getattr_maxsz)
+#define NFS4_enc_io_advise_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
+ encode_putfh_maxsz + \
+ encode_io_advise_maxsz)
+#define NFS4_dec_io_advise_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
+ decode_putfh_maxsz + \
+ decode_io_advise_maxsz)
#define NFS4_enc_read_plus_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_putfh_maxsz + \
@@ -342,6 +358,17 @@ static void encode_deallocate(struct xdr_stream *xdr,
encode_fallocate(xdr, args);
}
+static void encode_io_advise(struct xdr_stream *xdr,
+ const struct nfs42_io_advise_args *args,
+ struct compound_hdr *hdr)
+{
+ encode_op_hdr(xdr, OP_IO_ADVISE, decode_io_advise_maxsz, hdr);
+ encode_nfs4_stateid(xdr, &args->stateid);
+ encode_uint64(xdr, args->offset);
+ encode_uint64(xdr, args->count);
+ xdr_encode_bitmap4(xdr, &args->hints, 1);
+}
+
static void encode_read_plus(struct xdr_stream *xdr,
const struct nfs_pgio_args *args,
struct compound_hdr *hdr)
@@ -764,6 +791,25 @@ static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
encode_nops(&hdr);
}
+/*
+ * Encode IO_ADVISE request
+ */
+static void nfs4_xdr_enc_io_advise(struct rpc_rqst *req,
+ struct xdr_stream *xdr,
+ const void *data)
+{
+ const struct nfs42_io_advise_args *args = data;
+ struct compound_hdr hdr = {
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
+ };
+
+ encode_compound_hdr(xdr, req, &hdr);
+ encode_sequence(xdr, &args->seq_args, &hdr);
+ encode_putfh(xdr, args->fh, &hdr);
+ encode_io_advise(xdr, args, &hdr);
+ encode_nops(&hdr);
+}
+
/*
* Encode READ_PLUS request
*/
@@ -1034,6 +1080,19 @@ static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *re
return decode_op_hdr(xdr, OP_DEALLOCATE);
}
+static int decode_io_advise(struct xdr_stream *xdr, struct nfs42_io_advise_res *res)
+{
+ int status;
+
+ status = decode_op_hdr(xdr, OP_IO_ADVISE);
+ if (status)
+ return status;
+
+ if (unlikely(decode_bitmap4(xdr, &res->hints, 1) < 0))
+ return -EIO;
+ return 0;
+}
+
struct read_plus_segment {
enum data_content4 type;
uint64_t offset;
@@ -1337,6 +1396,31 @@ static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
return status;
}
+/*
+ * Decode IO_ADVISE response
+ */
+static int nfs4_xdr_dec_io_advise(struct rpc_rqst *rqstp,
+ struct xdr_stream *xdr,
+ void *data)
+{
+ struct nfs42_io_advise_res *res = data;
+ struct compound_hdr hdr;
+ int status;
+
+ status = decode_compound_hdr(xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
+ status = decode_putfh(xdr);
+ if (status)
+ goto out;
+ status = decode_io_advise(xdr, res);
+out:
+ return status;
+}
+
/*
* Decode READ_PLUS request
*/
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index 2563ed8580f3..5f6e4b5f1559 100644
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -7,6 +7,7 @@
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/falloc.h>
+#include <linux/fadvise.h>
#include <linux/mount.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_ssc.h>
@@ -236,6 +237,41 @@ static long nfs42_fallocate(struct file *filep, int mode, loff_t offset, loff_t
return nfs42_proc_allocate(filep, offset, len);
}
+static int nfs42_file_fadvise(struct file *filep, loff_t start, loff_t len, int advice)
+{
+ int ret;
+ unsigned int hints = 0;
+
+ switch (advice) {
+ case POSIX_FADV_NORMAL:
+ hints = NFS_IO_ADVISE4_NORMAL;
+ break;
+ case POSIX_FADV_RANDOM:
+ hints = NFS_IO_ADVISE4_RANDOM;
+ break;
+ case POSIX_FADV_SEQUENTIAL:
+ hints = NFS_IO_ADVISE4_SEQUENTIAL;
+ break;
+ case POSIX_FADV_WILLNEED:
+ hints = NFS_IO_ADVISE4_WILLNEED;
+ break;
+ case POSIX_FADV_DONTNEED:
+ hints = NFS_IO_ADVISE4_DONTNEED;
+ break;
+ case POSIX_FADV_NOREUSE:
+ hints = NFS_IO_ADVISE4_NOREUSE;
+ break;
+ default:
+ goto out;
+ }
+
+ ret = nfs42_proc_io_advise(filep, start, len, hints);
+ if (ret < 0)
+ return ret;
+out:
+ return generic_fadvise(filep, start, len, advice);
+}
+
static loff_t nfs42_remap_file_range(struct file *src_file, loff_t src_off,
struct file *dst_file, loff_t dst_off, loff_t count,
unsigned int remap_flags)
@@ -462,6 +498,7 @@ const struct file_operations nfs4_file_operations = {
.copy_file_range = nfs4_copy_file_range,
.llseek = nfs4_file_llseek,
.fallocate = nfs42_fallocate,
+ .fadvise = nfs42_file_fadvise,
.remap_file_range = nfs42_remap_file_range,
#else
.llseek = nfs_file_llseek,
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 40d749f29ed3..89b21b94f948 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -10529,6 +10529,7 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
| NFS_CAP_OFFLOAD_CANCEL
| NFS_CAP_COPY_NOTIFY
| NFS_CAP_DEALLOCATE
+ | NFS_CAP_IO_ADVISE
| NFS_CAP_SEEK
| NFS_CAP_LAYOUTSTATS
| NFS_CAP_CLONE
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index deec76cf5afe..962c5b023769 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -7698,6 +7698,7 @@ const struct rpc_procinfo nfs4_procedures[] = {
PROC42(SEEK, enc_seek, dec_seek),
PROC42(ALLOCATE, enc_allocate, dec_allocate),
PROC42(DEALLOCATE, enc_deallocate, dec_deallocate),
+ PROC42(IO_ADVISE, enc_io_advise, dec_io_advise),
PROC42(LAYOUTSTATS, enc_layoutstats, dec_layoutstats),
PROC42(CLONE, enc_clone, dec_clone),
PROC42(COPY, enc_copy, dec_copy),
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 8d04b6a5964c..a1d925b1f06b 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -557,6 +557,7 @@ enum {
NFSPROC4_CLNT_LISTXATTRS,
NFSPROC4_CLNT_REMOVEXATTR,
NFSPROC4_CLNT_READ_PLUS,
+ NFSPROC4_CLNT_IO_ADVISE,
};
/* nfs41 types */
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index ea2f7e6b1b0b..38eb0cd86979 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -270,6 +270,7 @@ struct nfs_server {
#define NFS_CAP_LGOPEN (1U << 5)
#define NFS_CAP_CASE_INSENSITIVE (1U << 6)
#define NFS_CAP_CASE_PRESERVING (1U << 7)
+#define NFS_CAP_IO_ADVISE (1U << 13)
#define NFS_CAP_POSIX_LOCK (1U << 14)
#define NFS_CAP_UIDGID_NOMAP (1U << 15)
#define NFS_CAP_STATEID_NFSV41 (1U << 16)
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index e86cf6642d21..3a52e5dc2fea 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -17,6 +17,18 @@
#define NFS_BITMASK_SZ 3
+#define NFS_IO_ADVISE4_NORMAL (1U << 0)
+#define NFS_IO_ADVISE4_SEQUENTIAL (1U << 1)
+#define NFS_IO_ADVISE4_SEQUENTIAL_BACKWARDS (1U << 2)
+#define NFS_IO_ADVISE4_RANDOM (1U << 3)
+#define NFS_IO_ADVISE4_WILLNEED (1U << 4)
+#define NFS_IO_ADVISE4_WILLNEED_OPPORTUNISTIC (1U << 5)
+#define NFS_IO_ADVISE4_DONTNEED (1U << 6)
+#define NFS_IO_ADVISE4_NOREUSE (1U << 7)
+#define NFS_IO_ADVISE4_READ (1U << 8)
+#define NFS_IO_ADVISE4_WRITE (1U << 9)
+#define NFS_IO_ADVISE4_INIT_PROXIMITY (1U << 10)
+
struct nfs4_string {
unsigned int len;
char *data;
@@ -1449,6 +1461,22 @@ struct nfs42_falloc_res {
const struct nfs_server *falloc_server;
};
+struct nfs42_io_advise_args {
+ struct nfs4_sequence_args seq_args;
+
+ struct nfs_fh *fh;
+ nfs4_stateid stateid;
+ loff_t offset;
+ u64 count;
+ u32 hints;
+};
+
+struct nfs42_io_advise_res {
+ struct nfs4_sequence_res seq_res;
+
+ u32 hints;
+};
+
struct nfs42_copy_args {
struct nfs4_sequence_args seq_args;
--
2.31.1
next prev parent reply other threads:[~2023-01-10 18:53 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-01-10 18:46 [PATCH v1 0/2] add support for IO_ADVISE Jorge Mora
2023-01-10 18:46 ` Jorge Mora [this message]
2023-01-10 20:33 ` [PATCH v1 1/2] NFS: add IO_ADVISE operation Trond Myklebust
2023-01-10 18:46 ` [PATCH v1 2/2] NFSv4.2 add tracepoint to IO_ADVISE Jorge Mora
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230110184641.13334-2-mora@netapp.com \
--to=jmora1300@gmail.com \
--cc=Anna.Schumaker@netapp.com \
--cc=linux-nfs@vger.kernel.org \
--cc=trond.myklebust@hammerspace.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox