mirror of https://gitee.com/openkylin/linux.git
NFS client bugfixes for 3.12
- Stable fix for Oopses in the pNFS files layout driver - Fix a regression when doing a non-exclusive file create on NFSv4.x - NFSv4.1 security negotiation fixes when looking up the root filesystem - Fix a memory ordering issue in the pNFS files layout driver -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) iQIcBAABAgAGBQJSSfNNAAoJEGcL54qWCgDybGYQAJGm4/vd7/rWZ49KIjGFGkFo sCt0UOK6Y6ALhUOIlIreXsQ+Iwn9aAoIIRgx8UwnB+hO6PGnSyFuJZZx1KE8V2kj 6JlE5FbsWV+3uFQzNJQsNcoj7NZMzIRZT7x+7QansBOdSQjgQc3ig2sAMWREZjn8 GxMOl8FNRrnP8gRom30ZScgMp1YDM8J1ql80S/nbxh2NOLBsvgg9VapzJhhqkMyl b7WKX4Qbg4AeSaxIAIrIwcZ7L2YS09JGC40VSybQARs0/7J8fjOZPs7CmrUCoB5F DmT5vfEC4+dqDf8PMyoFVfxK5ua5Sb/FGQmagYYa8bSgY7Uq03akYI++co+4PZU1 f3SN6CSvVffzGMdXAhUupOZQbkKvKFxR2MTGy8s7dxdkQudd4RioYPDmLfCHlbmb VY5kFh/Duqso1FCrcfvZoC88ElrWUz5yoVzZyECOEwCs1wjI6bjmGdSqCSbU75Lm Z0XOAn1cStwFvGwCbGZPUzlvueji3coDdCFPBXAOFHzisLYoo/Lxenw7l5D1qM5b 02iZllcIo340vw8wxHZxVebecFo33P90X1gjv0HQQkV/6EeNgq4D47SWTPxRq3Ai Dl9MFjTPl51oseDLrH6I/hBvcqjksB1M1+WjifT0bCIi3Y0HAea2U0wgweHS3vAd QHqIpIJxNHDjPBMDWEZW =ScfI -----END PGP SIGNATURE----- Merge tag 'nfs-for-3.12-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs Pull NFS client bugfixes from Trond Myklebust: - Stable fix for Oopses in the pNFS files layout driver - Fix a regression when doing a non-exclusive file create on NFSv4.x - NFSv4.1 security negotiation fixes when looking up the root filesystem - Fix a memory ordering issue in the pNFS files layout driver * tag 'nfs-for-3.12-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFS: Give "flavor" an initial value to fix a compile warning NFSv4.1: try SECINFO_NO_NAME flavs until one works NFSv4.1: Ensure memory ordering between nfs4_ds_connect and nfs4_fl_prepare_ds NFSv4.1: nfs4_fl_prepare_ds - fix bugs when the connect attempt fails NFSv4: Honour the 'opened' parameter in the atomic_open() filesystem method
This commit is contained in:
commit
f927318840
|
@ -1458,7 +1458,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
|
|||
|
||||
trace_nfs_atomic_open_enter(dir, ctx, open_flags);
|
||||
nfs_block_sillyrename(dentry->d_parent);
|
||||
inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr);
|
||||
inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr, opened);
|
||||
nfs_unblock_sillyrename(dentry->d_parent);
|
||||
if (IS_ERR(inode)) {
|
||||
err = PTR_ERR(inode);
|
||||
|
|
|
@ -19,6 +19,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)
|
|||
struct inode *dir;
|
||||
unsigned openflags = filp->f_flags;
|
||||
struct iattr attr;
|
||||
int opened = 0;
|
||||
int err;
|
||||
|
||||
/*
|
||||
|
@ -55,7 +56,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)
|
|||
nfs_wb_all(inode);
|
||||
}
|
||||
|
||||
inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr);
|
||||
inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr, &opened);
|
||||
if (IS_ERR(inode)) {
|
||||
err = PTR_ERR(inode);
|
||||
switch (err) {
|
||||
|
|
|
@ -185,6 +185,7 @@ nfs4_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds)
|
|||
if (status)
|
||||
goto out_put;
|
||||
|
||||
smp_wmb();
|
||||
ds->ds_clp = clp;
|
||||
dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr);
|
||||
out:
|
||||
|
@ -801,34 +802,35 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
|
|||
struct nfs4_file_layout_dsaddr *dsaddr = FILELAYOUT_LSEG(lseg)->dsaddr;
|
||||
struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx];
|
||||
struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
|
||||
|
||||
if (filelayout_test_devid_unavailable(devid))
|
||||
return NULL;
|
||||
struct nfs4_pnfs_ds *ret = ds;
|
||||
|
||||
if (ds == NULL) {
|
||||
printk(KERN_ERR "NFS: %s: No data server for offset index %d\n",
|
||||
__func__, ds_idx);
|
||||
filelayout_mark_devid_invalid(devid);
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
smp_rmb();
|
||||
if (ds->ds_clp)
|
||||
return ds;
|
||||
goto out_test_devid;
|
||||
|
||||
if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) {
|
||||
struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode);
|
||||
int err;
|
||||
|
||||
err = nfs4_ds_connect(s, ds);
|
||||
if (err) {
|
||||
if (err)
|
||||
nfs4_mark_deviceid_unavailable(devid);
|
||||
ds = NULL;
|
||||
}
|
||||
nfs4_clear_ds_conn_bit(ds);
|
||||
} else {
|
||||
/* Either ds is connected, or ds is NULL */
|
||||
nfs4_wait_ds_connect(ds);
|
||||
}
|
||||
return ds;
|
||||
out_test_devid:
|
||||
if (filelayout_test_devid_unavailable(devid))
|
||||
ret = NULL;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
module_param(dataserver_retrans, uint, 0644);
|
||||
|
|
|
@ -912,6 +912,7 @@ struct nfs4_opendata {
|
|||
struct iattr attrs;
|
||||
unsigned long timestamp;
|
||||
unsigned int rpc_done : 1;
|
||||
unsigned int file_created : 1;
|
||||
unsigned int is_recover : 1;
|
||||
int rpc_status;
|
||||
int cancelled;
|
||||
|
@ -1946,8 +1947,13 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
|
|||
|
||||
nfs_fattr_map_and_free_names(server, &data->f_attr);
|
||||
|
||||
if (o_arg->open_flags & O_CREAT)
|
||||
if (o_arg->open_flags & O_CREAT) {
|
||||
update_changeattr(dir, &o_res->cinfo);
|
||||
if (o_arg->open_flags & O_EXCL)
|
||||
data->file_created = 1;
|
||||
else if (o_res->cinfo.before != o_res->cinfo.after)
|
||||
data->file_created = 1;
|
||||
}
|
||||
if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0)
|
||||
server->caps &= ~NFS_CAP_POSIX_LOCK;
|
||||
if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
|
||||
|
@ -2191,7 +2197,8 @@ static int _nfs4_do_open(struct inode *dir,
|
|||
struct nfs_open_context *ctx,
|
||||
int flags,
|
||||
struct iattr *sattr,
|
||||
struct nfs4_label *label)
|
||||
struct nfs4_label *label,
|
||||
int *opened)
|
||||
{
|
||||
struct nfs4_state_owner *sp;
|
||||
struct nfs4_state *state = NULL;
|
||||
|
@ -2261,6 +2268,8 @@ static int _nfs4_do_open(struct inode *dir,
|
|||
nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel);
|
||||
}
|
||||
}
|
||||
if (opendata->file_created)
|
||||
*opened |= FILE_CREATED;
|
||||
|
||||
if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server))
|
||||
*ctx_th = opendata->f_attr.mdsthreshold;
|
||||
|
@ -2289,7 +2298,8 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir,
|
|||
struct nfs_open_context *ctx,
|
||||
int flags,
|
||||
struct iattr *sattr,
|
||||
struct nfs4_label *label)
|
||||
struct nfs4_label *label,
|
||||
int *opened)
|
||||
{
|
||||
struct nfs_server *server = NFS_SERVER(dir);
|
||||
struct nfs4_exception exception = { };
|
||||
|
@ -2297,7 +2307,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir,
|
|||
int status;
|
||||
|
||||
do {
|
||||
status = _nfs4_do_open(dir, ctx, flags, sattr, label);
|
||||
status = _nfs4_do_open(dir, ctx, flags, sattr, label, opened);
|
||||
res = ctx->state;
|
||||
trace_nfs4_open_file(ctx, flags, status);
|
||||
if (status == 0)
|
||||
|
@ -2659,7 +2669,8 @@ int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait)
|
|||
}
|
||||
|
||||
static struct inode *
|
||||
nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
|
||||
nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx,
|
||||
int open_flags, struct iattr *attr, int *opened)
|
||||
{
|
||||
struct nfs4_state *state;
|
||||
struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL;
|
||||
|
@ -2667,7 +2678,7 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags
|
|||
label = nfs4_label_init_security(dir, ctx->dentry, attr, &l);
|
||||
|
||||
/* Protect against concurrent sillydeletes */
|
||||
state = nfs4_do_open(dir, ctx, open_flags, attr, label);
|
||||
state = nfs4_do_open(dir, ctx, open_flags, attr, label, opened);
|
||||
|
||||
nfs4_label_release_security(label);
|
||||
|
||||
|
@ -3332,6 +3343,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
|||
struct nfs4_label l, *ilabel = NULL;
|
||||
struct nfs_open_context *ctx;
|
||||
struct nfs4_state *state;
|
||||
int opened = 0;
|
||||
int status = 0;
|
||||
|
||||
ctx = alloc_nfs_open_context(dentry, FMODE_READ);
|
||||
|
@ -3341,7 +3353,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
|||
ilabel = nfs4_label_init_security(dir, dentry, sattr, &l);
|
||||
|
||||
sattr->ia_mode &= ~current_umask();
|
||||
state = nfs4_do_open(dir, ctx, flags, sattr, ilabel);
|
||||
state = nfs4_do_open(dir, ctx, flags, sattr, ilabel, &opened);
|
||||
if (IS_ERR(state)) {
|
||||
status = PTR_ERR(state);
|
||||
goto out;
|
||||
|
@ -7564,8 +7576,10 @@ nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
|
|||
{
|
||||
int err;
|
||||
struct page *page;
|
||||
rpc_authflavor_t flavor;
|
||||
rpc_authflavor_t flavor = RPC_AUTH_MAXFLAVOR;
|
||||
struct nfs4_secinfo_flavors *flavors;
|
||||
struct nfs4_secinfo4 *secinfo;
|
||||
int i;
|
||||
|
||||
page = alloc_page(GFP_KERNEL);
|
||||
if (!page) {
|
||||
|
@ -7587,9 +7601,31 @@ nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
|
|||
if (err)
|
||||
goto out_freepage;
|
||||
|
||||
flavor = nfs_find_best_sec(flavors);
|
||||
if (err == 0)
|
||||
err = nfs4_lookup_root_sec(server, fhandle, info, flavor);
|
||||
for (i = 0; i < flavors->num_flavors; i++) {
|
||||
secinfo = &flavors->flavors[i];
|
||||
|
||||
switch (secinfo->flavor) {
|
||||
case RPC_AUTH_NULL:
|
||||
case RPC_AUTH_UNIX:
|
||||
case RPC_AUTH_GSS:
|
||||
flavor = rpcauth_get_pseudoflavor(secinfo->flavor,
|
||||
&secinfo->flavor_info);
|
||||
break;
|
||||
default:
|
||||
flavor = RPC_AUTH_MAXFLAVOR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (flavor != RPC_AUTH_MAXFLAVOR) {
|
||||
err = nfs4_lookup_root_sec(server, fhandle,
|
||||
info, flavor);
|
||||
if (!err)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flavor == RPC_AUTH_MAXFLAVOR)
|
||||
err = -EPERM;
|
||||
|
||||
out_freepage:
|
||||
put_page(page);
|
||||
|
|
|
@ -1455,7 +1455,8 @@ struct nfs_rpc_ops {
|
|||
struct inode * (*open_context) (struct inode *dir,
|
||||
struct nfs_open_context *ctx,
|
||||
int open_flags,
|
||||
struct iattr *iattr);
|
||||
struct iattr *iattr,
|
||||
int *);
|
||||
int (*have_delegation)(struct inode *, fmode_t);
|
||||
int (*return_delegation)(struct inode *);
|
||||
struct nfs_client *(*alloc_client) (const struct nfs_client_initdata *);
|
||||
|
|
Loading…
Reference in New Issue