Skip to contentSkip to conversation

NFSv4.2: handle NFS-specific llseek errors

PATCH In review J. Bruce Fields 2 participants 3 messages Jul 23, 2015

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 NFSv4.2: handle NFS-specific llseek errors

From: "J. Bruce Fields" <[email protected]>

Handle NFS-specific llseek errors instead of letting them leak out to userspace.

---
 fs/nfs/nfs42proc.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

I don't actually have a test case for this, but it looks right....

fs/nfs/nfs42proc.c +18 -1
index f486b80f927a..2fec410bc50f 100644
@@ -135,7 +135,7 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
 	return err;
 }
 
-loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
+loff_t _nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
 {
 	struct inode *inode = file_inode(filep);
 	struct nfs42_seek_args args = {
@@ -171,6 +171,23 @@ loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
 	return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes);
 }
 
+loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
+{
+	struct nfs_server *server = NFS_SERVER(file_inode(filep));
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = _nfs42_proc_llseek(filep, offset, whence);
+		if (err == -ENOTSUPP)
+			return -EOPNOTSUPP;
+		err = nfs4_handle_exception(server, err, &exception);
+	} while (exception.retry);
+
+	return err;
+}
+
+
 static void
 nfs42_layoutstat_prepare(struct rpc_task *task, void *calldata)
 {
Signature · 1 line
2.4.3
#1 lore raw

Hi Bruce,

Quoted 27 lines · J. Bruce Fields

From: "J. Bruce Fields" <[email protected]>

Handle NFS-specific llseek errors instead of letting them leak out to userspace.

---
 fs/nfs/nfs42proc.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

I don't actually have a test case for this, but it looks right....

fs/nfs/nfs42proc.c +1 -1
index f486b80f927a..2fec410bc50f 100644
@@ -135,7 +135,7 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
 	return err;
 }
 
-loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
+loff_t _nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
 {
 	struct inode *inode = file_inode(filep);
 	struct nfs42_seek_args args = {

fs/nfs/nfs42proc.c loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) · line 178

Quoted 8 lines
fs/nfs/nfs42proc.c +5 -0
@@ -171,6 +171,23 @@ loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
 	return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes);
 }
 
+loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
+{
+	struct nfs_server *server = NFS_SERVER(file_inode(filep));
+	struct nfs4_exception exception = { };
+	int err;

Can you move the nfs_server_capable() check to before the do {} while loop? I think it's cleaner if we check for support before ever trying to call _nfs42_proc_llseek().

fs/nfs/nfs42proc.c loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) · line 183

Quoted 5 lines
fs/nfs/nfs42proc.c +5 -0
+
+	do {
+		err = _nfs42_proc_llseek(filep, offset, whence);
+		if (err == -ENOTSUPP)
+			return -EOPNOTSUPP;

With the change to check support moved to this function, we should also unset NFS_CAP_SEEK if we see -ENOTSUPP here. I think you'll also need to change nfs4_file_llseek() (in nfs4file.c) to check for -EOPNOTSUPP instead of -ENOTSUPP.

Thanks,
Anna

Quoted 11 lines
fs/nfs/nfs42proc.c +7 -0
+		err = nfs4_handle_exception(server, err, &exception);
+	} while (exception.retry);
+
+	return err;
+}
+
+
 static void
 nfs42_layoutstat_prepare(struct rpc_task *task, void *calldata)
 {
#2 lore raw
Quoted 33 lines · Anna Schumaker

Hi Bruce,

Quoted 30 lines · J. Bruce Fields

From: "J. Bruce Fields" <[email protected]>

Handle NFS-specific llseek errors instead of letting them leak out to userspace.

---
 fs/nfs/nfs42proc.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

I don't actually have a test case for this, but it looks right....

fs/nfs/nfs42proc.c +1 -1
index f486b80f927a..2fec410bc50f 100644
@@ -135,7 +135,7 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
 	return err;
 }
 
-loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
+loff_t _nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
 {
 	struct inode *inode = file_inode(filep);
 	struct nfs42_seek_args args = {
@@ -171,6 +171,23 @@ loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
 	return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes);
 }
 
Quoted 7 lines

fs/nfs/nfs42proc.c loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) · line 178

Quoted 5 lines
fs/nfs/nfs42proc.c +5 -0
+loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
+{
+	struct nfs_server *server = NFS_SERVER(file_inode(filep));
+	struct nfs4_exception exception = { };
+	int err;

Can you move the nfs_server_capable() check to before the do {} while loop? I think it's cleaner if we check for support before ever trying to call _nfs42_proc_llseek().

I believe the results of that check can change on subsequent iterations, due to a concurrent SEEK returning NOTSUPP.

The code would be correct either way, because the nfs_server_capable() check is really just an optimization--it should always be OK just to send the SEEK and then handle the NOTSUPP reply.

But accidentally sending an unnecessary rpc is much more expensive than checking a flag, so the code's probably best left as is.

(Also, this is the way it's done elsewhere in nfs{4,42}proc.c, so if there's some reason to change we'd want to do that everywhere.)

--b.