forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge tag 'nfs-for-4.13-1' of git://git.linux-nfs.org/projects/anna/l…
…inux-nfs Pull NFS client updates from Anna Schumaker: "Stable bugfixes: - Fix -EACCESS on commit to DS handling - Fix initialization of nfs_page_array->npages - Only invalidate dentries that are actually invalid Features: - Enable NFSoRDMA transparent state migration - Add support for lookup-by-filehandle - Add support for nfs re-exporting Other bugfixes and cleanups: - Christoph cleaned up the way we declare NFS operations - Clean up various internal structures - Various cleanups to commits - Various improvements to error handling - Set the dt_type of . and .. entries in NFS v4 - Make slot allocation more reliable - Fix fscache stat printing - Fix uninitialized variable warnings - Fix potential list overrun in nfs_atomic_open() - Fix a race in NFSoRDMA RPC reply handler - Fix return size for nfs42_proc_copy() - Fix against MAC forgery timing attacks" * tag 'nfs-for-4.13-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (68 commits) NFS: Don't run wake_up_bit() when nobody is waiting... nfs: add export operations nfs4: add NFSv4 LOOKUPP handlers nfs: add a nfs_ilookup helper nfs: replace d_add with d_splice_alias in atomic_open sunrpc: use constant time memory comparison for mac NFSv4.2 fix size storage for nfs42_proc_copy xprtrdma: Fix documenting comments in frwr_ops.c xprtrdma: Replace PAGE_MASK with offset_in_page() xprtrdma: FMR does not need list_del_init() xprtrdma: Demote "connect" log messages NFSv4.1: Use seqid returned by EXCHANGE_ID after state migration NFSv4.1: Handle EXCHGID4_FLAG_CONFIRMED_R during NFSv4.1 migration xprtrdma: Don't defer MR recovery if ro_map fails xprtrdma: Fix FRWR invalidation error recovery xprtrdma: Fix client lock-up after application signal fires xprtrdma: Rename rpcrdma_req::rl_free xprtrdma: Pass only the list of registered MRs to ro_unmap_sync xprtrdma: Pre-mark remotely invalidated MRs xprtrdma: On invalidation failure, remove MWs from rl_registered ...
- Loading branch information
Showing
35 changed files
with
777 additions
and
289 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
/* | ||
* Copyright (c) 2015, Primary Data, Inc. All rights reserved. | ||
* | ||
* Tao Peng <[email protected]> | ||
*/ | ||
#include <linux/dcache.h> | ||
#include <linux/exportfs.h> | ||
#include <linux/nfs.h> | ||
#include <linux/nfs_fs.h> | ||
|
||
#include "internal.h" | ||
#include "nfstrace.h" | ||
|
||
#define NFSDBG_FACILITY NFSDBG_VFS | ||
|
||
enum { | ||
FILEID_HIGH_OFF = 0, /* inode fileid high */ | ||
FILEID_LOW_OFF, /* inode fileid low */ | ||
FILE_I_TYPE_OFF, /* inode type */ | ||
EMBED_FH_OFF /* embeded server fh */ | ||
}; | ||
|
||
|
||
static struct nfs_fh *nfs_exp_embedfh(__u32 *p) | ||
{ | ||
return (struct nfs_fh *)(p + EMBED_FH_OFF); | ||
} | ||
|
||
/* | ||
* Let's break subtree checking for now... otherwise we'll have to embed parent fh | ||
* but there might not be enough space. | ||
*/ | ||
static int | ||
nfs_encode_fh(struct inode *inode, __u32 *p, int *max_len, struct inode *parent) | ||
{ | ||
struct nfs_fh *server_fh = NFS_FH(inode); | ||
struct nfs_fh *clnt_fh = nfs_exp_embedfh(p); | ||
size_t fh_size = offsetof(struct nfs_fh, data) + server_fh->size; | ||
int len = EMBED_FH_OFF + XDR_QUADLEN(fh_size); | ||
|
||
dprintk("%s: max fh len %d inode %p parent %p", | ||
__func__, *max_len, inode, parent); | ||
|
||
if (*max_len < len || IS_AUTOMOUNT(inode)) { | ||
dprintk("%s: fh len %d too small, required %d\n", | ||
__func__, *max_len, len); | ||
*max_len = len; | ||
return FILEID_INVALID; | ||
} | ||
if (IS_AUTOMOUNT(inode)) { | ||
*max_len = FILEID_INVALID; | ||
goto out; | ||
} | ||
|
||
p[FILEID_HIGH_OFF] = NFS_FILEID(inode) >> 32; | ||
p[FILEID_LOW_OFF] = NFS_FILEID(inode); | ||
p[FILE_I_TYPE_OFF] = inode->i_mode & S_IFMT; | ||
p[len - 1] = 0; /* Padding */ | ||
nfs_copy_fh(clnt_fh, server_fh); | ||
*max_len = len; | ||
out: | ||
dprintk("%s: result fh fileid %llu mode %u size %d\n", | ||
__func__, NFS_FILEID(inode), inode->i_mode, *max_len); | ||
return *max_len; | ||
} | ||
|
||
static struct dentry * | ||
nfs_fh_to_dentry(struct super_block *sb, struct fid *fid, | ||
int fh_len, int fh_type) | ||
{ | ||
struct nfs4_label *label = NULL; | ||
struct nfs_fattr *fattr = NULL; | ||
struct nfs_fh *server_fh = nfs_exp_embedfh(fid->raw); | ||
size_t fh_size = offsetof(struct nfs_fh, data) + server_fh->size; | ||
const struct nfs_rpc_ops *rpc_ops; | ||
struct dentry *dentry; | ||
struct inode *inode; | ||
int len = EMBED_FH_OFF + XDR_QUADLEN(fh_size); | ||
u32 *p = fid->raw; | ||
int ret; | ||
|
||
/* NULL translates to ESTALE */ | ||
if (fh_len < len || fh_type != len) | ||
return NULL; | ||
|
||
fattr = nfs_alloc_fattr(); | ||
if (fattr == NULL) { | ||
dentry = ERR_PTR(-ENOMEM); | ||
goto out; | ||
} | ||
|
||
fattr->fileid = ((u64)p[FILEID_HIGH_OFF] << 32) + p[FILEID_LOW_OFF]; | ||
fattr->mode = p[FILE_I_TYPE_OFF]; | ||
fattr->valid |= NFS_ATTR_FATTR_FILEID | NFS_ATTR_FATTR_TYPE; | ||
|
||
dprintk("%s: fileid %llu mode %d\n", __func__, fattr->fileid, fattr->mode); | ||
|
||
inode = nfs_ilookup(sb, fattr, server_fh); | ||
if (inode) | ||
goto out_found; | ||
|
||
label = nfs4_label_alloc(NFS_SB(sb), GFP_KERNEL); | ||
if (IS_ERR(label)) { | ||
dentry = ERR_CAST(label); | ||
goto out_free_fattr; | ||
} | ||
|
||
rpc_ops = NFS_SB(sb)->nfs_client->rpc_ops; | ||
ret = rpc_ops->getattr(NFS_SB(sb), server_fh, fattr, label); | ||
if (ret) { | ||
dprintk("%s: getattr failed %d\n", __func__, ret); | ||
dentry = ERR_PTR(ret); | ||
goto out_free_label; | ||
} | ||
|
||
inode = nfs_fhget(sb, server_fh, fattr, label); | ||
|
||
out_found: | ||
dentry = d_obtain_alias(inode); | ||
|
||
out_free_label: | ||
nfs4_label_free(label); | ||
out_free_fattr: | ||
nfs_free_fattr(fattr); | ||
out: | ||
return dentry; | ||
} | ||
|
||
static struct dentry * | ||
nfs_get_parent(struct dentry *dentry) | ||
{ | ||
int ret; | ||
struct inode *inode = d_inode(dentry), *pinode; | ||
struct super_block *sb = inode->i_sb; | ||
struct nfs_server *server = NFS_SB(sb); | ||
struct nfs_fattr *fattr = NULL; | ||
struct nfs4_label *label = NULL; | ||
struct dentry *parent; | ||
struct nfs_rpc_ops const *ops = server->nfs_client->rpc_ops; | ||
struct nfs_fh fh; | ||
|
||
if (!ops->lookupp) | ||
return ERR_PTR(-EACCES); | ||
|
||
fattr = nfs_alloc_fattr(); | ||
if (fattr == NULL) { | ||
parent = ERR_PTR(-ENOMEM); | ||
goto out; | ||
} | ||
|
||
label = nfs4_label_alloc(server, GFP_KERNEL); | ||
if (IS_ERR(label)) { | ||
parent = ERR_CAST(label); | ||
goto out_free_fattr; | ||
} | ||
|
||
ret = ops->lookupp(inode, &fh, fattr, label); | ||
if (ret) { | ||
parent = ERR_PTR(ret); | ||
goto out_free_label; | ||
} | ||
|
||
pinode = nfs_fhget(sb, &fh, fattr, label); | ||
parent = d_obtain_alias(pinode); | ||
out_free_label: | ||
nfs4_label_free(label); | ||
out_free_fattr: | ||
nfs_free_fattr(fattr); | ||
out: | ||
return parent; | ||
} | ||
|
||
const struct export_operations nfs_export_ops = { | ||
.encode_fh = nfs_encode_fh, | ||
.fh_to_dentry = nfs_fh_to_dentry, | ||
.get_parent = nfs_get_parent, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.