Skip to content

Commit

Permalink
Merge git://git.linux-nfs.org/pub/linux/nfs-2.6
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Linus Torvalds committed Sep 23, 2006
2 parents a4c12d6 + 026ed5c commit 9f261e0
Show file tree
Hide file tree
Showing 56 changed files with 3,994 additions and 2,113 deletions.
12 changes: 12 additions & 0 deletions block/ll_rw_blk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down
4 changes: 2 additions & 2 deletions fs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
164 changes: 150 additions & 14 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);
spin_unlock(&dcache_lock);
security_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);

/**
Expand Down Expand Up @@ -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
Expand All @@ -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);
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
10 changes: 5 additions & 5 deletions fs/lockd/clntproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,22 +151,22 @@ 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) {
printk(KERN_NOTICE "NFSv4 file locking not implemented!\n");
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;

Expand Down
51 changes: 27 additions & 24 deletions fs/lockd/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand All @@ -179,39 +177,44 @@ 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;
dprintk("lockd: next rebind in %ld jiffies\n",
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 */

host->h_rpcclnt = clnt;
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;
}

/*
Expand Down
Loading

0 comments on commit 9f261e0

Please sign in to comment.