Merge tag 'nfs-for-5.17-1' of git://git.linux-nfs.org/projects/anna/linux-nfs

Pull NFS client updates from Anna Schumaker:
 "New Features:

   - Basic handling for case insensitive filesystems

   - Initial support for fs_locations and server trunking

  Bugfixes and Cleanups:

   - Cleanups to how the "struct cred *" is handled for the
     nfs_access_entry

   - Ensure the server has an up to date ctimes before hardlinking or
     renaming

   - Update 'blocks used' after writeback, fallocate, and clone

   - nfs_atomic_open() fixes

   - Improvements to sunrpc tracing

   - Various null check & indenting related cleanups

   - Some improvements to the sunrpc sysfs code:
      - Use default_groups in kobj_type
      - Fix some potential races and reference leaks

   - A few tracepoint cleanups in xprtrdma"

[ This should have gone in during the merge window, but didn't. The
  original pull request - sent during the merge window - had gotten
  marked as spam and discarded due missing DKIM headers in the email
  from Anna.   - Linus ]

* tag 'nfs-for-5.17-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (35 commits)
  SUNRPC: Don't dereference xprt->snd_task if it's a cookie
  xprtrdma: Remove definitions of RPCDBG_FACILITY
  xprtrdma: Remove final dprintk call sites from xprtrdma
  sunrpc: Fix potential race conditions in rpc_sysfs_xprt_state_change()
  net/sunrpc: fix reference count leaks in rpc_sysfs_xprt_state_change
  NFSv4.1 test and add 4.1 trunking transport
  SUNRPC allow for unspecified transport time in rpc_clnt_add_xprt
  NFSv4 handle port presence in fs_location server string
  NFSv4 expose nfs_parse_server_name function
  NFSv4.1 query for fs_location attr on a new file system
  NFSv4 store server support for fs_location attribute
  NFSv4 remove zero number of fs_locations entries error check
  NFSv4: nfs_atomic_open() can race when looking up a non-regular file
  NFSv4: Handle case where the lookup of a directory fails
  NFSv42: Fallocate and clone should also request 'blocks used'
  NFSv4: Allow writebacks to request 'blocks used'
  SUNRPC: use default_groups in kobj_type
  NFS: use default_groups in kobj_type
  NFS: Fix the verifier for case sensitive filesystem in nfs_atomic_open()
  NFS: Add a helper to remove case-insensitive aliases
  ...
This commit is contained in:
Linus Torvalds
2022-01-25 20:16:03 +02:00
30 changed files with 474 additions and 207 deletions

View File

@@ -170,7 +170,7 @@ struct cb_devicenotifyitem {
}; };
struct cb_devicenotifyargs { struct cb_devicenotifyargs {
int ndevs; uint32_t ndevs;
struct cb_devicenotifyitem *devs; struct cb_devicenotifyitem *devs;
}; };

View File

@@ -358,7 +358,7 @@ __be32 nfs4_callback_devicenotify(void *argp, void *resp,
struct cb_process_state *cps) struct cb_process_state *cps)
{ {
struct cb_devicenotifyargs *args = argp; struct cb_devicenotifyargs *args = argp;
int i; uint32_t i;
__be32 res = 0; __be32 res = 0;
struct nfs_client *clp = cps->clp; struct nfs_client *clp = cps->clp;
struct nfs_server *server = NULL; struct nfs_server *server = NULL;

View File

@@ -258,11 +258,9 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
void *argp) void *argp)
{ {
struct cb_devicenotifyargs *args = argp; struct cb_devicenotifyargs *args = argp;
uint32_t tmp, n, i;
__be32 *p; __be32 *p;
__be32 status = 0; __be32 status = 0;
u32 tmp;
int n, i;
args->ndevs = 0;
/* Num of device notifications */ /* Num of device notifications */
p = xdr_inline_decode(xdr, sizeof(uint32_t)); p = xdr_inline_decode(xdr, sizeof(uint32_t));
@@ -271,7 +269,7 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
goto out; goto out;
} }
n = ntohl(*p++); n = ntohl(*p++);
if (n <= 0) if (n == 0)
goto out; goto out;
if (n > ULONG_MAX / sizeof(*args->devs)) { if (n > ULONG_MAX / sizeof(*args->devs)) {
status = htonl(NFS4ERR_BADXDR); status = htonl(NFS4ERR_BADXDR);
@@ -330,19 +328,21 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
dev->cbd_immediate = 0; dev->cbd_immediate = 0;
} }
args->ndevs++;
dprintk("%s: type %d layout 0x%x immediate %d\n", dprintk("%s: type %d layout 0x%x immediate %d\n",
__func__, dev->cbd_notify_type, dev->cbd_layout_type, __func__, dev->cbd_notify_type, dev->cbd_layout_type,
dev->cbd_immediate); dev->cbd_immediate);
} }
args->ndevs = n;
dprintk("%s: ndevs %d\n", __func__, args->ndevs);
return 0;
err:
kfree(args->devs);
out: out:
args->devs = NULL;
args->ndevs = 0;
dprintk("%s: status %d ndevs %d\n", dprintk("%s: status %d ndevs %d\n",
__func__, ntohl(status), args->ndevs); __func__, ntohl(status), args->ndevs);
return status; return status;
err:
kfree(args->devs);
goto out;
} }
static __be32 decode_sessionid(struct xdr_stream *xdr, static __be32 decode_sessionid(struct xdr_stream *xdr,

View File

@@ -856,6 +856,13 @@ static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, str
server->namelen = pathinfo.max_namelen; server->namelen = pathinfo.max_namelen;
} }
if (clp->rpc_ops->discover_trunking != NULL &&
(server->caps & NFS_CAP_FS_LOCATIONS)) {
error = clp->rpc_ops->discover_trunking(server, mntfh);
if (error < 0)
return error;
}
return 0; return 0;
} }

View File

