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

Commit 9f261e01 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.linux-nfs.org/pub/linux/nfs-2.6: (74 commits)
  NFS: unmark NFS direct I/O as experimental
  NFS: add comments clarifying the use of nfs_post_op_update()
  NFSv4: rpc_mkpipe creating socket inodes w/out sk buffers
  NFS: Use SEEK_END instead of hardcoded value
  NFSv4: When mounting with a port=0 argument, substitute port=2049
  NFSv4: Poll more aggressively when handling NFS4ERR_DELAY
  NFSv4: Handle the condition NFS4ERR_FILE_OPEN
  NFSv4: Retry lease recovery if it failed during a synchronous operation.
  NFS: Don't invalidate the symlink we just stuffed into the cache
  NFS: Make read() return an ESTALE if the file has been deleted
  NFSv4: It's perfectly legal for clp to be NULL here....
  NFS: nfs_lookup - don't hash dentry when optimising away the lookup
  SUNRPC: Fix Oops in pmap_getport_done
  SUNRPC: Add refcounting to the struct rpc_xprt
  SUNRPC: Clean up soft task error handling
  SUNRPC: Handle ENETUNREACH, EHOSTUNREACH and EHOSTDOWN socket errors
  SUNRPC: rpc_delay() should not clobber the rpc_task->tk_status
  Fix a referral error Oops
  NFS: NFS_ROOT should use the new rpc_create API
  NFS: Fix up compiler warnings on 64-bit platforms in client.c
  ...

Manually resolved conflict in net/sunrpc/xprtsock.c
parents a4c12d6c 026ed5c9
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -2734,6 +2734,18 @@ long blk_congestion_wait(int rw, long timeout)

EXPORT_SYMBOL(blk_congestion_wait);

/**
 * blk_congestion_end - wake up sleepers on a congestion queue
 * @rw: READ or WRITE
 */
void blk_congestion_end(int rw)
{
	wait_queue_head_t *wqh = &congestion_wqh[rw];

	if (waitqueue_active(wqh))
		wake_up(wqh);
}

/*
 * Has to be called with the request spinlock acquired
 */
+2 −2
Original line number Diff line number Diff line
@@ -1471,8 +1471,8 @@ config NFS_V4
	  If unsure, say N.

config NFS_DIRECTIO
	bool "Allow direct I/O on NFS files (EXPERIMENTAL)"
	depends on NFS_FS && EXPERIMENTAL
	bool "Allow direct I/O on NFS files"
	depends on NFS_FS
	help
	  This option enables applications to perform uncached I/O on files
	  in NFS file systems using the O_DIRECT open() flag.  When O_DIRECT
+150 −14
Original line number Diff line number Diff line
@@ -828,17 +828,19 @@ void d_instantiate(struct dentry *entry, struct inode * inode)
 * (or otherwise set) by the caller to indicate that it is now
 * in use by the dcache.
 */
struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
static struct dentry *__d_instantiate_unique(struct dentry *entry,
					     struct inode *inode)
{
	struct dentry *alias;
	int len = entry->d_name.len;
	const char *name = entry->d_name.name;
	unsigned int hash = entry->d_name.hash;

	BUG_ON(!list_empty(&entry->d_alias));
	spin_lock(&dcache_lock);
	if (!inode)
		goto do_negative;
	if (!inode) {
		entry->d_inode = NULL;
		return NULL;
	}

	list_for_each_entry(alias, &inode->i_dentry, d_alias) {
		struct qstr *qstr = &alias->d_name;

@@ -851,19 +853,35 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
		if (memcmp(qstr->name, name, len))
			continue;
		dget_locked(alias);
		spin_unlock(&dcache_lock);
		BUG_ON(!d_unhashed(alias));
		iput(inode);
		return alias;
	}

	list_add(&entry->d_alias, &inode->i_dentry);
do_negative:
	entry->d_inode = inode;
	fsnotify_d_instantiate(entry, inode);
	return NULL;
}

struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
{
	struct dentry *result;

	BUG_ON(!list_empty(&entry->d_alias));

	spin_lock(&dcache_lock);
	result = __d_instantiate_unique(entry, inode);
	spin_unlock(&dcache_lock);

	if (!result) {
		security_d_instantiate(entry, inode);
		return NULL;
	}

	BUG_ON(!d_unhashed(result));
	iput(inode);
	return result;
}

EXPORT_SYMBOL(d_instantiate_unique);

