unfuck nfs patch

This commit is contained in:
Charlotte 🦝 Delenk 2023-06-16 21:08:10 +01:00
parent 14137b2552
commit b070b5da8d
Signed by: darkkirb
GPG key ID: AB2BD8DAF2E37122
2 changed files with 195 additions and 0 deletions

View file

@ -46,6 +46,10 @@ in
hash = "sha256-SpKDm4PXR6qs7kX5SGVpFF/EPBijMhX1NsFUHrlCynM=";
};
}
{
name = "nfs-unfuck.patch";
patch = ./nfs-unfuck.patch;
}
];
structuredExtraConfig = with lib.kernel; {

191
linux/vf2/nfs-unfuck.patch Normal file
View file

@ -0,0 +1,191 @@
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index d3665390c4cb..7a782a1717d3 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -55,6 +55,7 @@
#include <linux/utsname.h>
#include <linux/freezer.h>
#include <linux/iversion.h>
+#include <linux/posix_acl_xattr.h>
#include "nfs4_fs.h"
#include "delegation.h"
@@ -327,7 +328,7 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
memset(&readdir->verifier, 0, sizeof(readdir->verifier));
if (cookie == 2)
return;
-
+
/*
* NFSv4 servers do not return entries for '.' and '..'
* Therefore, we fake these entries here. We let '.'
@@ -336,7 +337,7 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
* instead of 1 or 2.
*/
start = p = kmap_atomic(*readdir->pages);
-
+
if (cookie == 0) {
*p++ = xdr_one; /* next */
*p++ = xdr_zero; /* cookie, first word */
@@ -350,7 +351,7 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
*p++ = htonl(NF4DIR);
p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry)));
}
-
+
*p++ = xdr_one; /* next */
*p++ = xdr_zero; /* cookie, first word */
*p++ = xdr_two; /* cookie, second word */
@@ -2147,7 +2148,7 @@ static int nfs4_open_recover_helper(struct nfs4_opendata *opendata,
nfs4_init_opendata_res(opendata);
ret = _nfs4_recover_proc_open(opendata);
if (ret != 0)
- return ret;
+ return ret;
newstate = nfs4_opendata_to_nfs4_state(opendata);
if (IS_ERR(newstate))
return PTR_ERR(newstate);
@@ -3709,13 +3710,13 @@ static const struct rpc_call_ops nfs4_close_ops = {
.rpc_release = nfs4_free_closedata,
};
-/*
- * It is possible for data to be read/written from a mem-mapped file
+/*
+ * It is possible for data to be read/written from a mem-mapped file
* after the sys_close call (which hits the vfs layer as a flush).
- * This means that we can't safely call nfsv4 close on a file until
+ * This means that we can't safely call nfsv4 close on a file until
* the inode is cleared. This in turn means that we are not good
- * NFSv4 citizens - we do not indicate to the server to update the file's
- * share state even when we are done with one of the three share
+ * NFSv4 citizens - we do not indicate to the server to update the file's
+ * share state even when we are done with one of the three share
* stateid's in the inode.
*
* NOTE: Caller must be holding the sp->so_owner semaphore!
@@ -4335,7 +4336,7 @@ int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
return err;
}
-/*
+/*
* The file is not closed if it is opened due to the a request to change
* the size of the file. The open call will not be needed once the
* VFS layer lookup-intents are implemented.
@@ -4367,7 +4368,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
pnfs_commit_and_return_layout(inode);
nfs_fattr_init(fattr);
-
+
/* Deal with open(O_TRUNC) */
if (sattr->ia_valid & ATTR_OPEN)
sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME);
@@ -5024,7 +5025,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
data->arg.u.symlink.pages = &page;
data->arg.u.symlink.len = len;
data->arg.label = label;
-
+
status = nfs4_do_create(dir, dentry, data);
nfs4_free_createdata(data);
@@ -10623,6 +10624,78 @@ static void nfs4_disable_swap(struct inode *inode)
nfs4_schedule_state_manager(clp);
}
+static struct posix_acl *nfs4_get_acl(struct mnt_idmap *idmap,
+ struct dentry *dentry, int type) {int size;
+ const char *name;
+ char *value = NULL;
+ struct posix_acl *acl;
+ struct inode* inode = d_inode(dentry);
+
+ switch (type) {
+ case ACL_TYPE_ACCESS:
+ name = XATTR_USER_PREFIX XATTR_POSIX_ACL_ACCESS;
+ break;
+ case ACL_TYPE_DEFAULT:
+ name = XATTR_USER_PREFIX XATTR_POSIX_ACL_DEFAULT;
+ break;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+
+ size = nfs4_xattr_get_nfs4_user(NULL, dentry, inode, name, NULL, 0);
+ if (size > 0) {
+ value = kzalloc(size, GFP_KERNEL);
+ if (!value)
+ return ERR_PTR(-ENOMEM);
+ size = nfs4_xattr_get_nfs4_user(NULL, dentry, inode, name, value, size);
+ }
+ if (size > 0)
+ acl = posix_acl_from_xattr(&init_user_ns, value, size);
+ else if (size == -ENODATA || size == 0)
+ acl = NULL;
+ else
+ acl = ERR_PTR(size);
+ kfree(value);
+
+ return acl;
+}
+
+static int nfs4_set_acl(struct mnt_idmap *idmap,
+ struct dentry *dentry, struct posix_acl *acl,
+ int type)
+{
+ int rc = 0;
+ char * name = NULL;
+ void * value = NULL;
+ int size = 0;
+ struct inode* inode = d_inode(dentry);
+
+ switch (type) {
+ case ACL_TYPE_ACCESS:
+ name = XATTR_USER_PREFIX XATTR_POSIX_ACL_ACCESS;
+ break;
+ case ACL_TYPE_DEFAULT:
+ name = XATTR_USER_PREFIX XATTR_POSIX_ACL_DEFAULT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ size = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0);
+
+ value = kzalloc(size, GFP_KERNEL);
+
+ if(!value)
+ return -ENOMEM;
+
+ rc = nfs4_xattr_set_nfs4_user(NULL, idmap, dentry, inode, name, value, size, 0);
+
+ kfree(value);
+
+ return rc;
+}
+
+
static const struct inode_operations nfs4_dir_inode_operations = {
.create = nfs_create,
.lookup = nfs_lookup,
@@ -10638,6 +10711,8 @@ static const struct inode_operations nfs4_dir_inode_operations = {
.getattr = nfs_getattr,
.setattr = nfs_setattr,
.listxattr = nfs4_listxattr,
+ .get_acl = nfs4_get_acl,
+ .set_acl = nfs4_set_acl,
};
static const struct inode_operations nfs4_file_inode_operations = {
@@ -10645,6 +10720,8 @@ static const struct inode_operations nfs4_file_inode_operations = {
.getattr = nfs_getattr,
.setattr = nfs_setattr,
.listxattr = nfs4_listxattr,
+ .get_acl = nfs4_get_acl,
+ .set_acl = nfs4_set_acl,
};
const struct nfs_rpc_ops nfs_v4_clientops = {