diff --git a/linux/vf2/default.nix b/linux/vf2/default.nix index 979b795..3649d0c 100644 --- a/linux/vf2/default.nix +++ b/linux/vf2/default.nix @@ -46,6 +46,10 @@ in hash = "sha256-SpKDm4PXR6qs7kX5SGVpFF/EPBijMhX1NsFUHrlCynM="; }; } + { + name = "nfs-unfuck.patch"; + patch = ./nfs-unfuck.patch; + } ]; structuredExtraConfig = with lib.kernel; { diff --git a/linux/vf2/nfs-unfuck.patch b/linux/vf2/nfs-unfuck.patch new file mode 100644 index 0000000..3a53fa6 --- /dev/null +++ b/linux/vf2/nfs-unfuck.patch @@ -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 + #include + #include ++#include + + #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 = {