/**
@@ -1235,6 +1253,11 @@ static void __d_rehash(struct dentry * entry, struct hlist_head *list)
 	hlist_add_head_rcu(&entry->d_hash, list);
}

static void _d_rehash(struct dentry * entry)
{
	__d_rehash(entry, d_hash(entry->d_parent, entry->d_name.hash));
}

/**
 * d_rehash	- add an entry back to the hash
 * @entry: dentry to add to the hash
@@ -1244,11 +1267,9 @@ static void __d_rehash(struct dentry * entry, struct hlist_head *list)
 
void d_rehash(struct dentry * entry)
{
	struct hlist_head *list = d_hash(entry->d_parent, entry->d_name.hash);

	spin_lock(&dcache_lock);
	spin_lock(&entry->d_lock);
	__d_rehash(entry, list);
	_d_rehash(entry);
	spin_unlock(&entry->d_lock);
	spin_unlock(&dcache_lock);
}
@@ -1386,6 +1407,120 @@ void d_move(struct dentry * dentry, struct dentry * target)
	spin_unlock(&dcache_lock);
}

/*
 * Prepare an anonymous dentry for life in the superblock's dentry tree as a
 * named dentry in place of the dentry to be replaced.
 */
static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
{
	struct dentry *dparent, *aparent;

	switch_names(dentry, anon);
	do_switch(dentry->d_name.len, anon->d_name.len);
	do_switch(dentry->d_name.hash, anon->d_name.hash);

	dparent = dentry->d_parent;
	aparent = anon->d_parent;

	dentry->d_parent = (aparent == anon) ? dentry : aparent;
	list_del(&dentry->d_u.d_child);
	if (!IS_ROOT(dentry))
		list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
	else
		INIT_LIST_HEAD(&dentry->d_u.d_child);

	anon->d_parent = (dparent == dentry) ? anon : dparent;
	list_del(&anon->d_u.d_child);
	if (!IS_ROOT(anon))
		list_add(&anon->d_u.d_child, &anon->d_parent->d_subdirs);
	else
		INIT_LIST_HEAD(&anon->d_u.d_child);

	anon->d_flags &= ~DCACHE_DISCONNECTED;
}

/**
 * d_materialise_unique - introduce an inode into the tree
 * @dentry: candidate dentry
 * @inode: inode to bind to the dentry, to which aliases may be attached
 *
 * Introduces an dentry into the tree, substituting an extant disconnected
 * root directory alias in its place if there is one
 */
struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
{
	struct dentry *alias, *actual;

	BUG_ON(!d_unhashed(dentry));

	spin_lock(&dcache_lock);

	if (!inode) {
		actual = dentry;
		dentry->d_inode = NULL;
		goto found_lock;
	}

	/* See if a disconnected directory already exists as an anonymous root
	 * that we should splice into the tree instead */
	if (S_ISDIR(inode->i_mode) && (alias = __d_find_alias(inode, 1))) {
		spin_lock(&alias->d_lock);

		/* Is this a mountpoint that we could splice into our tree? */
		if (IS_ROOT(alias))
			goto connect_mountpoint;

		if (alias->d_name.len == dentry->d_name.len &&
		    alias->d_parent == dentry->d_parent &&
		    memcmp(alias->d_name.name,
			   dentry->d_name.name,
			   dentry->d_name.len) == 0)
			goto replace_with_alias;

		spin_unlock(&alias->d_lock);

		/* Doh! Seem to be aliasing directories for some reason... */
		dput(alias);
	}

	/* Add a unique reference */
	actual = __d_instantiate_unique(dentry, inode);
	if (!actual)
		actual = dentry;
	else if (unlikely(!d_unhashed(actual)))
		goto shouldnt_be_hashed;

found_lock:
	spin_lock(&actual->d_lock);
found:
	_d_rehash(actual);
	spin_unlock(&actual->d_lock);
	spin_unlock(&dcache_lock);

	if (actual == dentry) {
		security_d_instantiate(dentry, inode);
		return NULL;
	}

	iput(inode);
	return actual;

	/* Convert the anonymous/root alias into an ordinary dentry */
connect_mountpoint:
	__d_materialise_dentry(dentry, alias);

	/* Replace the candidate dentry with the alias in the tree */
replace_with_alias:
	__d_drop(alias);
	actual = alias;
	goto found;

shouldnt_be_hashed:
	spin_unlock(&dcache_lock);
	BUG();
	goto shouldnt_be_hashed;
}

