Skip to content

Commit

Permalink
Merge branch 'devel' into linux-next
Browse files Browse the repository at this point in the history
  • Loading branch information
Trond Myklebust authored and Trond Myklebust committed Dec 4, 2009
2 parents 0b08b07 + 44ed355 commit 7285f2d
Show file tree
Hide file tree
Showing 12 changed files with 261 additions and 114 deletions.
12 changes: 0 additions & 12 deletions fs/nfs/callback.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,6 @@ nfs4_callback_svc(void *vrqstp)

set_freezable();

/*
* FIXME: do we really need to run this under the BKL? If so, please
* add a comment about what it's intended to protect.
*/
lock_kernel();
while (!kthread_should_stop()) {
/*
* Listen for a request on the socket
Expand All @@ -104,7 +99,6 @@ nfs4_callback_svc(void *vrqstp)
preverr = err;
svc_process(rqstp);
}
unlock_kernel();
return 0;
}

Expand Down Expand Up @@ -160,11 +154,6 @@ nfs41_callback_svc(void *vrqstp)

set_freezable();

/*
* FIXME: do we really need to run this under the BKL? If so, please
* add a comment about what it's intended to protect.
*/
lock_kernel();
while (!kthread_should_stop()) {
prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
spin_lock_bh(&serv->sv_cb_lock);
Expand All @@ -183,7 +172,6 @@ nfs41_callback_svc(void *vrqstp)
}
finish_wait(&serv->sv_cb_waitq, &wq);
}
unlock_kernel();
return 0;
}

Expand Down
67 changes: 29 additions & 38 deletions fs/nfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1579,55 +1579,46 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct dentry *dentry = NULL, *rehash = NULL;
int error = -EBUSY;

/*
* To prevent any new references to the target during the rename,
* we unhash the dentry and free the inode in advance.
*/
if (!d_unhashed(new_dentry)) {
d_drop(new_dentry);
rehash = new_dentry;
}

dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n",
old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
atomic_read(&new_dentry->d_count));

/*
* First check whether the target is busy ... we can't
* safely do _any_ rename if the target is in use.
*
* For files, make a copy of the dentry and then do a
* silly-rename. If the silly-rename succeeds, the
* copied dentry is hashed and becomes the new target.
* For non-directories, check whether the target is busy and if so,
* make a copy of the dentry and then do a silly-rename. If the
* silly-rename succeeds, the copied dentry is hashed and becomes
* the new target.
*/
if (!new_inode)
goto go_ahead;
if (S_ISDIR(new_inode->i_mode)) {
error = -EISDIR;
if (!S_ISDIR(old_inode->i_mode))
goto out;
} else if (atomic_read(&new_dentry->d_count) > 2) {
int err;
/* copy the target dentry's name */
dentry = d_alloc(new_dentry->d_parent,
&new_dentry->d_name);
if (!dentry)
goto out;
if (new_inode && !S_ISDIR(new_inode->i_mode)) {
/*
* To prevent any new references to the target during the
* rename, we unhash the dentry in advance.
*/
if (!d_unhashed(new_dentry)) {
d_drop(new_dentry);
rehash = new_dentry;
}

if (atomic_read(&new_dentry->d_count) > 2) {
int err;

/* copy the target dentry's name */
dentry = d_alloc(new_dentry->d_parent,
&new_dentry->d_name);
if (!dentry)
goto out;

/* silly-rename the existing target ... */
err = nfs_sillyrename(new_dir, new_dentry);
if (!err) {
new_dentry = rehash = dentry;
/* silly-rename the existing target ... */
err = nfs_sillyrename(new_dir, new_dentry);
if (err)
goto out;

new_dentry = dentry;
new_inode = NULL;
/* instantiate the replacement target */
d_instantiate(new_dentry, NULL);
} else if (atomic_read(&new_dentry->d_count) > 1)
/* dentry still busy? */
goto out;
}
}

go_ahead:
/*
* ... prune child dentries and writebacks if needed.
*/
Expand Down
7 changes: 7 additions & 0 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,13 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
/* FALLTHROUGH */
#endif /* !defined(CONFIG_NFS_V4_1) */
case -NFS4ERR_FILE_OPEN:
if (exception->timeout > HZ) {
/* We have retried a decent amount, time to
* fail
*/
ret = -EBUSY;
break;
}
case -NFS4ERR_GRACE:
case -NFS4ERR_DELAY:
ret = nfs4_delay(server->client, &exception->timeout);
Expand Down
8 changes: 8 additions & 0 deletions fs/nfs/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,10 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
case -NFS4ERR_EXPIRED:
case -NFS4ERR_NO_GRACE:
case -NFS4ERR_STALE_CLIENTID:
case -NFS4ERR_BADSESSION:
case -NFS4ERR_BADSLOT:
case -NFS4ERR_BAD_HIGH_SLOT:
case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
goto out;
default:
printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
Expand Down Expand Up @@ -959,6 +963,10 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs
case -NFS4ERR_NO_GRACE:
nfs4_state_mark_reclaim_nograce(sp->so_client, state);
case -NFS4ERR_STALE_CLIENTID:
case -NFS4ERR_BADSESSION:
case -NFS4ERR_BADSLOT:
case -NFS4ERR_BAD_HIGH_SLOT:
case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
goto out_err;
}
nfs4_put_open_state(state);
Expand Down
104 changes: 82 additions & 22 deletions fs/nfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,14 +175,16 @@ static const match_table_t nfs_mount_option_tokens = {
};