@@ -1325,6 +1325,14 @@ void nfs_clear_verifier_delegated(struct inode *inode)
EXPORT_SYMBOL_GPL(nfs_clear_verifier_delegated); EXPORT_SYMBOL_GPL(nfs_clear_verifier_delegated);
#endif /* IS_ENABLED(CONFIG_NFS_V4) */ #endif /* IS_ENABLED(CONFIG_NFS_V4) */
static int nfs_dentry_verify_change(struct inode *dir, struct dentry *dentry)
{
if (nfs_server_capable(dir, NFS_CAP_CASE_INSENSITIVE) &&
d_really_is_negative(dentry))
return dentry->d_time == inode_peek_iversion_raw(dir);
return nfs_verify_change_attribute(dir, dentry->d_time);
}
/* /*
* A check for whether or not the parent directory has changed. * A check for whether or not the parent directory has changed.
* In the case it has, we assume that the dentries are untrustworthy * In the case it has, we assume that the dentries are untrustworthy
@@ -1338,7 +1346,7 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry,
return 1; return 1;
if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONE) if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONE)
return 0; return 0;
if (!nfs_verify_change_attribute(dir, dentry->d_time)) if (!nfs_dentry_verify_change(dir, dentry))
return 0; return 0;
/* Revalidate nfsi->cache_change_attribute before we declare a match */ /* Revalidate nfsi->cache_change_attribute before we declare a match */
if (nfs_mapping_need_revalidate_inode(dir)) { if (nfs_mapping_need_revalidate_inode(dir)) {
@@ -1347,7 +1355,7 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry,
if (__nfs_revalidate_inode(NFS_SERVER(dir), dir) < 0) if (__nfs_revalidate_inode(NFS_SERVER(dir), dir) < 0)
return 0; return 0;
} }
if (!nfs_verify_change_attribute(dir, dentry->d_time)) if (!nfs_dentry_verify_change(dir, dentry))
return 0; return 0;
return 1; return 1;
} }
@@ -1437,6 +1445,9 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
return 0; return 0;
if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG) if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG)
return 1; return 1;
/* Case insensitive server? Revalidate negative dentries */
if (nfs_server_capable(dir, NFS_CAP_CASE_INSENSITIVE))
return 1;
return !nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU); return !nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU);
} }
@@ -1537,7 +1548,7 @@ out:
* If the lookup failed despite the dentry change attribute being * If the lookup failed despite the dentry change attribute being
* a match, then we should revalidate the directory cache. * a match, then we should revalidate the directory cache.
*/ */
if (!ret && nfs_verify_change_attribute(dir, dentry->d_time)) if (!ret && nfs_dentry_verify_change(dir, dentry))
nfs_mark_dir_for_revalidate(dir); nfs_mark_dir_for_revalidate(dir);
return nfs_lookup_revalidate_done(dir, dentry, inode, ret); return nfs_lookup_revalidate_done(dir, dentry, inode, ret);
} }
@@ -1776,8 +1787,11 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in
dir_verifier = nfs_save_change_attribute(dir); dir_verifier = nfs_save_change_attribute(dir);
trace_nfs_lookup_enter(dir, dentry, flags); trace_nfs_lookup_enter(dir, dentry, flags);
error = NFS_PROTO(dir)->lookup(dir, dentry, fhandle, fattr); error = NFS_PROTO(dir)->lookup(dir, dentry, fhandle, fattr);
if (error == -ENOENT) if (error == -ENOENT) {
if (nfs_server_capable(dir, NFS_CAP_CASE_INSENSITIVE))
dir_verifier = inode_peek_iversion_raw(dir);
goto no_entry; goto no_entry;
}
if (error < 0) { if (error < 0) {
res = ERR_PTR(error); res = ERR_PTR(error);
goto out; goto out;
@@ -1806,6 +1820,14 @@ out:
} }
EXPORT_SYMBOL_GPL(nfs_lookup); EXPORT_SYMBOL_GPL(nfs_lookup);
void nfs_d_prune_case_insensitive_aliases(struct inode *inode)
{
/* Case insensitive server? Revalidate dentries */
if (inode && nfs_server_capable(inode, NFS_CAP_CASE_INSENSITIVE))
d_prune_aliases(inode);
}
EXPORT_SYMBOL_GPL(nfs_d_prune_case_insensitive_aliases);
#if IS_ENABLED(CONFIG_NFS_V4) #if IS_ENABLED(CONFIG_NFS_V4)
static int nfs4_lookup_revalidate(struct dentry *, unsigned int); static int nfs4_lookup_revalidate(struct dentry *, unsigned int);
@@ -1867,6 +1889,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
struct iattr attr = { .ia_valid = ATTR_OPEN }; struct iattr attr = { .ia_valid = ATTR_OPEN };
struct inode *inode; struct inode *inode;
unsigned int lookup_flags = 0; unsigned int lookup_flags = 0;
unsigned long dir_verifier;
bool switched = false; bool switched = false;
int created = 0; int created = 0;
int err; int err;
@@ -1940,7 +1963,11 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
switch (err) { switch (err) {
case -ENOENT: case -ENOENT:
d_splice_alias(NULL, dentry); d_splice_alias(NULL, dentry);
nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); if (nfs_server_capable(dir, NFS_CAP_CASE_INSENSITIVE))
dir_verifier = inode_peek_iversion_raw(dir);
else
dir_verifier = nfs_save_change_attribute(dir);
nfs_set_verifier(dentry, dir_verifier);
break; break;
case -EISDIR: case -EISDIR:
case -ENOTDIR: case -ENOTDIR:
@@ -1968,6 +1995,24 @@ out:
no_open: no_open:
res = nfs_lookup(dir, dentry, lookup_flags); res = nfs_lookup(dir, dentry, lookup_flags);
if (!res) {
inode = d_inode(dentry);
if ((lookup_flags & LOOKUP_DIRECTORY) && inode &&
!S_ISDIR(inode->i_mode))
res = ERR_PTR(-ENOTDIR);
else if (inode && S_ISREG(inode->i_mode))
res = ERR_PTR(-EOPENSTALE);
} else if (!IS_ERR(res)) {
inode = d_inode(res);
if ((lookup_flags & LOOKUP_DIRECTORY) && inode &&
!S_ISDIR(inode->i_mode)) {
dput(res);
res = ERR_PTR(-ENOTDIR);
} else if (inode && S_ISREG(inode->i_mode)) {
dput(res);
res = ERR_PTR(-EOPENSTALE);
}
}
if (switched) { if (switched) {
d_lookup_done(dentry); d_lookup_done(dentry);
if (!res) if (!res)
@@ -2186,8 +2231,10 @@ static void nfs_dentry_remove_handle_error(struct inode *dir,
switch (error) { switch (error) {
case -ENOENT: case -ENOENT:
d_delete(dentry); d_delete(dentry);
fallthrough; nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
break;
case 0: case 0:
nfs_d_prune_case_insensitive_aliases(d_inode(dentry));
nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
} }
} }
@@ -2380,6 +2427,8 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
trace_nfs_link_enter(inode, dir, dentry); trace_nfs_link_enter(inode, dir, dentry);
d_drop(dentry); d_drop(dentry);
if (S_ISREG(inode->i_mode))
nfs_sync_inode(inode);
error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
if (error == 0) { if (error == 0) {
nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
@@ -2469,6 +2518,8 @@ int nfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
} }
} }
if (S_ISREG(old_inode->i_mode))
nfs_sync_inode(old_inode);
task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry, NULL); task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry, NULL);
if (IS_ERR(task)) { if (IS_ERR(task)) {
error = PTR_ERR(task); error = PTR_ERR(task);
@@ -2529,7 +2580,7 @@ MODULE_PARM_DESC(nfs_access_max_cachesize, "NFS access maximum total cache lengt
static void nfs_access_free_entry(struct nfs_access_entry *entry) static void nfs_access_free_entry(struct nfs_access_entry *entry)
{ {
put_cred(entry->cred); put_group_info(entry->group_info);
kfree_rcu(entry, rcu_head); kfree_rcu(entry, rcu_head);
smp_mb__before_atomic(); smp_mb__before_atomic();
atomic_long_dec(&nfs_access_nr_entries); atomic_long_dec(&nfs_access_nr_entries);
@@ -2655,6 +2706,43 @@ void nfs_access_zap_cache(struct inode *inode)
} }
EXPORT_SYMBOL_GPL(nfs_access_zap_cache); EXPORT_SYMBOL_GPL(nfs_access_zap_cache);
static int access_cmp(const struct cred *a, const struct nfs_access_entry *b)
{
struct group_info *ga, *gb;
int g;
if (uid_lt(a->fsuid, b->fsuid))
return -1;
if (uid_gt(a->fsuid, b->fsuid))
return 1;
if (gid_lt(a->fsgid, b->fsgid))
return -1;
if (gid_gt(a->fsgid, b->fsgid))
return 1;
ga = a->group_info;
gb = b->group_info;
if (ga == gb)
return 0;
if (ga == NULL)
return -1;
if (gb == NULL)
return 1;
if (ga->ngroups < gb->ngroups)
return -1;
if (ga->ngroups > gb->ngroups)
return 1;
for (g = 0; g < ga->ngroups; g++) {
if (gid_lt(ga->gid[g], gb->gid[g]))
return -1;
if (gid_gt(ga->gid[g], gb->gid[g]))
return 1;
}
return 0;
}
static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, const struct cred *cred) static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, const struct cred *cred)
{ {
struct rb_node *n = NFS_I(inode)->access_cache.rb_node; struct rb_node *n = NFS_I(inode)->access_cache.rb_node;
@@ -2662,7 +2750,7 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, co
while (n != NULL) { while (n != NULL) {
struct nfs_access_entry *entry = struct nfs_access_entry *entry =
rb_entry(n, struct nfs_access_entry, rb_node); rb_entry(n, struct nfs_access_entry, rb_node);
int cmp = cred_fscmp(cred, entry->cred); int cmp = access_cmp(cred, entry);
if (cmp < 0) if (cmp < 0)
n = n->rb_left; n = n->rb_left;
@@ -2674,7 +2762,7 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, co
return NULL; return NULL;
} }
static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *cred, struct nfs_access_entry *res, bool may_block) static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *cred, u32 *mask, bool may_block)
{ {
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_access_entry *cache; struct nfs_access_entry *cache;
@@ -2704,8 +2792,7 @@ static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
retry = false; retry = false;
} }
res->cred = cache->cred; *mask = cache->mask;
res->mask = cache->mask;
list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru); list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru);
err = 0; err = 0;
out: out:
@@ -2717,7 +2804,7 @@ out_zap:
return -ENOENT; return -ENOENT;
} }
static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cred, struct nfs_access_entry *res) static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cred, u32 *mask)
{ {
/* Only check the most recently returned cache entry, /* Only check the most recently returned cache entry,
* but do it without locking. * but do it without locking.
@@ -2733,35 +2820,36 @@ static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cre
lh = rcu_dereference(list_tail_rcu(&nfsi->access_cache_entry_lru)); lh = rcu_dereference(list_tail_rcu(&nfsi->access_cache_entry_lru));
cache = list_entry(lh, struct nfs_access_entry, lru); cache = list_entry(lh, struct nfs_access_entry, lru);
if (lh == &nfsi->access_cache_entry_lru || if (lh == &nfsi->access_cache_entry_lru ||
cred_fscmp(cred, cache->cred) != 0) access_cmp(cred, cache) != 0)
cache = NULL; cache = NULL;
if (cache == NULL) if (cache == NULL)
goto out; goto out;
if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS)) if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS))
goto out; goto out;
res->cred = cache->cred; *mask = cache->mask;
res->mask = cache->mask;
err = 0; err = 0;
out: out:
rcu_read_unlock(); rcu_read_unlock();
return err; return err;
} }
int nfs_access_get_cached(struct inode *inode, const struct cred *cred, struct int nfs_access_get_cached(struct inode *inode, const struct cred *cred,
nfs_access_entry *res, bool may_block) u32 *mask, bool may_block)
{ {
int status; int status;
status = nfs_access_get_cached_rcu(inode, cred, res); status = nfs_access_get_cached_rcu(inode, cred, mask);
if (status != 0) if (status != 0)
status = nfs_access_get_cached_locked(inode, cred, res, status = nfs_access_get_cached_locked(inode, cred, mask,
may_block); may_block);
return status; return status;
} }
EXPORT_SYMBOL_GPL(nfs_access_get_cached); EXPORT_SYMBOL_GPL(nfs_access_get_cached);
static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *set) static void nfs_access_add_rbtree(struct inode *inode,
struct nfs_access_entry *set,
const struct cred *cred)
{ {
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
struct rb_root *root_node = &nfsi->access_cache; struct rb_root *root_node = &nfsi->access_cache;
@@ -2774,7 +2862,7 @@ static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *
while (*p != NULL) { while (*p != NULL) {
parent = *p; parent = *p;
entry = rb_entry(parent, struct nfs_access_entry, rb_node); entry = rb_entry(parent, struct nfs_access_entry, rb_node);
cmp = cred_fscmp(set->cred, entry->cred); cmp = access_cmp(cred, entry);
if (cmp < 0) if (cmp < 0)
p = &parent->rb_left; p = &parent->rb_left;
@@ -2796,13 +2884,16 @@ found:
nfs_access_free_entry(entry); nfs_access_free_entry(entry);
} }
void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set,
const struct cred *cred)
{ {
struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL); struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL);
if (cache == NULL) if (cache == NULL)
return; return;
RB_CLEAR_NODE(&cache->rb_node); RB_CLEAR_NODE(&cache->rb_node);
cache->cred = get_cred(set->cred); cache->fsuid = cred->fsuid;
cache->fsgid = cred->fsgid;
cache->group_info = get_group_info(cred->group_info);
cache->mask = set->mask; cache->mask = set->mask;
/* The above field assignments must be visible /* The above field assignments must be visible
@@ -2810,7 +2901,7 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
* use rcu_assign_pointer, so just force the memory barrier. * use rcu_assign_pointer, so just force the memory barrier.
*/ */
smp_wmb(); smp_wmb();
nfs_access_add_rbtree(inode, cache); nfs_access_add_rbtree(inode, cache, cred);
/* Update accounting */ /* Update accounting */
smp_mb__before_atomic(); smp_mb__before_atomic();
@@ -2875,7 +2966,7 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask)
trace_nfs_access_enter(inode); trace_nfs_access_enter(inode);
status = nfs_access_get_cached(inode, cred, &cache, may_block); status = nfs_access_get_cached(inode, cred, &cache.mask, may_block);
if (status == 0) if (status == 0)
goto out_cached; goto out_cached;
@@ -2895,8 +2986,7 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask)
cache.mask |= NFS_ACCESS_DELETE | NFS_ACCESS_LOOKUP; cache.mask |= NFS_ACCESS_DELETE | NFS_ACCESS_LOOKUP;
else else
cache.mask |= NFS_ACCESS_EXECUTE; cache.mask |= NFS_ACCESS_EXECUTE;
cache.cred = cred; status = NFS_PROTO(inode)->access(inode, &cache, cred);
status = NFS_PROTO(inode)->access(inode, &cache);
if (status != 0) { if (status != 0) {
if (status == -ESTALE) { if (status == -ESTALE) {
if (!S_ISDIR(inode->i_mode)) if (!S_ISDIR(inode->i_mode))
@@ -2906,7 +2996,7 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask)
} }
goto out; goto out;
} }
nfs_access_add_cache(inode, &cache); nfs_access_add_cache(inode, &cache, cred);
out_cached: out_cached:
cache_mask = nfs_access_calc_mask(cache.mask, inode->i_mode); cache_mask = nfs_access_calc_mask(cache.mask, inode->i_mode);
if ((mask & ~cache_mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0) if ((mask & ~cache_mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0)

View File

@@ -51,7 +51,7 @@ struct nfs4_file_layout_dsaddr {
u32 stripe_count; u32 stripe_count;
u8 *stripe_indices; u8 *stripe_indices;
u32 ds_num; u32 ds_num;
struct nfs4_pnfs_ds *ds_list[1]; struct nfs4_pnfs_ds *ds_list[];
}; };
struct nfs4_filelayout_segment { struct nfs4_filelayout_segment {

View File

@@ -136,9 +136,7 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
goto out_err_free_stripe_indices; goto out_err_free_stripe_indices;
} }
dsaddr = kzalloc(sizeof(*dsaddr) + dsaddr = kzalloc(struct_size(dsaddr, ds_list, num), gfp_flags);
(sizeof(struct nfs4_pnfs_ds *) * (num - 1)),
gfp_flags);
if (!dsaddr) if (!dsaddr)
goto out_err_free_stripe_indices; goto out_err_free_stripe_indices;

View File

@@ -373,6 +373,7 @@ extern unsigned long nfs_access_cache_count(struct shrinker *shrink,
extern unsigned long nfs_access_cache_scan(struct shrinker *shrink, extern unsigned long nfs_access_cache_scan(struct shrinker *shrink,
struct shrink_control *sc); struct shrink_control *sc);
struct dentry *nfs_lookup(struct inode *, struct dentry *, unsigned int); struct dentry *nfs_lookup(struct inode *, struct dentry *, unsigned int);
void nfs_d_prune_case_insensitive_aliases(struct inode *inode);
int nfs_create(struct user_namespace *, struct inode *, struct dentry *, int nfs_create(struct user_namespace *, struct inode *, struct dentry *,
umode_t, bool); umode_t, bool);
int nfs_mkdir(struct user_namespace *, struct inode *, struct dentry *, int nfs_mkdir(struct user_namespace *, struct inode *, struct dentry *,

View File

@@ -220,7 +220,8 @@ static int nfs3_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle,
task_flags); task_flags);
} }
static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry,
const struct cred *cred)
{ {
struct nfs3_accessargs arg = { struct nfs3_accessargs arg = {
.fh = NFS_FH(inode), .fh = NFS_FH(inode),
@@ -231,7 +232,7 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
.rpc_proc = &nfs3_procedures[NFS3PROC_ACCESS], .rpc_proc = &nfs3_procedures[NFS3PROC_ACCESS],
.rpc_argp = &arg, .rpc_argp = &arg,
.rpc_resp = &res, .rpc_resp = &res,
.rpc_cred = entry->cred, .rpc_cred = cred,
}; };
int status = -ENOMEM; int status = -ENOMEM;

View File

@@ -46,7 +46,7 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
{ {
struct inode *inode = file_inode(filep); struct inode *inode = file_inode(filep);
struct nfs_server *server = NFS_SERVER(inode); struct nfs_server *server = NFS_SERVER(inode);
u32 bitmask[3]; u32 bitmask[NFS_BITMASK_SZ];
struct nfs42_falloc_args args = { struct nfs42_falloc_args args = {
.falloc_fh = NFS_FH(inode), .falloc_fh = NFS_FH(inode),
.falloc_offset = offset, .falloc_offset = offset,
@@ -69,9 +69,8 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
return status; return status;
} }
memcpy(bitmask, server->cache_consistency_bitmask, sizeof(bitmask)); nfs4_bitmask_set(bitmask, server->cache_consistency_bitmask, inode,
if (server->attr_bitmask[1] & FATTR4_WORD1_SPACE_USED) NFS_INO_INVALID_BLOCKS);
bitmask[1] |= FATTR4_WORD1_SPACE_USED;
res.falloc_fattr = nfs_alloc_fattr(); res.falloc_fattr = nfs_alloc_fattr();
if (!res.falloc_fattr) if (!res.falloc_fattr)
@@ -1044,13 +1043,14 @@ static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f,
struct inode *src_inode = file_inode(src_f); struct inode *src_inode = file_inode(src_f);
struct inode *dst_inode = file_inode(dst_f); struct inode *dst_inode = file_inode(dst_f);
struct nfs_server *server = NFS_SERVER(dst_inode); struct nfs_server *server = NFS_SERVER(dst_inode);
__u32 dst_bitmask[NFS_BITMASK_SZ];
struct nfs42_clone_args args = { struct nfs42_clone_args args = {
.src_fh = NFS_FH(src_inode), .src_fh = NFS_FH(src_inode),
.dst_fh = NFS_FH(dst_inode), .dst_fh = NFS_FH(dst_inode),
.src_offset = src_offset, .src_offset = src_offset,
.dst_offset = dst_offset, .dst_offset = dst_offset,
.count = count, .count = count,
.dst_bitmask = server->cache_consistency_bitmask, .dst_bitmask = dst_bitmask,
}; };
struct nfs42_clone_res res = { struct nfs42_clone_res res = {
.server = server, .server = server,
@@ -1079,6 +1079,9 @@ static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f,
if (!res.dst_fattr) if (!res.dst_fattr)
return -ENOMEM; return -ENOMEM;
nfs4_bitmask_set(dst_bitmask, server->cache_consistency_bitmask,
dst_inode, NFS_INO_INVALID_BLOCKS);
status = nfs4_call_sync(server->client, server, msg, status = nfs4_call_sync(server->client, server, msg,
&args.seq_args, &res.seq_res, 0); &args.seq_args, &res.seq_res, 0);
trace_nfs4_clone(src_inode, dst_inode, &args, status); trace_nfs4_clone(src_inode, dst_inode, &args, status);

View File

@@ -260,8 +260,8 @@ struct nfs4_state_maintenance_ops {
}; };
struct nfs4_mig_recovery_ops { struct nfs4_mig_recovery_ops {
int (*get_locations)(struct inode *, struct nfs4_fs_locations *, int (*get_locations)(struct nfs_server *, struct nfs_fh *,
struct page *, const struct cred *); struct nfs4_fs_locations *, struct page *, const struct cred *);
int (*fsid_present)(struct inode *, const struct cred *); int (*fsid_present)(struct inode *, const struct cred *);
}; };
@@ -280,7 +280,8 @@ struct rpc_clnt *nfs4_negotiate_security(struct rpc_clnt *, struct inode *,
int nfs4_submount(struct fs_context *, struct nfs_server *); int nfs4_submount(struct fs_context *, struct nfs_server *);
int nfs4_replace_transport(struct nfs_server *server, int nfs4_replace_transport(struct nfs_server *server,
const struct nfs4_fs_locations *locations); const struct nfs4_fs_locations *locations);
size_t nfs_parse_server_name(char *string, size_t len, struct sockaddr *sa,
size_t salen, struct net *net, int port);
/* nfs4proc.c */ /* nfs4proc.c */
extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception *); extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception *);
extern int nfs4_async_handle_error(struct rpc_task *task, extern int nfs4_async_handle_error(struct rpc_task *task,
@@ -302,8 +303,9 @@ extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait);
extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
extern int nfs4_proc_fs_locations(struct rpc_clnt *, struct inode *, const struct qstr *, extern int nfs4_proc_fs_locations(struct rpc_clnt *, struct inode *, const struct qstr *,
struct nfs4_fs_locations *, struct page *); struct nfs4_fs_locations *, struct page *);
extern int nfs4_proc_get_locations(struct inode *, struct nfs4_fs_locations *, extern int nfs4_proc_get_locations(struct nfs_server *, struct nfs_fh *,
struct page *page, const struct cred *); struct nfs4_fs_locations *,
struct page *page, const struct cred *);
extern int nfs4_proc_fsid_present(struct inode *, const struct cred *); extern int nfs4_proc_fsid_present(struct inode *, const struct cred *);
extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *,
struct dentry *, struct dentry *,
@@ -315,6 +317,8 @@ extern int nfs4_set_rw_stateid(nfs4_stateid *stateid,
const struct nfs_open_context *ctx, const struct nfs_open_context *ctx,
const struct nfs_lock_context *l_ctx, const struct nfs_lock_context *l_ctx,
fmode_t fmode); fmode_t fmode);
extern void nfs4_bitmask_set(__u32 bitmask[], const __u32 src[],
struct inode *inode, unsigned long cache_validity);
extern int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, extern int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fattr *fattr, struct inode *inode); struct nfs_fattr *fattr, struct inode *inode);
extern int update_open_stateid(struct nfs4_state *state, extern int update_open_stateid(struct nfs4_state *state,

View File

@@ -1343,8 +1343,11 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname,
} }
nfs_put_client(clp); nfs_put_client(clp);
if (server->nfs_client->cl_hostname == NULL) if (server->nfs_client->cl_hostname == NULL) {
server->nfs_client->cl_hostname = kstrdup(hostname, GFP_KERNEL); server->nfs_client->cl_hostname = kstrdup(hostname, GFP_KERNEL);
if (server->nfs_client->cl_hostname == NULL)
return -ENOMEM;
}
nfs_server_insert_lists(server); nfs_server_insert_lists(server);
return nfs_probe_server(server, NFS_FH(d_inode(server->super->s_root))); return nfs_probe_server(server, NFS_FH(d_inode(server->super->s_root)));

View File

@@ -164,16 +164,21 @@ static int nfs4_validate_fspath(struct dentry *dentry,
return 0; return 0;
} }
static size_t nfs_parse_server_name(char *string, size_t len, size_t nfs_parse_server_name(char *string, size_t len, struct sockaddr *sa,
struct sockaddr *sa, size_t salen, struct net *net) size_t salen, struct net *net, int port)
{ {
ssize_t ret; ssize_t ret;
ret = rpc_pton(net, string, len, sa, salen); ret = rpc_pton(net, string, len, sa, salen);
if (ret == 0) { if (ret == 0) {
ret = nfs_dns_resolve_name(net, string, len, sa, salen); ret = rpc_uaddr2sockaddr(net, string, len, sa, salen);
if (ret < 0) if (ret == 0) {
ret = 0; ret = nfs_dns_resolve_name(net, string, len, sa, salen);
if (ret < 0)
ret = 0;
}
} else if (port) {
rpc_set_port(sa, port);
} }
return ret; return ret;
} }
@@ -328,7 +333,7 @@ static int try_location(struct fs_context *fc,
nfs_parse_server_name(buf->data, buf->len, nfs_parse_server_name(buf->data, buf->len,
&ctx->nfs_server.address, &ctx->nfs_server.address,
sizeof(ctx->nfs_server._address), sizeof(ctx->nfs_server._address),
fc->net_ns); fc->net_ns, 0);
if (ctx->nfs_server.addrlen == 0) if (ctx->nfs_server.addrlen == 0)
continue; continue;
@@ -496,7 +501,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server,
continue; continue;
salen = nfs_parse_server_name(buf->data, buf->len, salen = nfs_parse_server_name(buf->data, buf->len,
sap, addr_bufsize, net); sap, addr_bufsize, net, 0);
if (salen == 0) if (salen == 0)
continue; continue;
rpc_set_port(sap, NFS_PORT); rpc_set_port(sap, NFS_PORT);

View File

@@ -108,10 +108,6 @@ static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *,
static int nfs41_free_stateid(struct nfs_server *, const nfs4_stateid *, static int nfs41_free_stateid(struct nfs_server *, const nfs4_stateid *,
const struct cred *, bool); const struct cred *, bool);
#endif #endif
static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ],
const __u32 *src, struct inode *inode,
struct nfs_server *server,
struct nfs4_label *label);
#ifdef CONFIG_NFS_V4_SECURITY_LABEL #ifdef CONFIG_NFS_V4_SECURITY_LABEL
static inline struct nfs4_label * static inline struct nfs4_label *
@@ -2653,9 +2649,8 @@ static int nfs4_opendata_access(const struct cred *cred,
} else if ((fmode & FMODE_READ) && !opendata->file_created) } else if ((fmode & FMODE_READ) && !opendata->file_created)
mask = NFS4_ACCESS_READ; mask = NFS4_ACCESS_READ;
cache.cred = cred;
nfs_access_set_mask(&cache, opendata->o_res.access_result); nfs_access_set_mask(&cache, opendata->o_res.access_result);
nfs_access_add_cache(state->inode, &cache); nfs_access_add_cache(state->inode, &cache, cred);
flags = NFS4_ACCESS_READ | NFS4_ACCESS_EXECUTE | NFS4_ACCESS_LOOKUP; flags = NFS4_ACCESS_READ | NFS4_ACCESS_EXECUTE | NFS4_ACCESS_LOOKUP;
if ((mask & ~cache.mask & flags) == 0) if ((mask & ~cache.mask & flags) == 0)
@@ -3670,7 +3665,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
if (!nfs4_have_delegation(inode, FMODE_READ)) { if (!nfs4_have_delegation(inode, FMODE_READ)) {
nfs4_bitmask_set(calldata->arg.bitmask_store, nfs4_bitmask_set(calldata->arg.bitmask_store,
server->cache_consistency_bitmask, server->cache_consistency_bitmask,
inode, server, NULL); inode, 0);
calldata->arg.bitmask = calldata->arg.bitmask_store; calldata->arg.bitmask = calldata->arg.bitmask_store;
} else } else
calldata->arg.bitmask = NULL; calldata->arg.bitmask = NULL;
@@ -3841,7 +3836,9 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
FATTR4_WORD0_FH_EXPIRE_TYPE | FATTR4_WORD0_FH_EXPIRE_TYPE |
FATTR4_WORD0_LINK_SUPPORT | FATTR4_WORD0_LINK_SUPPORT |
FATTR4_WORD0_SYMLINK_SUPPORT | FATTR4_WORD0_SYMLINK_SUPPORT |
FATTR4_WORD0_ACLSUPPORT; FATTR4_WORD0_ACLSUPPORT |
FATTR4_WORD0_CASE_INSENSITIVE |
FATTR4_WORD0_CASE_PRESERVING;
if (minorversion) if (minorversion)
bitmask[2] = FATTR4_WORD2_SUPPATTR_EXCLCREAT; bitmask[2] = FATTR4_WORD2_SUPPATTR_EXCLCREAT;
@@ -3870,10 +3867,16 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
server->caps |= NFS_CAP_HARDLINKS; server->caps |= NFS_CAP_HARDLINKS;
if (res.has_symlinks != 0) if (res.has_symlinks != 0)
server->caps |= NFS_CAP_SYMLINKS; server->caps |= NFS_CAP_SYMLINKS;
if (res.case_insensitive)
server->caps |= NFS_CAP_CASE_INSENSITIVE;
if (res.case_preserving)
server->caps |= NFS_CAP_CASE_PRESERVING;
#ifdef CONFIG_NFS_V4_SECURITY_LABEL #ifdef CONFIG_NFS_V4_SECURITY_LABEL
if (res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL) if (res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL)
server->caps |= NFS_CAP_SECURITY_LABEL; server->caps |= NFS_CAP_SECURITY_LABEL;
#endif #endif
if (res.attr_bitmask[0] & FATTR4_WORD0_FS_LOCATIONS)
server->caps |= NFS_CAP_FS_LOCATIONS;
if (!(res.attr_bitmask[0] & FATTR4_WORD0_FILEID)) if (!(res.attr_bitmask[0] & FATTR4_WORD0_FILEID))
server->fattr_valid &= ~NFS_ATTR_FATTR_FILEID; server->fattr_valid &= ~NFS_ATTR_FATTR_FILEID;
if (!(res.attr_bitmask[1] & FATTR4_WORD1_MODE)) if (!(res.attr_bitmask[1] & FATTR4_WORD1_MODE))
@@ -3932,6 +3935,114 @@ int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
return err; return err;
} }
static void test_fs_location_for_trunking(struct nfs4_fs_location *location,
struct nfs_client *clp,
struct nfs_server *server)
{
int i;
for (i = 0; i < location->nservers; i++) {
struct nfs4_string *srv_loc = &location->servers[i];
struct sockaddr addr;
size_t addrlen;
struct xprt_create xprt_args = {
.ident = 0,
.net = clp->cl_net,
};
struct nfs4_add_xprt_data xprtdata = {
.clp = clp,
};
struct rpc_add_xprt_test rpcdata = {
.add_xprt_test = clp->cl_mvops->session_trunk,
.data = &xprtdata,
};
char *servername = NULL;
if (!srv_loc->len)
continue;
addrlen = nfs_parse_server_name(srv_loc->data, srv_loc->len,
&addr, sizeof(addr),
clp->cl_net, server->port);
if (!addrlen)
return;
xprt_args.dstaddr = &addr;
xprt_args.addrlen = addrlen;
servername = kmalloc(srv_loc->len + 1, GFP_KERNEL);
if (!servername)
return;
memcpy(servername, srv_loc->data, srv_loc->len);
servername[srv_loc->len] = '\0';
xprt_args.servername = servername;
xprtdata.cred = nfs4_get_clid_cred(clp);
rpc_clnt_add_xprt(clp->cl_rpcclient, &xprt_args,
rpc_clnt_setup_test_and_add_xprt,
&rpcdata);
if (xprtdata.cred)
put_cred(xprtdata.cred);
kfree(servername);
}
}
static int _nfs4_discover_trunking(struct nfs_server *server,
struct nfs_fh *fhandle)
{
struct nfs4_fs_locations *locations = NULL;
struct page *page;
const struct cred *cred;
struct nfs_client *clp = server->nfs_client;
const struct nfs4_state_maintenance_ops *ops =
clp->cl_mvops->state_renewal_ops;
int status = -ENOMEM, i;
cred = ops->get_state_renewal_cred(clp);
if (cred == NULL) {
cred = nfs4_get_clid_cred(clp);
if (cred == NULL)
return -ENOKEY;
}
page = alloc_page(GFP_KERNEL);
locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
if (page == NULL || locations == NULL)
goto out;
status = nfs4_proc_get_locations(server, fhandle, locations, page,
cred);
if (status)
goto out;
for (i = 0; i < locations->nlocations; i++)
test_fs_location_for_trunking(&locations->locations[i], clp,
server);
out:
if (page)
__free_page(page);
kfree(locations);
return status;
}
static int nfs4_discover_trunking(struct nfs_server *server,
struct nfs_fh *fhandle)
{
struct nfs4_exception exception = {
.interruptible = true,
};
struct nfs_client *clp = server->nfs_client;
int err = 0;
if (!nfs4_has_session(clp))
goto out;
do {
err = nfs4_handle_exception(server,
_nfs4_discover_trunking(server, fhandle),
&exception);
} while (exception.retry);
out:
return err;
}
static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsinfo *info) struct nfs_fsinfo *info)
{ {
@@ -4441,7 +4552,8 @@ static int nfs4_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle,
return err; return err;
} }
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry,
const struct cred *cred)
{ {
struct nfs_server *server = NFS_SERVER(inode); struct nfs_server *server = NFS_SERVER(inode);
struct nfs4_accessargs args = { struct nfs4_accessargs args = {
@@ -4455,7 +4567,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS],
.rpc_argp = &args, .rpc_argp = &args,
.rpc_resp = &res, .rpc_resp = &res,
.rpc_cred = entry->cred, .rpc_cred = cred,
}; };
int status = 0; int status = 0;
@@ -4475,14 +4587,15 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
return status; return status;
} }
static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry,
const struct cred *cred)
{ {
struct nfs4_exception exception = { struct nfs4_exception exception = {
.interruptible = true, .interruptible = true,
}; };
int err; int err;
do { do {
err = _nfs4_proc_access(inode, entry); err = _nfs4_proc_access(inode, entry, cred);
trace_nfs4_access(inode, err); trace_nfs4_access(inode, err);
err = nfs4_handle_exception(NFS_SERVER(inode), err, err = nfs4_handle_exception(NFS_SERVER(inode), err,
&exception); &exception);
@@ -4663,8 +4776,10 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg,
nfs_fattr_init(res->dir_attr); nfs_fattr_init(res->dir_attr);
if (inode) if (inode) {
nfs4_inode_return_delegation(inode); nfs4_inode_return_delegation(inode);
nfs_d_prune_case_insensitive_aliases(inode);
}
} }
static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data)
@@ -4730,6 +4845,7 @@ static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
return 0; return 0;
if (task->tk_status == 0) { if (task->tk_status == 0) {
nfs_d_prune_case_insensitive_aliases(d_inode(data->old_dentry));
if (new_dir != old_dir) { if (new_dir != old_dir) {
/* Note: If we moved a directory, nlink will change */ /* Note: If we moved a directory, nlink will change */
nfs4_update_changeattr(old_dir, &res->old_cinfo, nfs4_update_changeattr(old_dir, &res->old_cinfo,
@@ -5422,14 +5538,14 @@ bool nfs4_write_need_cache_consistency_data(struct nfs_pgio_header *hdr)
return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0; return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0;
} }
static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ], const __u32 *src, void nfs4_bitmask_set(__u32 bitmask[], const __u32 src[],
struct inode *inode, struct nfs_server *server, struct inode *inode, unsigned long cache_validity)
struct nfs4_label *label)
{ {
unsigned long cache_validity = READ_ONCE(NFS_I(inode)->cache_validity); struct nfs_server *server = NFS_SERVER(inode);
unsigned int i; unsigned int i;
memcpy(bitmask, src, sizeof(*bitmask) * NFS4_BITMASK_SZ); memcpy(bitmask, src, sizeof(*bitmask) * NFS4_BITMASK_SZ);
cache_validity |= READ_ONCE(NFS_I(inode)->cache_validity);
if (cache_validity & NFS_INO_INVALID_CHANGE) if (cache_validity & NFS_INO_INVALID_CHANGE)
bitmask[0] |= FATTR4_WORD0_CHANGE; bitmask[0] |= FATTR4_WORD0_CHANGE;
@@ -5441,8 +5557,6 @@ static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ], const __u32 *src,
bitmask[1] |= FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP; bitmask[1] |= FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP;
if (cache_validity & NFS_INO_INVALID_NLINK) if (cache_validity & NFS_INO_INVALID_NLINK)
bitmask[1] |= FATTR4_WORD1_NUMLINKS; bitmask[1] |= FATTR4_WORD1_NUMLINKS;
if (label && label->len && cache_validity & NFS_INO_INVALID_LABEL)
bitmask[2] |= FATTR4_WORD2_SECURITY_LABEL;
if (cache_validity & NFS_INO_INVALID_CTIME) if (cache_validity & NFS_INO_INVALID_CTIME)
bitmask[1] |= FATTR4_WORD1_TIME_METADATA; bitmask[1] |= FATTR4_WORD1_TIME_METADATA;
if (cache_validity & NFS_INO_INVALID_MTIME) if (cache_validity & NFS_INO_INVALID_MTIME)
@@ -5469,7 +5583,7 @@ static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
} else { } else {
nfs4_bitmask_set(hdr->args.bitmask_store, nfs4_bitmask_set(hdr->args.bitmask_store,
server->cache_consistency_bitmask, server->cache_consistency_bitmask,
hdr->inode, server, NULL); hdr->inode, NFS_INO_INVALID_BLOCKS);
hdr->args.bitmask = hdr->args.bitmask_store; hdr->args.bitmask = hdr->args.bitmask_store;
} }
@@ -6507,8 +6621,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
data->args.fhandle = &data->fh; data->args.fhandle = &data->fh;
data->args.stateid = &data->stateid; data->args.stateid = &data->stateid;
nfs4_bitmask_set(data->args.bitmask_store, nfs4_bitmask_set(data->args.bitmask_store,
server->cache_consistency_bitmask, inode, server, server->cache_consistency_bitmask, inode, 0);
NULL);
data->args.bitmask = data->args.bitmask_store; data->args.bitmask = data->args.bitmask_store;
nfs_copy_fh(&data->fh, NFS_FH(inode)); nfs_copy_fh(&data->fh, NFS_FH(inode));
nfs4_stateid_copy(&data->stateid, stateid); nfs4_stateid_copy(&data->stateid, stateid);
@@ -7611,7 +7724,7 @@ static int nfs4_xattr_set_nfs4_user(const struct xattr_handler *handler,
const char *key, const void *buf, const char *key, const void *buf,
size_t buflen, int flags) size_t buflen, int flags)
{ {
struct nfs_access_entry cache; u32 mask;
int ret; int ret;
if (!nfs_server_capable(inode, NFS_CAP_XATTR)) if (!nfs_server_capable(inode, NFS_CAP_XATTR))
@@ -7626,8 +7739,8 @@ static int nfs4_xattr_set_nfs4_user(const struct xattr_handler *handler,
* do a cached access check for the XA* flags to possibly avoid * do a cached access check for the XA* flags to possibly avoid
* doing an RPC and getting EACCES back. * doing an RPC and getting EACCES back.
*/ */
if (!nfs_access_get_cached(inode, current_cred(), &cache, true)) { if (!nfs_access_get_cached(inode, current_cred(), &mask, true)) {
if (!(cache.mask & NFS_ACCESS_XAWRITE)) if (!(mask & NFS_ACCESS_XAWRITE))
return -EACCES; return -EACCES;
} }
@@ -7648,14 +7761,14 @@ static int nfs4_xattr_get_nfs4_user(const struct xattr_handler *handler,
struct dentry *unused, struct inode *inode, struct dentry *unused, struct inode *inode,
const char *key, void *buf, size_t buflen) const char *key, void *buf, size_t buflen)
{ {
struct nfs_access_entry cache; u32 mask;
ssize_t ret; ssize_t ret;
if (!nfs_server_capable(inode, NFS_CAP_XATTR)) if (!nfs_server_capable(inode, NFS_CAP_XATTR))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (!nfs_access_get_cached(inode, current_cred(), &cache, true)) { if (!nfs_access_get_cached(inode, current_cred(), &mask, true)) {
if (!(cache.mask & NFS_ACCESS_XAREAD)) if (!(mask & NFS_ACCESS_XAREAD))
return -EACCES; return -EACCES;
} }
@@ -7680,13 +7793,13 @@ nfs4_listxattr_nfs4_user(struct inode *inode, char *list, size_t list_len)
ssize_t ret, size; ssize_t ret, size;
char *buf; char *buf;
size_t buflen; size_t buflen;
struct nfs_access_entry cache; u32 mask;
if (!nfs_server_capable(inode, NFS_CAP_XATTR)) if (!nfs_server_capable(inode, NFS_CAP_XATTR))
return 0; return 0;
if (!nfs_access_get_cached(inode, current_cred(), &cache, true)) { if (!nfs_access_get_cached(inode, current_cred(), &mask, true)) {
if (!(cache.mask & NFS_ACCESS_XALIST)) if (!(mask & NFS_ACCESS_XALIST))
return 0; return 0;
} }
@@ -7818,18 +7931,18 @@ int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir,
* appended to this compound to identify the client ID which is * appended to this compound to identify the client ID which is
* performing recovery. * performing recovery.
*/ */
static int _nfs40_proc_get_locations(struct inode *inode, static int _nfs40_proc_get_locations(struct nfs_server *server,
struct nfs_fh *fhandle,
struct nfs4_fs_locations *locations, struct nfs4_fs_locations *locations,
struct page *page, const struct cred *cred) struct page *page, const struct cred *cred)
{ {
struct nfs_server *server = NFS_SERVER(inode);
struct rpc_clnt *clnt = server->client; struct rpc_clnt *clnt = server->client;
u32 bitmask[2] = { u32 bitmask[2] = {
[0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS,
}; };
struct nfs4_fs_locations_arg args = { struct nfs4_fs_locations_arg args = {
.clientid = server->nfs_client->cl_clientid, .clientid = server->nfs_client->cl_clientid,
.fh = NFS_FH(inode), .fh = fhandle,
.page = page, .page = page,
.bitmask = bitmask, .bitmask = bitmask,
.migration = 1, /* skip LOOKUP */ .migration = 1, /* skip LOOKUP */
@@ -7875,17 +7988,17 @@ static int _nfs40_proc_get_locations(struct inode *inode,
* When the client supports GETATTR(fs_locations_info), it can * When the client supports GETATTR(fs_locations_info), it can
* be plumbed in here. * be plumbed in here.
*/ */
static int _nfs41_proc_get_locations(struct inode *inode, static int _nfs41_proc_get_locations(struct nfs_server *server,
struct nfs_fh *fhandle,
struct nfs4_fs_locations *locations, struct nfs4_fs_locations *locations,
struct page *page, const struct cred *cred) struct page *page, const struct cred *cred)
{ {
struct nfs_server *server = NFS_SERVER(inode);
struct rpc_clnt *clnt = server->client; struct rpc_clnt *clnt = server->client;
u32 bitmask[2] = { u32 bitmask[2] = {
[0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS,
}; };
struct nfs4_fs_locations_arg args = { struct nfs4_fs_locations_arg args = {
.fh = NFS_FH(inode), .fh = fhandle,
.page = page, .page = page,
.bitmask = bitmask, .bitmask = bitmask,
.migration = 1, /* skip LOOKUP */ .migration = 1, /* skip LOOKUP */
@@ -7934,11 +8047,11 @@ static int _nfs41_proc_get_locations(struct inode *inode,
* -NFS4ERR_LEASE_MOVED is returned if the server still has leases * -NFS4ERR_LEASE_MOVED is returned if the server still has leases
* from this client that require migration recovery. * from this client that require migration recovery.
*/ */
int nfs4_proc_get_locations(struct inode *inode, int nfs4_proc_get_locations(struct nfs_server *server,
struct nfs_fh *fhandle,
struct nfs4_fs_locations *locations, struct nfs4_fs_locations *locations,
struct page *page, const struct cred *cred) struct page *page, const struct cred *cred)
{ {
struct nfs_server *server = NFS_SERVER(inode);
struct nfs_client *clp = server->nfs_client; struct nfs_client *clp = server->nfs_client;
const struct nfs4_mig_recovery_ops *ops = const struct nfs4_mig_recovery_ops *ops =
clp->cl_mvops->mig_recovery_ops; clp->cl_mvops->mig_recovery_ops;
@@ -7951,10 +8064,11 @@ int nfs4_proc_get_locations(struct inode *inode,
(unsigned long long)server->fsid.major, (unsigned long long)server->fsid.major,
(unsigned long long)server->fsid.minor, (unsigned long long)server->fsid.minor,
clp->cl_hostname); clp->cl_hostname);
nfs_display_fhandle(NFS_FH(inode), __func__); nfs_display_fhandle(fhandle, __func__);
do { do {
status = ops->get_locations(inode, locations, page, cred); status = ops->get_locations(server, fhandle, locations, page,
cred);
if (status != -NFS4ERR_DELAY) if (status != -NFS4ERR_DELAY)
break; break;
nfs4_handle_exception(server, status, &exception); nfs4_handle_exception(server, status, &exception);
@@ -10423,6 +10537,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
.free_client = nfs4_free_client, .free_client = nfs4_free_client,
.create_server = nfs4_create_server, .create_server = nfs4_create_server,
.clone_server = nfs_clone_server, .clone_server = nfs_clone_server,
.discover_trunking = nfs4_discover_trunking,
}; };
static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {

View File

@@ -2098,7 +2098,8 @@ static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred
} }
inode = d_inode(server->super->s_root); inode = d_inode(server->super->s_root);
result = nfs4_proc_get_locations(inode, locations, page, cred); result = nfs4_proc_get_locations(server, NFS_FH(inode), locations,
page, cred);
if (result) { if (result) {
dprintk("<-- %s: failed to retrieve fs_locations: %d\n", dprintk("<-- %s: failed to retrieve fs_locations: %d\n",
__func__, result); __func__, result);
@@ -2106,6 +2107,9 @@ static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred
} }
result = -NFS4ERR_NXIO; result = -NFS4ERR_NXIO;
if (!locations->nlocations)
goto out;
if (!(locations->fattr.valid & NFS_ATTR_FATTR_V4_LOCATIONS)) { if (!(locations->fattr.valid & NFS_ATTR_FATTR_V4_LOCATIONS)) {
dprintk("<-- %s: No fs_locations data, migration skipped\n", dprintk("<-- %s: No fs_locations data, migration skipped\n",
__func__); __func__);

View File

@@ -3533,6 +3533,42 @@ static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint
return 0; return 0;
} }
static int decode_attr_case_insensitive(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
{
__be32 *p;
*res = 0;
if (unlikely(bitmap[0] & (FATTR4_WORD0_CASE_INSENSITIVE - 1U)))
return -EIO;
if (likely(bitmap[0] & FATTR4_WORD0_CASE_INSENSITIVE)) {
p = xdr_inline_decode(xdr, 4);
if (unlikely(!p))
return -EIO;
*res = be32_to_cpup(p);
bitmap[0] &= ~FATTR4_WORD0_CASE_INSENSITIVE;
}
dprintk("%s: case_insensitive=%s\n", __func__, *res == 0 ? "false" : "true");
return 0;
}
static int decode_attr_case_preserving(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
{
__be32 *p;
*res = 0;
if (unlikely(bitmap[0] & (FATTR4_WORD0_CASE_PRESERVING - 1U)))
return -EIO;
if (likely(bitmap[0] & FATTR4_WORD0_CASE_PRESERVING)) {
p = xdr_inline_decode(xdr, 4);
if (unlikely(!p))
return -EIO;
*res = be32_to_cpup(p);
bitmap[0] &= ~FATTR4_WORD0_CASE_PRESERVING;
}
dprintk("%s: case_preserving=%s\n", __func__, *res == 0 ? "false" : "true");
return 0;
}
static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid) static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
{ {
__be32 *p; __be32 *p;
@@ -3696,8 +3732,6 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st
if (unlikely(!p)) if (unlikely(!p))
goto out_eio; goto out_eio;
n = be32_to_cpup(p); n = be32_to_cpup(p);
if (n <= 0)
goto out_eio;
for (res->nlocations = 0; res->nlocations < n; res->nlocations++) { for (res->nlocations = 0; res->nlocations < n; res->nlocations++) {
u32 m; u32 m;
struct nfs4_fs_location *loc; struct nfs4_fs_location *loc;
@@ -4200,10 +4234,11 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap,
} else } else
printk(KERN_WARNING "%s: label too long (%u)!\n", printk(KERN_WARNING "%s: label too long (%u)!\n",
__func__, len); __func__, len);
if (label && label->label)
dprintk("%s: label=%.*s, len=%d, PI=%d, LFS=%d\n",
__func__, label->len, (char *)label->label,
label->len, label->pi, label->lfs);
} }
if (label && label->label)
dprintk("%s: label=%s, len=%d, PI=%d, LFS=%d\n", __func__,
(char *)label->label, label->len, label->pi, label->lfs);
return status; return status;
} }
@@ -4412,6 +4447,10 @@ static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_re
goto xdr_error; goto xdr_error;
if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0) if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0)
goto xdr_error; goto xdr_error;
if ((status = decode_attr_case_insensitive(xdr, bitmap, &res->case_insensitive)) != 0)
goto xdr_error;
if ((status = decode_attr_case_preserving(xdr, bitmap, &res->case_preserving)) != 0)
goto xdr_error;
if ((status = decode_attr_exclcreat_supported(xdr, bitmap, if ((status = decode_attr_exclcreat_supported(xdr, bitmap,
res->exclcreat_bitmask)) != 0) res->exclcreat_bitmask)) != 0)
goto xdr_error; goto xdr_error;

View File

@@ -142,10 +142,11 @@ static struct attribute *nfs_netns_client_attrs[] = {
&nfs_netns_client_id.attr, &nfs_netns_client_id.attr,
NULL, NULL,
}; };
ATTRIBUTE_GROUPS(nfs_netns_client);
static struct kobj_type nfs_netns_client_type = { static struct kobj_type nfs_netns_client_type = {
.release = nfs_netns_client_release, .release = nfs_netns_client_release,
.default_attrs = nfs_netns_client_attrs, .default_groups = nfs_netns_client_groups,
.sysfs_ops = &kobj_sysfs_ops, .sysfs_ops = &kobj_sysfs_ops,
.namespace = nfs_netns_client_namespace, .namespace = nfs_netns_client_namespace,
}; };

View File

@@ -61,7 +61,9 @@
struct nfs_access_entry { struct nfs_access_entry {
struct rb_node rb_node; struct rb_node rb_node;
struct list_head lru; struct list_head lru;
const struct cred * cred; kuid_t fsuid;
kgid_t fsgid;
struct group_info *group_info;
__u32 mask; __u32 mask;
struct rcu_head rcu_head; struct rcu_head rcu_head;
}; };
@@ -395,7 +397,7 @@ extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fa
extern int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fattr *fattr); extern int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fattr *fattr);
extern int nfs_getattr(struct user_namespace *, const struct path *, extern int nfs_getattr(struct user_namespace *, const struct path *,
struct kstat *, u32, unsigned int); struct kstat *, u32, unsigned int);
extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *); extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *, const struct cred *);
extern void nfs_access_set_mask(struct nfs_access_entry *, u32); extern void nfs_access_set_mask(struct nfs_access_entry *, u32);
extern int nfs_permission(struct user_namespace *, struct inode *, int); extern int nfs_permission(struct user_namespace *, struct inode *, int);
extern int nfs_open(struct inode *, struct file *); extern int nfs_open(struct inode *, struct file *);
@@ -532,8 +534,8 @@ extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh,
struct nfs_fattr *fattr); struct nfs_fattr *fattr);
extern int nfs_may_open(struct inode *inode, const struct cred *cred, int openflags); extern int nfs_may_open(struct inode *inode, const struct cred *cred, int openflags);
extern void nfs_access_zap_cache(struct inode *inode); extern void nfs_access_zap_cache(struct inode *inode);
extern int nfs_access_get_cached(struct inode *inode, const struct cred *cred, struct nfs_access_entry *res, extern int nfs_access_get_cached(struct inode *inode, const struct cred *cred,
bool may_block); u32 *mask, bool may_block);
/* /*
* linux/fs/nfs/symlink.c * linux/fs/nfs/symlink.c

View File

@@ -266,6 +266,8 @@ struct nfs_server {
#define NFS_CAP_ACLS (1U << 3) #define NFS_CAP_ACLS (1U << 3)
#define NFS_CAP_ATOMIC_OPEN (1U << 4) #define NFS_CAP_ATOMIC_OPEN (1U << 4)
#define NFS_CAP_LGOPEN (1U << 5) #define NFS_CAP_LGOPEN (1U << 5)
#define NFS_CAP_CASE_INSENSITIVE (1U << 6)
#define NFS_CAP_CASE_PRESERVING (1U << 7)
#define NFS_CAP_POSIX_LOCK (1U << 14) #define NFS_CAP_POSIX_LOCK (1U << 14)
#define NFS_CAP_UIDGID_NOMAP (1U << 15) #define NFS_CAP_UIDGID_NOMAP (1U << 15)
#define NFS_CAP_STATEID_NFSV41 (1U << 16) #define NFS_CAP_STATEID_NFSV41 (1U << 16)
@@ -282,5 +284,5 @@ struct nfs_server {
#define NFS_CAP_COPY_NOTIFY (1U << 27) #define NFS_CAP_COPY_NOTIFY (1U << 27)
#define NFS_CAP_XATTR (1U << 28) #define NFS_CAP_XATTR (1U << 28)
#define NFS_CAP_READ_PLUS (1U << 29) #define NFS_CAP_READ_PLUS (1U << 29)
#define NFS_CAP_FS_LOCATIONS (1U << 30)
#endif #endif

View File

@@ -1194,6 +1194,8 @@ struct nfs4_server_caps_res {
u32 has_links; u32 has_links;
u32 has_symlinks; u32 has_symlinks;
u32 fh_expire_type; u32 fh_expire_type;
u32 case_insensitive;
u32 case_preserving;
}; };
#define NFS4_PATHNAME_MAXCOMPONENTS 512 #define NFS4_PATHNAME_MAXCOMPONENTS 512
@@ -1737,7 +1739,7 @@ struct nfs_rpc_ops {
struct nfs_fh *, struct nfs_fattr *); struct nfs_fh *, struct nfs_fattr *);
int (*lookupp) (struct inode *, struct nfs_fh *, int (*lookupp) (struct inode *, struct nfs_fh *,
struct nfs_fattr *); struct nfs_fattr *);
int (*access) (struct inode *, struct nfs_access_entry *); int (*access) (struct inode *, struct nfs_access_entry *, const struct cred *);
int (*readlink)(struct inode *, struct page *, unsigned int, int (*readlink)(struct inode *, struct page *, unsigned int,
unsigned int); unsigned int);
int (*create) (struct inode *, struct dentry *, int (*create) (struct inode *, struct dentry *,
@@ -1795,6 +1797,7 @@ struct nfs_rpc_ops {
struct nfs_server *(*create_server)(struct fs_context *); struct nfs_server *(*create_server)(struct fs_context *);
struct nfs_server *(*clone_server)(struct nfs_server *, struct nfs_fh *, struct nfs_server *(*clone_server)(struct nfs_server *, struct nfs_fh *,
struct nfs_fattr *, rpc_authflavor_t); struct nfs_fattr *, rpc_authflavor_t);
int (*discover_trunking)(struct nfs_server *, struct nfs_fh *);
}; };
/* /*

View File

@@ -794,6 +794,9 @@ RPC_SHOW_SOCKET
RPC_SHOW_SOCK RPC_SHOW_SOCK
#include <trace/events/net_probe_common.h>
/* /*
* Now redefine the EM() and EMe() macros to map the enums to the strings * Now redefine the EM() and EMe() macros to map the enums to the strings
* that will be printed in the output. * that will be printed in the output.
@@ -816,27 +819,32 @@ DECLARE_EVENT_CLASS(xs_socket_event,
__field(unsigned int, socket_state) __field(unsigned int, socket_state)
__field(unsigned int, sock_state) __field(unsigned int, sock_state)
__field(unsigned long long, ino) __field(unsigned long long, ino)
__string(dstaddr, __array(__u8, saddr, sizeof(struct sockaddr_in6))
xprt->address_strings[RPC_DISPLAY_ADDR]) __array(__u8, daddr, sizeof(struct sockaddr_in6))
__string(dstport,
xprt->address_strings[RPC_DISPLAY_PORT])
), ),
TP_fast_assign( TP_fast_assign(
struct inode *inode = SOCK_INODE(socket); struct inode *inode = SOCK_INODE(socket);
const struct sock *sk = socket->sk;
const struct inet_sock *inet = inet_sk(sk);
memset(__entry->saddr, 0, sizeof(struct sockaddr_in6));
memset(__entry->daddr, 0, sizeof(struct sockaddr_in6));
TP_STORE_ADDR_PORTS(__entry, inet, sk);
__entry->socket_state = socket->state; __entry->socket_state = socket->state;
__entry->sock_state = socket->sk->sk_state; __entry->sock_state = socket->sk->sk_state;
__entry->ino = (unsigned long long)inode->i_ino; __entry->ino = (unsigned long long)inode->i_ino;
__assign_str(dstaddr,
xprt->address_strings[RPC_DISPLAY_ADDR]);
__assign_str(dstport,
xprt->address_strings[RPC_DISPLAY_PORT]);
), ),
TP_printk( TP_printk(
"socket:[%llu] dstaddr=%s/%s " "socket:[%llu] srcaddr=%pISpc dstaddr=%pISpc "
"state=%u (%s) sk_state=%u (%s)", "state=%u (%s) sk_state=%u (%s)",
__entry->ino, __get_str(dstaddr), __get_str(dstport), __entry->ino,
__entry->saddr,
__entry->daddr,
__entry->socket_state, __entry->socket_state,
rpc_show_socket_state(__entry->socket_state), rpc_show_socket_state(__entry->socket_state),
__entry->sock_state, __entry->sock_state,
@@ -866,29 +874,33 @@ DECLARE_EVENT_CLASS(xs_socket_event_done,
__field(unsigned int, socket_state) __field(unsigned int, socket_state)
__field(unsigned int, sock_state) __field(unsigned int, sock_state)
__field(unsigned long long, ino) __field(unsigned long long, ino)
__string(dstaddr, __array(__u8, saddr, sizeof(struct sockaddr_in6))
xprt->address_strings[RPC_DISPLAY_ADDR]) __array(__u8, daddr, sizeof(struct sockaddr_in6))
__string(dstport,
xprt->address_strings[RPC_DISPLAY_PORT])
), ),
TP_fast_assign( TP_fast_assign(
struct inode *inode = SOCK_INODE(socket); struct inode *inode = SOCK_INODE(socket);
const struct sock *sk = socket->sk;
const struct inet_sock *inet = inet_sk(sk);
memset(__entry->saddr, 0, sizeof(struct sockaddr_in6));
memset(__entry->daddr, 0, sizeof(struct sockaddr_in6));
TP_STORE_ADDR_PORTS(__entry, inet, sk);
__entry->socket_state = socket->state; __entry->socket_state = socket->state;
__entry->sock_state = socket->sk->sk_state; __entry->sock_state = socket->sk->sk_state;
__entry->ino = (unsigned long long)inode->i_ino; __entry->ino = (unsigned long long)inode->i_ino;
__entry->error = error; __entry->error = error;
__assign_str(dstaddr,
xprt->address_strings[RPC_DISPLAY_ADDR]);
__assign_str(dstport,
xprt->address_strings[RPC_DISPLAY_PORT]);
), ),
TP_printk( TP_printk(
"error=%d socket:[%llu] dstaddr=%s/%s " "error=%d socket:[%llu] srcaddr=%pISpc dstaddr=%pISpc "
"state=%u (%s) sk_state=%u (%s)", "state=%u (%s) sk_state=%u (%s)",
__entry->error, __entry->error,
__entry->ino, __get_str(dstaddr), __get_str(dstport), __entry->ino,
__entry->saddr,
__entry->daddr,
__entry->socket_state, __entry->socket_state,
rpc_show_socket_state(__entry->socket_state), rpc_show_socket_state(__entry->socket_state),
__entry->sock_state, __entry->sock_state,
@@ -953,7 +965,8 @@ TRACE_EVENT(rpc_socket_nospace,
{ BIT(XPRT_REMOVE), "REMOVE" }, \ { BIT(XPRT_REMOVE), "REMOVE" }, \
{ BIT(XPRT_CONGESTED), "CONGESTED" }, \ { BIT(XPRT_CONGESTED), "CONGESTED" }, \
{ BIT(XPRT_CWND_WAIT), "CWND_WAIT" }, \ { BIT(XPRT_CWND_WAIT), "CWND_WAIT" }, \
{ BIT(XPRT_WRITE_SPACE), "WRITE_SPACE" }) { BIT(XPRT_WRITE_SPACE), "WRITE_SPACE" }, \
{ BIT(XPRT_SND_IS_COOKIE), "SND_IS_COOKIE" })
DECLARE_EVENT_CLASS(rpc_xprt_lifetime_class, DECLARE_EVENT_CLASS(rpc_xprt_lifetime_class,
TP_PROTO( TP_PROTO(
@@ -1150,8 +1163,11 @@ DECLARE_EVENT_CLASS(xprt_writelock_event,
__entry->task_id = -1; __entry->task_id = -1;
__entry->client_id = -1; __entry->client_id = -1;
} }
__entry->snd_task_id = xprt->snd_task ? if (xprt->snd_task &&
xprt->snd_task->tk_pid : -1; !test_bit(XPRT_SND_IS_COOKIE, &xprt->state))
__entry->snd_task_id = xprt->snd_task->tk_pid;
else
__entry->snd_task_id = -1;
), ),
TP_printk(SUNRPC_TRACE_TASK_SPECIFIER TP_printk(SUNRPC_TRACE_TASK_SPECIFIER
@@ -1196,8 +1212,12 @@ DECLARE_EVENT_CLASS(xprt_cong_event,
__entry->task_id = -1; __entry->task_id = -1;
__entry->client_id = -1; __entry->client_id = -1;
} }
__entry->snd_task_id = xprt->snd_task ? if (xprt->snd_task &&
xprt->snd_task->tk_pid : -1; !test_bit(XPRT_SND_IS_COOKIE, &xprt->state))
__entry->snd_task_id = xprt->snd_task->tk_pid;
else
__entry->snd_task_id = -1;
__entry->cong = xprt->cong; __entry->cong = xprt->cong;
__entry->cwnd = xprt->cwnd; __entry->cwnd = xprt->cwnd;
__entry->wait = test_bit(XPRT_CWND_WAIT, &xprt->state); __entry->wait = test_bit(XPRT_CWND_WAIT, &xprt->state);

View File

@@ -222,10 +222,8 @@ g_verify_token_header(struct xdr_netobj *mech, int *body_size,
if (ret) if (ret)
return ret; return ret;
if (!ret) { *buf_in = buf;
*buf_in = buf; *body_size = toksize;
*body_size = toksize;
}
return ret; return ret;
} }

View File

@@ -2900,7 +2900,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
unsigned long connect_timeout; unsigned long connect_timeout;
unsigned long reconnect_timeout; unsigned long reconnect_timeout;
unsigned char resvport, reuseport; unsigned char resvport, reuseport;
int ret = 0; int ret = 0, ident;
rcu_read_lock(); rcu_read_lock();
xps = xprt_switch_get(rcu_dereference(clnt->cl_xpi.xpi_xpswitch)); xps = xprt_switch_get(rcu_dereference(clnt->cl_xpi.xpi_xpswitch));
@@ -2914,8 +2914,11 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
reuseport = xprt->reuseport; reuseport = xprt->reuseport;
connect_timeout = xprt->connect_timeout; connect_timeout = xprt->connect_timeout;
reconnect_timeout = xprt->max_reconnect_timeout; reconnect_timeout = xprt->max_reconnect_timeout;
ident = xprt->xprt_class->ident;
rcu_read_unlock(); rcu_read_unlock();
if (!xprtargs->ident)
xprtargs->ident = ident;
xprt = xprt_create_transport(xprtargs); xprt = xprt_create_transport(xprtargs);
if (IS_ERR(xprt)) { if (IS_ERR(xprt)) {
ret = PTR_ERR(xprt); ret = PTR_ERR(xprt);

View File

@@ -295,8 +295,10 @@ static ssize_t rpc_sysfs_xprt_state_change(struct kobject *kobj,
online = 1; online = 1;
else if (!strncmp(buf, "remove", 6)) else if (!strncmp(buf, "remove", 6))
remove = 1; remove = 1;
else else {
return -EINVAL; count = -EINVAL;
goto out_put;
}
if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) { if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) {
count = -EINTR; count = -EINTR;
@@ -307,25 +309,28 @@ static ssize_t rpc_sysfs_xprt_state_change(struct kobject *kobj,
goto release_tasks; goto release_tasks;
} }
if (offline) { if (offline) {
set_bit(XPRT_OFFLINE, &xprt->state); if (!test_and_set_bit(XPRT_OFFLINE, &xprt->state)) {
spin_lock(&xps->xps_lock); spin_lock(&xps->xps_lock);
xps->xps_nactive--; xps->xps_nactive--;
spin_unlock(&xps->xps_lock); spin_unlock(&xps->xps_lock);
}
} else if (online) { } else if (online) {
clear_bit(XPRT_OFFLINE, &xprt->state); if (test_and_clear_bit(XPRT_OFFLINE, &xprt->state)) {
spin_lock(&xps->xps_lock); spin_lock(&xps->xps_lock);
xps->xps_nactive++; xps->xps_nactive++;
spin_unlock(&xps->xps_lock); spin_unlock(&xps->xps_lock);
}
} else if (remove) { } else if (remove) {
if (test_bit(XPRT_OFFLINE, &xprt->state)) { if (test_bit(XPRT_OFFLINE, &xprt->state)) {
set_bit(XPRT_REMOVE, &xprt->state); if (!test_and_set_bit(XPRT_REMOVE, &xprt->state)) {
xprt_force_disconnect(xprt); xprt_force_disconnect(xprt);
if (test_bit(XPRT_CONNECTED, &xprt->state)) { if (test_bit(XPRT_CONNECTED, &xprt->state)) {
if (!xprt->sending.qlen && if (!xprt->sending.qlen &&
!xprt->pending.qlen && !xprt->pending.qlen &&
!xprt->backlog.qlen && !xprt->backlog.qlen &&
!atomic_long_read(&xprt->queuelen)) !atomic_long_read(&xprt->queuelen))
rpc_xprt_switch_remove_xprt(xps, xprt); rpc_xprt_switch_remove_xprt(xps, xprt);
}
} }
} else { } else {
count = -EINVAL; count = -EINVAL;
@@ -422,6 +427,7 @@ static struct attribute *rpc_sysfs_xprt_attrs[] = {
&rpc_sysfs_xprt_change_state.attr, &rpc_sysfs_xprt_change_state.attr,
NULL, NULL,
}; };
ATTRIBUTE_GROUPS(rpc_sysfs_xprt);
static struct kobj_attribute rpc_sysfs_xprt_switch_info = static struct kobj_attribute rpc_sysfs_xprt_switch_info =
__ATTR(xprt_switch_info, 0444, rpc_sysfs_xprt_switch_info_show, NULL); __ATTR(xprt_switch_info, 0444, rpc_sysfs_xprt_switch_info_show, NULL);
@@ -430,6 +436,7 @@ static struct attribute *rpc_sysfs_xprt_switch_attrs[] = {
&rpc_sysfs_xprt_switch_info.attr, &rpc_sysfs_xprt_switch_info.attr,
NULL, NULL,
}; };
ATTRIBUTE_GROUPS(rpc_sysfs_xprt_switch);
static struct kobj_type rpc_sysfs_client_type = { static struct kobj_type rpc_sysfs_client_type = {
.release = rpc_sysfs_client_release, .release = rpc_sysfs_client_release,
@@ -439,14 +446,14 @@ static struct kobj_type rpc_sysfs_client_type = {
static struct kobj_type rpc_sysfs_xprt_switch_type = { static struct kobj_type rpc_sysfs_xprt_switch_type = {
.release = rpc_sysfs_xprt_switch_release, .release = rpc_sysfs_xprt_switch_release,
.default_attrs = rpc_sysfs_xprt_switch_attrs, .default_groups = rpc_sysfs_xprt_switch_groups,
.sysfs_ops = &kobj_sysfs_ops, .sysfs_ops = &kobj_sysfs_ops,
.namespace = rpc_sysfs_xprt_switch_namespace, .namespace = rpc_sysfs_xprt_switch_namespace,
}; };
static struct kobj_type rpc_sysfs_xprt_type = { static struct kobj_type rpc_sysfs_xprt_type = {
.release = rpc_sysfs_xprt_release, .release = rpc_sysfs_xprt_release,
.default_attrs = rpc_sysfs_xprt_attrs, .default_groups = rpc_sysfs_xprt_groups,
.sysfs_ops = &kobj_sysfs_ops, .sysfs_ops = &kobj_sysfs_ops,
.namespace = rpc_sysfs_xprt_namespace, .namespace = rpc_sysfs_xprt_namespace,
}; };

View File

@@ -13,10 +13,6 @@
#include "xprt_rdma.h" #include "xprt_rdma.h"
#include <trace/events/rpcrdma.h> #include <trace/events/rpcrdma.h>
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_TRANS
#endif
#undef RPCRDMA_BACKCHANNEL_DEBUG #undef RPCRDMA_BACKCHANNEL_DEBUG
/** /**

View File

@@ -45,10 +45,6 @@
#include "xprt_rdma.h" #include "xprt_rdma.h"
#include <trace/events/rpcrdma.h> #include <trace/events/rpcrdma.h>
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_TRANS
#endif
static void frwr_cid_init(struct rpcrdma_ep *ep, static void frwr_cid_init(struct rpcrdma_ep *ep,
struct rpcrdma_mr *mr) struct rpcrdma_mr *mr)
{ {

View File

@@ -54,10 +54,6 @@
#include "xprt_rdma.h" #include "xprt_rdma.h"
#include <trace/events/rpcrdma.h> #include <trace/events/rpcrdma.h>
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_TRANS
#endif
/* Returns size of largest RPC-over-RDMA header in a Call message /* Returns size of largest RPC-over-RDMA header in a Call message
* *
* The largest Call header contains a full-size Read list and a * The largest Call header contains a full-size Read list and a

View File

@@ -60,10 +60,6 @@
#include "xprt_rdma.h" #include "xprt_rdma.h"
#include <trace/events/rpcrdma.h> #include <trace/events/rpcrdma.h>
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_TRANS
#endif
/* /*
* tunables * tunables
*/ */

View File

@@ -63,17 +63,6 @@
#include "xprt_rdma.h" #include "xprt_rdma.h"
#include <trace/events/rpcrdma.h> #include <trace/events/rpcrdma.h>
/*
* Globals/Macros
*/
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_TRANS
#endif
/*
* internal functions
*/
static int rpcrdma_sendctxs_create(struct rpcrdma_xprt *r_xprt); static int rpcrdma_sendctxs_create(struct rpcrdma_xprt *r_xprt);
static void rpcrdma_sendctxs_destroy(struct rpcrdma_xprt *r_xprt); static void rpcrdma_sendctxs_destroy(struct rpcrdma_xprt *r_xprt);
static void rpcrdma_sendctx_put_locked(struct rpcrdma_xprt *r_xprt, static void rpcrdma_sendctx_put_locked(struct rpcrdma_xprt *r_xprt,
@@ -274,8 +263,6 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
ep->re_connect_status = -ENETUNREACH; ep->re_connect_status = -ENETUNREACH;
goto wake_connect_worker; goto wake_connect_worker;
case RDMA_CM_EVENT_REJECTED: case RDMA_CM_EVENT_REJECTED:
dprintk("rpcrdma: connection to %pISpc rejected: %s\n",
sap, rdma_reject_msg(id, event->status));
ep->re_connect_status = -ECONNREFUSED; ep->re_connect_status = -ECONNREFUSED;
if (event->status == IB_CM_REJ_STALE_CONN) if (event->status == IB_CM_REJ_STALE_CONN)
ep->re_connect_status = -ENOTCONN; ep->re_connect_status = -ENOTCONN;
@@ -291,8 +278,6 @@ disconnected:
break; break;
} }
dprintk("RPC: %s: %pISpc on %s/frwr: %s\n", __func__, sap,
ep->re_id->device->name, rdma_event_msg(event->event));
return 0; return 0;
} }
@@ -419,14 +404,6 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
ep->re_attr.qp_type = IB_QPT_RC; ep->re_attr.qp_type = IB_QPT_RC;
ep->re_attr.port_num = ~0; ep->re_attr.port_num = ~0;
dprintk("RPC: %s: requested max: dtos: send %d recv %d; "
"iovs: send %d recv %d\n",
__func__,
ep->re_attr.cap.max_send_wr,
ep->re_attr.cap.max_recv_wr,
ep->re_attr.cap.max_send_sge,
ep->re_attr.cap.max_recv_sge);
ep->re_send_batch = ep->re_max_requests >> 3; ep->re_send_batch = ep->re_max_requests >> 3;
ep->re_send_count = ep->re_send_batch; ep->re_send_count = ep->re_send_batch;
init_waitqueue_head(&ep->re_connect_wait); init_waitqueue_head(&ep->re_connect_wait);

View File

@@ -1910,7 +1910,7 @@ static void xs_local_connect(struct rpc_xprt *xprt, struct rpc_task *task)
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
int ret; int ret;
if (RPC_IS_ASYNC(task)) { if (RPC_IS_ASYNC(task)) {
/* /*
* We want the AF_LOCAL connect to be resolved in the * We want the AF_LOCAL connect to be resolved in the
* filesystem namespace of the process making the rpc * filesystem namespace of the process making the rpc