/**
 * d_path - return the path of a dentry
 * @dentry: dentry to report
@@ -1784,6 +1919,7 @@ EXPORT_SYMBOL(d_instantiate);
EXPORT_SYMBOL(d_invalidate);
EXPORT_SYMBOL(d_lookup);
EXPORT_SYMBOL(d_move);
EXPORT_SYMBOL_GPL(d_materialise_unique);
EXPORT_SYMBOL(d_path);
EXPORT_SYMBOL(d_prune_aliases);
EXPORT_SYMBOL(d_rehash);
+5 −5
Original line number Diff line number Diff line
@@ -151,11 +151,13 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req)
int
nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
{
	struct rpc_clnt		*client = NFS_CLIENT(inode);
	struct sockaddr_in	addr;
	struct nlm_host		*host;
	struct nlm_rqst		*call;
	sigset_t		oldset;
	unsigned long		flags;
	int			status, proto, vers;
	int			status, vers;

	vers = (NFS_PROTO(inode)->version == 3) ? 4 : 1;
	if (NFS_PROTO(inode)->version > 3) {
@@ -163,10 +165,8 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
		return -ENOLCK;
	}

	/* Retrieve transport protocol from NFS client */
	proto = NFS_CLIENT(inode)->cl_xprt->prot;

	host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers);
	rpc_peeraddr(client, (struct sockaddr *) &addr, sizeof(addr));
	host = nlmclnt_lookup_host(&addr, client->cl_xprt->prot, vers);
	if (host == NULL)
		return -ENOLCK;

+27 −24
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@
#define NLM_HOST_REBIND		(60 * HZ)
#define NLM_HOST_EXPIRE		((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ)
#define NLM_HOST_COLLECT	((nrhosts > NLM_HOST_MAX)? 120 * HZ :  60 * HZ)
#define NLM_HOST_ADDR(sv)	(&(sv)->s_nlmclnt->cl_xprt->addr)

static struct nlm_host *	nlm_hosts[NLM_HOST_NRHASH];
static unsigned long		next_gc;
@@ -167,7 +166,6 @@ struct rpc_clnt *
nlm_bind_host(struct nlm_host *host)
{
	struct rpc_clnt	*clnt;
	struct rpc_xprt	*xprt;

	dprintk("lockd: nlm_bind_host(%08x)\n",
			(unsigned)ntohl(host->h_addr.sin_addr.s_addr));
@@ -179,7 +177,6 @@ nlm_bind_host(struct nlm_host *host)
	 * RPC rebind is required
	 */
	if ((clnt = host->h_rpcclnt) != NULL) {
		xprt = clnt->cl_xprt;
		if (time_after_eq(jiffies, host->h_nextrebind)) {
			rpc_force_rebind(clnt);
			host->h_nextrebind = jiffies + NLM_HOST_REBIND;
@@ -187,31 +184,37 @@ nlm_bind_host(struct nlm_host *host)
					host->h_nextrebind - jiffies);
		}
	} else {
		xprt = xprt_create_proto(host->h_proto, &host->h_addr, NULL);
		if (IS_ERR(xprt))
			goto forgetit;

		xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout);
		xprt->resvport = 1;	/* NLM requires a reserved port */

		/* Existing NLM servers accept AUTH_UNIX only */
		clnt = rpc_new_client(xprt, host->h_name, &nlm_program,
					host->h_version, RPC_AUTH_UNIX);
		if (IS_ERR(clnt))
			goto forgetit;
		clnt->cl_autobind = 1;	/* turn on pmap queries */
		clnt->cl_softrtry = 1; /* All queries are soft */

		unsigned long increment = nlmsvc_timeout * HZ;
		struct rpc_timeout timeparms = {
			.to_initval	= increment,
			.to_increment	= increment,
			.to_maxval	= increment * 6UL,
			.to_retries	= 5U,
		};
		struct rpc_create_args args = {
			.protocol	= host->h_proto,
			.address	= (struct sockaddr *)&host->h_addr,
			.addrsize	= sizeof(host->h_addr),
			.timeout	= &timeparms,
			.servername	= host->h_name,
			.program	= &nlm_program,
			.version	= host->h_version,
			.authflavor	= RPC_AUTH_UNIX,
			.flags		= (RPC_CLNT_CREATE_HARDRTRY |
					   RPC_CLNT_CREATE_AUTOBIND),
		};

		clnt = rpc_create(&args);
		if (!IS_ERR(clnt))
			host->h_rpcclnt = clnt;
		else {
			printk("lockd: couldn't create RPC handle for %s\n", host->h_name);
			clnt = NULL;
		}
	}

	mutex_unlock(&host->h_mutex);
	return clnt;

forgetit:
	printk("lockd: couldn't create RPC handle for %s\n", host->h_name);
	mutex_unlock(&host->h_mutex);
	return NULL;
}

/*
Loading