enum {
Opt_xprt_udp, Opt_xprt_tcp, Opt_xprt_rdma,
Opt_xprt_udp, Opt_xprt_udp6, Opt_xprt_tcp, Opt_xprt_tcp6, Opt_xprt_rdma,

Opt_xprt_err
};

static const match_table_t nfs_xprt_protocol_tokens = {
{ Opt_xprt_udp, "udp" },
{ Opt_xprt_udp6, "udp6" },
{ Opt_xprt_tcp, "tcp" },
{ Opt_xprt_tcp6, "tcp6" },
{ Opt_xprt_rdma, "rdma" },

{ Opt_xprt_err, NULL }
Expand Down Expand Up @@ -492,6 +494,45 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
return sec_flavours[i].str;
}

static void nfs_show_mountd_netid(struct seq_file *m, struct nfs_server *nfss,
int showdefaults)
{
struct sockaddr *sap = (struct sockaddr *) &nfss->mountd_address;

seq_printf(m, ",mountproto=");
switch (sap->sa_family) {
case AF_INET:
switch (nfss->mountd_protocol) {
case IPPROTO_UDP:
seq_printf(m, RPCBIND_NETID_UDP);
break;
case IPPROTO_TCP:
seq_printf(m, RPCBIND_NETID_TCP);
break;
default:
if (showdefaults)
seq_printf(m, "auto");
}
break;
case AF_INET6:
switch (nfss->mountd_protocol) {
case IPPROTO_UDP:
seq_printf(m, RPCBIND_NETID_UDP6);
break;
case IPPROTO_TCP:
seq_printf(m, RPCBIND_NETID_TCP6);
break;
default:
if (showdefaults)
seq_printf(m, "auto");
}
break;
default:
if (showdefaults)
seq_printf(m, "auto");
}
}

static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
int showdefaults)
{
Expand All @@ -505,7 +546,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
}
case AF_INET6: {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
seq_printf(m, ",mountaddr=%pI6", &sin6->sin6_addr);
seq_printf(m, ",mountaddr=%pI6c", &sin6->sin6_addr);
break;
}
default:
Expand All @@ -518,17 +559,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
if (nfss->mountd_port || showdefaults)
seq_printf(m, ",mountport=%u", nfss->mountd_port);

switch (nfss->mountd_protocol) {
case IPPROTO_UDP:
seq_printf(m, ",mountproto=udp");
break;
case IPPROTO_TCP:
seq_printf(m, ",mountproto=tcp");
break;
default:
if (showdefaults)
seq_printf(m, ",mountproto=auto");
}
nfs_show_mountd_netid(m, nfss, showdefaults);
}

/*
Expand Down Expand Up @@ -578,7 +609,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
seq_puts(m, nfs_infop->nostr);
}
seq_printf(m, ",proto=%s",
rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO));
rpc_peeraddr2str(nfss->client, RPC_DISPLAY_NETID));
if (version == 4) {
if (nfss->port != NFS_PORT)
seq_printf(m, ",port=%u", nfss->port);
Expand Down Expand Up @@ -714,8 +745,6 @@ static void nfs_umount_begin(struct super_block *sb)
struct nfs_server *server;
struct rpc_clnt *rpc;

lock_kernel();

server = NFS_SB(sb);
/* -EIO all pending I/O */
rpc = server->client_acl;
Expand All @@ -724,8 +753,6 @@ static void nfs_umount_begin(struct super_block *sb)
rpc = server->client;
if (!IS_ERR(rpc))
rpc_killall_tasks(rpc);

