Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 98219727 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-3.8' of git://linux-nfs.org/~bfields/linux

Pull nfsd update from Bruce Fields:
 "Included this time:

   - more nfsd containerization work from Stanislav Kinsbursky: we're
     not quite there yet, but should be by 3.9.

   - NFSv4.1 progress: implementation of basic backchannel security
     negotiation and the mandatory BACKCHANNEL_CTL operation.  See

       http://wiki.linux-nfs.org/wiki/index.php/Server_4.0_and_4.1_issues

     for remaining TODO's

   - Fixes for some bugs that could be triggered by unusual compounds.
     Our xdr code wasn't designed with v4 compounds in mind, and it
     shows.  A more thorough rewrite is still a todo.

   - If you've ever seen "RPC: multiple fragments per record not
     supported" logged while using some sort of odd userland NFS client,
     that should now be fixed.

   - Further work from Jeff Layton on our mechanism for storing
     information about NFSv4 clients across reboots.

   - Further work from Bryan Schumaker on his fault-injection mechanism
     (which allows us to discard selective NFSv4 state, to excercise
     rarely-taken recovery code paths in the client.)

   - The usual mix of miscellaneous bugs and cleanup.

  Thanks to everyone who tested or contributed this cycle."

* 'for-3.8' of git://linux-nfs.org/~bfields/linux: (111 commits)
  nfsd4: don't leave freed stateid hashed
  nfsd4: free_stateid can use the current stateid
  nfsd4: cleanup: replace rq_resused count by rq_next_page pointer
  nfsd: warn on odd reply state in nfsd_vfs_read
  nfsd4: fix oops on unusual readlike compound
  nfsd4: disable zero-copy on non-final read ops
  svcrpc: fix some printks
  NFSD: Correct the size calculation in fault_inject_write
  NFSD: Pass correct buffer size to rpc_ntop
  nfsd: pass proper net to nfsd_destroy() from NFSd kthreads
  nfsd: simplify service shutdown
  nfsd: replace boolean nfsd_up flag by users counter
  nfsd: simplify NFSv4 state init and shutdown
  nfsd: introduce helpers for generic resources init and shutdown
  nfsd: make NFSd service structure allocated per net
  nfsd: make NFSd service boot time per-net
  nfsd: per-net NFSd up flag introduced
  nfsd: move per-net startup code to separated function
  nfsd: pass net to __write_ports() and down
  nfsd: pass net to nfsd_set_nrthreads()
  ...
parents 40889e8d 24ffb938
Loading
Loading
Loading
Loading
+4 −16
Original line number Diff line number Diff line
@@ -39,21 +39,10 @@ interoperability problems with future clients. Known issues:
	  from a linux client are possible, but we aren't really
	  conformant with the spec (for example, we don't use kerberos
	  on the backchannel correctly).
	- Incomplete backchannel support: incomplete backchannel gss
	  support and no support for BACKCHANNEL_CTL mean that
	  callbacks (hence delegations and layouts) may not be
	  available and clients confused by the incomplete
	  implementation may fail.
	- We do not support SSV, which provides security for shared
	  client-server state (thus preventing unauthorized tampering
	  with locks and opens, for example).  It is mandatory for
	  servers to support this, though no clients use it yet.
	- Mandatory operations which we do not support, such as
	  DESTROY_CLIENTID, are not currently used by clients, but will be
	  (and the spec recommends their uses in common cases), and
	  clients should not be expected to know how to recover from the
	  case where they are not supported.  This will eventually cause
	  interoperability failures.

In addition, some limitations are inherited from the current NFSv4
implementation:
@@ -89,7 +78,7 @@ Operations
   |                      | MNI        | or OPT)      |                |
   +----------------------+------------+--------------+----------------+
   | ACCESS               | REQ        |              | Section 18.1   |
NS | BACKCHANNEL_CTL      | REQ        |              | Section 18.33  |
I  | BACKCHANNEL_CTL      | REQ        |              | Section 18.33  |
I  | BIND_CONN_TO_SESSION | REQ        |              | Section 18.34  |
   | CLOSE                | REQ        |              | Section 18.2   |
   | COMMIT               | REQ        |              | Section 18.3   |
@@ -99,7 +88,7 @@ NS*| DELEGPURGE | OPT | FDELG (REQ) | Section 18.5 |
   | DELEGRETURN          | OPT        | FDELG,       | Section 18.6   |
   |                      |            | DDELG, pNFS  |                |
   |                      |            | (REQ)        |                |