unlock_kernel();
}

static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version)
Expand All @@ -734,8 +761,6 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int ve

data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data) {
data->rsize = NFS_MAX_FILE_IO_SIZE;
data->wsize = NFS_MAX_FILE_IO_SIZE;
data->acregmin = NFS_DEF_ACREGMIN;
data->acregmax = NFS_DEF_ACREGMAX;
data->acdirmin = NFS_DEF_ACDIRMIN;
Expand Down Expand Up @@ -887,6 +912,8 @@ static int nfs_parse_mount_options(char *raw,
{
char *p, *string, *secdata;
int rc, sloppy = 0, invalid_option = 0;
unsigned short protofamily = AF_UNSPEC;
unsigned short mountfamily = AF_UNSPEC;

if (!raw) {
dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
Expand Down Expand Up @@ -1232,12 +1259,17 @@ static int nfs_parse_mount_options(char *raw,
token = match_token(string,
nfs_xprt_protocol_tokens, args);

protofamily = AF_INET;
switch (token) {
case Opt_xprt_udp6:
protofamily = AF_INET6;
case Opt_xprt_udp:
mnt->flags &= ~NFS_MOUNT_TCP;
mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP;
kfree(string);
break;
case Opt_xprt_tcp6:
protofamily = AF_INET6;
case Opt_xprt_tcp:
mnt->flags |= NFS_MOUNT_TCP;
mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP;
Expand Down Expand Up @@ -1265,10 +1297,15 @@ static int nfs_parse_mount_options(char *raw,
nfs_xprt_protocol_tokens, args);
kfree(string);

mountfamily = AF_INET;
switch (token) {
case Opt_xprt_udp6:
mountfamily = AF_INET6;
case Opt_xprt_udp:
mnt->mount_server.protocol = XPRT_TRANSPORT_UDP;
break;
case Opt_xprt_tcp6:
mountfamily = AF_INET6;
case Opt_xprt_tcp:
mnt->mount_server.protocol = XPRT_TRANSPORT_TCP;
break;
Expand Down Expand Up @@ -1367,8 +1404,33 @@ static int nfs_parse_mount_options(char *raw,
if (!sloppy && invalid_option)
return 0;

/*
* verify that any proto=/mountproto= options match the address
* familiies in the addr=/mountaddr= options.
*/
if (protofamily != AF_UNSPEC &&
protofamily != mnt->nfs_server.address.ss_family)
goto out_proto_mismatch;

if (mountfamily != AF_UNSPEC) {
if (mnt->mount_server.addrlen) {
if (mountfamily != mnt->mount_server.address.ss_family)
goto out_mountproto_mismatch;
} else {
if (mountfamily != mnt->nfs_server.address.ss_family)
goto out_mountproto_mismatch;
}
}

return 1;

out_mountproto_mismatch:
printk(KERN_INFO "NFS: mount server address does not match mountproto= "
"option\n");
return 0;
out_proto_mismatch:
printk(KERN_INFO "NFS: server address does not match proto= option\n");
return 0;
out_invalid_address:
printk(KERN_INFO "NFS: bad IP address specified: %s\n", p);
return 0;
Expand Down Expand Up @@ -1881,7 +1943,6 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
if (data == NULL)
return -ENOMEM;

lock_kernel();
/* fill out struct with values from existing mount */
data->flags = nfss->flags;
data->rsize = nfss->rsize;
Expand All @@ -1907,7 +1968,6 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
error = nfs_compare_remount_data(nfss, data);
out:
kfree(data);
unlock_kernel();
return error;
}

Expand Down
2 changes: 1 addition & 1 deletion include/linux/nfs_xdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,8 @@ struct nfs4_sequence_args {
struct nfs4_sequence_res {
struct nfs4_session *sr_session;
u8 sr_slotid; /* slot used to send request */
unsigned long sr_renewal_time;
int sr_status; /* sequence operation status */
unsigned long sr_renewal_time;
};

struct nfs4_get_lease_time_args {
Expand Down
Loading

0 comments on commit 7285f2d

Please sign in to comment.