NS | DESTROY_CLIENTID     | REQ        |              | Section 18.50  |
I  | DESTROY_CLIENTID     | REQ        |              | Section 18.50  |
I  | DESTROY_SESSION      | REQ        |              | Section 18.37  |
I  | EXCHANGE_ID          | REQ        |              | Section 18.35  |
I  | FREE_STATEID         | REQ        |              | Section 18.38  |
@@ -192,7 +181,6 @@ EXCHANGE_ID:

CREATE_SESSION:
* backchannel attributes are ignored
* backchannel security parameters are ignored

SEQUENCE:
* no support for dynamic slot table renegotiation (optional)
@@ -202,7 +190,7 @@ Nonstandard compound limitations:
  ca_maxrequestsize request and a ca_maxresponsesize reply, so we may
  fail to live up to the promise we made in CREATE_SESSION fore channel
  negotiation.
* No more than one IO operation (read, write, readdir) allowed per
  compound.
* No more than one read-like operation allowed per compound; encoding
  replies that cross page boundaries (except for read data) not handled.

See also http://wiki.linux-nfs.org/wiki/index.php/Server_4.0_and_4.1_issues.
+2 −2
Original line number Diff line number Diff line
@@ -322,10 +322,10 @@ static int export_encode_fh(struct inode *inode, struct fid *fid,

	if (parent && (len < 4)) {
		*max_len = 4;
		return 255;
		return FILEID_INVALID;
	} else if (len < 2) {
		*max_len = 2;
		return 255;
		return FILEID_INVALID;
	}

	len = 2;
+1 −1
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ static long do_sys_name_to_handle(struct path *path,
	handle_bytes = handle_dwords * sizeof(u32);
	handle->handle_bytes = handle_bytes;
	if ((handle->handle_bytes > f_handle.handle_bytes) ||
	    (retval == 255) || (retval == -ENOSPC)) {
	    (retval == FILEID_INVALID) || (retval == -ENOSPC)) {
		/* As per old exportfs_encode_fh documentation
		 * we could return ENOSPC to indicate overflow
		 * But file system returned 255 always. So handle
+98 −15
Original line number Diff line number Diff line
@@ -8,61 +8,144 @@
#include <linux/fs.h>
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/nsproxy.h>
#include <linux/sunrpc/clnt.h>
#include <asm/uaccess.h>

#include "state.h"
#include "fault_inject.h"
#include "netns.h"

struct nfsd_fault_inject_op {
	char *file;
	void (*func)(u64);
	u64 (*forget)(struct nfs4_client *, u64);
	u64 (*print)(struct nfs4_client *, u64);
};

static struct nfsd_fault_inject_op inject_ops[] = {
	{
		.file   = "forget_clients",
		.func   = nfsd_forget_clients,
		.forget = nfsd_forget_client,
		.print  = nfsd_print_client,
	},
	{
		.file   = "forget_locks",
		.func   = nfsd_forget_locks,
		.forget = nfsd_forget_client_locks,
		.print  = nfsd_print_client_locks,
	},
	{
		.file   = "forget_openowners",
		.func   = nfsd_forget_openowners,
		.forget = nfsd_forget_client_openowners,
		.print  = nfsd_print_client_openowners,
	},
	{
		.file   = "forget_delegations",
		.func   = nfsd_forget_delegations,
		.forget = nfsd_forget_client_delegations,
		.print  = nfsd_print_client_delegations,
	},
	{
		.file   = "recall_delegations",
		.func   = nfsd_recall_delegations,
		.forget = nfsd_recall_client_delegations,
		.print  = nfsd_print_client_delegations,
	},
};

static long int NUM_INJECT_OPS = sizeof(inject_ops) / sizeof(struct nfsd_fault_inject_op);
static struct dentry *debug_dir;

static int nfsd_inject_set(void *op_ptr, u64 val)
static void nfsd_inject_set(struct nfsd_fault_inject_op *op, u64 val)
{
	struct nfsd_fault_inject_op *op = op_ptr;
	u64 count = 0;

	if (val == 0)
		printk(KERN_INFO "NFSD Fault Injection: %s (all)", op->file);
	else
		printk(KERN_INFO "NFSD Fault Injection: %s (n = %llu)", op->file, val);

	op->func(val);
	return 0;
	nfs4_lock_state();
	count = nfsd_for_n_state(val, op->forget);
	nfs4_unlock_state();
	printk(KERN_INFO "NFSD: %s: found %llu", op->file, count);
}

static void nfsd_inject_set_client(struct nfsd_fault_inject_op *op,
				   struct sockaddr_storage *addr,
				   size_t addr_size)
{
	char buf[INET6_ADDRSTRLEN];
	struct nfs4_client *clp;
	u64 count;

	nfs4_lock_state();
	clp = nfsd_find_client(addr, addr_size);
	if (clp) {
		count = op->forget(clp, 0);
		rpc_ntop((struct sockaddr *)&clp->cl_addr, buf, sizeof(buf));
		printk(KERN_INFO "NFSD [%s]: Client %s had %llu state object(s)\n", op->file, buf, count);
	}
	nfs4_unlock_state();
}

static void nfsd_inject_get(struct nfsd_fault_inject_op *op, u64 *val)
{
	nfs4_lock_state();
	*val = nfsd_for_n_state(0, op->print);
	nfs4_unlock_state();
}

static int nfsd_inject_get(void *data, u64 *val)
static ssize_t fault_inject_read(struct file *file, char __user *buf,
				 size_t len, loff_t *ppos)
{
	*val = 0;
	static u64 val;
	char read_buf[25];
	size_t size, ret;
	loff_t pos = *ppos;

	if (!pos)
		nfsd_inject_get(file->f_dentry->d_inode->i_private, &val);
	size = scnprintf(read_buf, sizeof(read_buf), "%llu\n", val);

	if (pos < 0)
		return -EINVAL;
	if (pos >= size || !len)
		return 0;
	if (len > size - pos)
		len = size - pos;
	ret = copy_to_user(buf, read_buf + pos, len);
	if (ret == len)
		return -EFAULT;
	len -= ret;
	*ppos = pos + len;
	return len;
}

DEFINE_SIMPLE_ATTRIBUTE(fops_nfsd, nfsd_inject_get, nfsd_inject_set, "%llu\n");
static ssize_t fault_inject_write(struct file *file, const char __user *buf,
				  size_t len, loff_t *ppos)
{
	char write_buf[INET6_ADDRSTRLEN];
	size_t size = min(sizeof(write_buf) - 1, len);
	struct net *net = current->nsproxy->net_ns;
	struct sockaddr_storage sa;
	u64 val;

	if (copy_from_user(write_buf, buf, size))
		return -EFAULT;
	write_buf[size] = '\0';

	size = rpc_pton(net, write_buf, size, (struct sockaddr *)&sa, sizeof(sa));
	if (size > 0)
		nfsd_inject_set_client(file->f_dentry->d_inode->i_private, &sa, size);
	else {
		val = simple_strtoll(write_buf, NULL, 0);
		nfsd_inject_set(file->f_dentry->d_inode->i_private, val);
	}
	return len; /* on success, claim we got the whole input */
}

static const struct file_operations fops_nfsd = {
	.owner   = THIS_MODULE,
	.read    = fault_inject_read,
	.write   = fault_inject_write,
};

void nfsd_fault_inject_cleanup(void)
{

fs/nfsd/fault_inject.h

deleted100644 → 0
+0 −28
Original line number Diff line number Diff line
/*
 * Copyright (c) 2011 Bryan Schumaker <bjschuma@netapp.com>
 *
 * Function definitions for fault injection
 */

#ifndef LINUX_NFSD_FAULT_INJECT_H
#define LINUX_NFSD_FAULT_INJECT_H

#ifdef CONFIG_NFSD_FAULT_INJECTION
int nfsd_fault_inject_init(void);
void nfsd_fault_inject_cleanup(void);
void nfsd_forget_clients(u64);
void nfsd_forget_locks(u64);
void nfsd_forget_openowners(u64);
void nfsd_forget_delegations(u64);
void nfsd_recall_delegations(u64);
#else /* CONFIG_NFSD_FAULT_INJECTION */
static inline int nfsd_fault_inject_init(void) { return 0; }
static inline void nfsd_fault_inject_cleanup(void) {}
static inline void nfsd_forget_clients(u64 num) {}
static inline void nfsd_forget_locks(u64 num) {}
static inline void nfsd_forget_openowners(u64 num) {}
static inline void nfsd_forget_delegations(u64 num) {}
static inline void nfsd_recall_delegations(u64 num) {}
#endif /* CONFIG_NFSD_FAULT_INJECTION */

#endif /* LINUX_NFSD_FAULT_INJECT_H */
Loading