Skip to content

Commit

Permalink
Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/n…
Browse files Browse the repository at this point in the history
…fs-2.6

* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
  NFS: Fix decode_secinfo_maxsz
  NFSv4.1: Fix an off-by-one error in pnfs_generic_pg_test
  NFSv4.1: Fix some issues with pnfs_generic_pg_test
  NFSv4.1: file layout must consider pg_bsize for coalescing
  pnfs-obj: No longer needed to take an extra ref at add_device
  SUNRPC: Ensure the RPC client only quits on fatal signals
  NFSv4: Fix a readdir regression
  nfs4.1: mark layout as bad on error path in _pnfs_return_layout
  nfs4.1: prevent race that allowed use of freed layout in _pnfs_return_layout
  NFSv4.1: need to put_layout_hdr on _pnfs_return_layout error path
  NFS: (d)printks should use %zd for ssize_t arguments
  NFSv4.1: fix break condition in pnfs_find_lseg
  nfs4.1: fix several problems with _pnfs_return_layout
  NFSv4.1: allow zero fh array in filelayout decode layout
  NFSv4.1: allow nfs_fhget to succeed with mounted on fileid
  NFSv4.1: Fix a refcounting issue in the pNFS device id cache
  NFSv4.1: deprecate headerpadsz in CREATE_SESSION
  NFS41: do not update isize if inode needs layoutcommit
  NLM: Don't hang forever on NLM unlock requests
  NFS: fix umount of pnfs filesystems
  • Loading branch information
torvalds committed Jun 22, 2011
2 parents e08f6d4 + 1650add commit 2992c4b
Show file tree
Hide file tree
Showing 18 changed files with 139 additions and 66 deletions.
8 changes: 7 additions & 1 deletion fs/lockd/clntproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,13 @@ static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)

if (task->tk_status < 0) {
dprintk("lockd: unlock failed (err = %d)\n", -task->tk_status);
goto retry_rebind;
switch (task->tk_status) {
case -EACCES:
case -EIO:
goto die;
default:
goto retry_rebind;
}
}
if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
rpc_delay(task, NLMCLNT_GRACE_WAIT);
Expand Down
6 changes: 4 additions & 2 deletions fs/nfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)

nfs_attr_check_mountpoint(sb, fattr);

if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0 && (fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0)
if (((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0) &&
!nfs_attr_use_mounted_on_fileid(fattr))
goto out_no_inode;
if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0)
goto out_no_inode;
Expand Down Expand Up @@ -1294,7 +1295,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (new_isize != cur_isize) {
/* Do we perhaps have any outstanding writes, or has
* the file grown beyond our last write? */
if (nfsi->npages == 0 || new_isize > cur_isize) {
if ((nfsi->npages == 0 && !test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) ||
new_isize > cur_isize) {
i_size_write(inode, new_isize);
invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
}
Expand Down
11 changes: 11 additions & 0 deletions fs/nfs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ static inline void nfs_attr_check_mountpoint(struct super_block *parent, struct
fattr->valid |= NFS_ATTR_FATTR_MOUNTPOINT;
}

static inline int nfs_attr_use_mounted_on_fileid(struct nfs_fattr *fattr)
{
if (((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) == 0) ||
(((fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0) &&
((fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) == 0)))
return 0;

fattr->fileid = fattr->mounted_on_fileid;
return 1;
}

struct nfs_clone_mount {
const struct super_block *sb;
const struct dentry *dentry;
Expand Down
21 changes: 14 additions & 7 deletions fs/nfs/nfs4filelayout.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
*/

#include <linux/nfs_fs.h>
#include <linux/nfs_page.h>

#include "internal.h"
#include "nfs4filelayout.h"
Expand Down Expand Up @@ -552,13 +553,18 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
__func__, nfl_util, fl->num_fh, fl->first_stripe_index,
fl->pattern_offset);

if (!fl->num_fh)
/* Note that a zero value for num_fh is legal for STRIPE_SPARSE.
* Futher checking is done in filelayout_check_layout */
if (fl->num_fh < 0 || fl->num_fh >
max(NFS4_PNFS_MAX_STRIPE_CNT, NFS4_PNFS_MAX_MULTI_CNT))
goto out_err;

fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
gfp_flags);
if (!fl->fh_array)
goto out_err;
if (fl->num_fh > 0) {
fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
gfp_flags);
if (!fl->fh_array)
goto out_err;
}

for (i = 0; i < fl->num_fh; i++) {
/* Do we want to use a mempool here? */
Expand Down Expand Up @@ -661,8 +667,9 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
u64 p_stripe, r_stripe;
u32 stripe_unit;

if (!pnfs_generic_pg_test(pgio, prev, req))
return 0;
if (!pnfs_generic_pg_test(pgio, prev, req) ||
!nfs_generic_pg_test(pgio, prev, req))
return false;

if (!pgio->pg_lseg)
return 1;
Expand Down
45 changes: 27 additions & 18 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2265,12 +2265,14 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
return nfs4_map_errors(status);
}

static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr);
/*
* Get locations and (maybe) other attributes of a referral.
* Note that we'll actually follow the referral later when
* we detect fsid mismatch in inode revalidation
*/
static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct nfs_fattr *fattr, struct nfs_fh *fhandle)
static int nfs4_get_referral(struct inode *dir, const struct qstr *name,
struct nfs_fattr *fattr, struct nfs_fh *fhandle)
{
int status = -ENOMEM;
struct page *page = NULL;
Expand All @@ -2288,15 +2290,16 @@ static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct
goto out;
/* Make sure server returned a different fsid for the referral */
if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) {
dprintk("%s: server did not return a different fsid for a referral at %s\n", __func__, name->name);
dprintk("%s: server did not return a different fsid for"
" a referral at %s\n", __func__, name->name);
status = -EIO;
goto out;
}
/* Fixup attributes for the nfs_lookup() call to nfs_fhget() */
nfs_fixup_referral_attributes(&locations->fattr);

/* replace the lookup nfs_fattr with the locations nfs_fattr */
memcpy(fattr, &locations->fattr, sizeof(struct nfs_fattr));
fattr->valid |= NFS_ATTR_FATTR_V4_REFERRAL;
if (!fattr->mode)
fattr->mode = S_IFDIR;
memset(fhandle, 0, sizeof(struct nfs_fh));
out:
if (page)
Expand Down Expand Up @@ -4667,11 +4670,15 @@ static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list,
return len;
}

/*
* nfs_fhget will use either the mounted_on_fileid or the fileid
*/
static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr)
{
if (!((fattr->valid & NFS_ATTR_FATTR_FILEID) &&
(fattr->valid & NFS_ATTR_FATTR_FSID) &&
(fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)))
if (!(((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) ||
(fattr->valid & NFS_ATTR_FATTR_FILEID)) &&
(fattr->valid & NFS_ATTR_FATTR_FSID) &&
(fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)))
return;

fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE |
Expand All @@ -4686,7 +4693,6 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
struct nfs_server *server = NFS_SERVER(dir);
u32 bitmask[2] = {
[0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS,
[1] = FATTR4_WORD1_MOUNTED_ON_FILEID,
};
struct nfs4_fs_locations_arg args = {
.dir_fh = NFS_FH(dir),
Expand All @@ -4705,11 +4711,18 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
int status;

dprintk("%s: start\n", __func__);

/* Ask for the fileid of the absent filesystem if mounted_on_fileid
* is not supported */
if (NFS_SERVER(dir)->attr_bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
bitmask[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID;
else
bitmask[0] |= FATTR4_WORD0_FILEID;

nfs_fattr_init(&fs_locations->fattr);
fs_locations->server = server;
fs_locations->nlocations = 0;
status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
nfs_fixup_referral_attributes(&fs_locations->fattr);
dprintk("%s: returned status = %d\n", __func__, status);
return status;
}
Expand Down Expand Up @@ -5098,7 +5111,6 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
if (mxresp_sz == 0)
mxresp_sz = NFS_MAX_FILE_IO_SIZE;
/* Fore channel attributes */
args->fc_attrs.headerpadsz = 0;
args->fc_attrs.max_rqst_sz = mxrqst_sz;
args->fc_attrs.max_resp_sz = mxresp_sz;
args->fc_attrs.max_ops = NFS4_MAX_OPS;
Expand All @@ -5111,7 +5123,6 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
args->fc_attrs.max_ops, args->fc_attrs.max_reqs);

/* Back channel attributes */
args->bc_attrs.headerpadsz = 0;
args->bc_attrs.max_rqst_sz = PAGE_SIZE;
args->bc_attrs.max_resp_sz = PAGE_SIZE;
args->bc_attrs.max_resp_sz_cached = 0;
Expand All @@ -5131,8 +5142,6 @@ static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args
struct nfs4_channel_attrs *sent = &args->fc_attrs;
struct nfs4_channel_attrs *rcvd = &session->fc_attrs;

if (rcvd->headerpadsz > sent->headerpadsz)
return -EINVAL;
if (rcvd->max_resp_sz > sent->max_resp_sz)
return -EINVAL;
/*
Expand Down Expand Up @@ -5697,6 +5706,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
{
struct nfs4_layoutreturn *lrp = calldata;
struct nfs_server *server;
struct pnfs_layout_hdr *lo = NFS_I(lrp->args.inode)->layout;

dprintk("--> %s\n", __func__);

Expand All @@ -5708,16 +5718,15 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
nfs_restart_rpc(task, lrp->clp);
return;
}
spin_lock(&lo->plh_inode->i_lock);
if (task->tk_status == 0) {
struct pnfs_layout_hdr *lo = NFS_I(lrp->args.inode)->layout;

if (lrp->res.lrs_present) {
spin_lock(&lo->plh_inode->i_lock);
pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
spin_unlock(&lo->plh_inode->i_lock);
} else
BUG_ON(!list_empty(&lo->plh_segs));
}
lo->plh_block_lgets--;
spin_unlock(&lo->plh_inode->i_lock);
dprintk("<-- %s\n", __func__);
}

Expand Down
26 changes: 14 additions & 12 deletions fs/nfs/nfs4xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ static int nfs4_stat_to_errno(int);
#define decode_fs_locations_maxsz \
(0)
#define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz)
#define decode_secinfo_maxsz (op_decode_hdr_maxsz + 4 + (NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)))
#define decode_secinfo_maxsz (op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4))

#if defined(CONFIG_NFS_V4_1)
#define NFS4_MAX_MACHINE_NAME_LEN (64)
Expand Down Expand Up @@ -1725,7 +1725,7 @@ static void encode_create_session(struct xdr_stream *xdr,
*p++ = cpu_to_be32(args->flags); /*flags */

/* Fore Channel */
*p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */
*p++ = cpu_to_be32(0); /* header padding size */
*p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */
*p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */
*p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */
Expand All @@ -1734,7 +1734,7 @@ static void encode_create_session(struct xdr_stream *xdr,
*p++ = cpu_to_be32(0); /* rdmachannel_attrs */

/* Back Channel */
*p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */
*p++ = cpu_to_be32(0); /* header padding size */
*p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */
*p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */
*p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */
Expand Down Expand Up @@ -3098,7 +3098,7 @@ static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint
return -EIO;
}

static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap)
static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res)
{
__be32 *p;

Expand All @@ -3109,7 +3109,7 @@ static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap)
if (unlikely(!p))
goto out_overflow;
bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
return -be32_to_cpup(p);
*res = -be32_to_cpup(p);
}
return 0;
out_overflow:
Expand Down Expand Up @@ -4070,6 +4070,7 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
int status;
umode_t fmode = 0;
uint32_t type;
int32_t err;

status = decode_attr_type(xdr, bitmap, &type);
if (status < 0)
Expand All @@ -4095,13 +4096,12 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
goto xdr_error;
fattr->valid |= status;

status = decode_attr_error(xdr, bitmap);
if (status == -NFS4ERR_WRONGSEC) {
nfs_fixup_secinfo_attributes(fattr, fh);
status = 0;
}
err = 0;
status = decode_attr_error(xdr, bitmap, &err);
if (status < 0)
goto xdr_error;
if (err == -NFS4ERR_WRONGSEC)
nfs_fixup_secinfo_attributes(fattr, fh);

status = decode_attr_filehandle(xdr, bitmap, fh);
if (status < 0)
Expand Down Expand Up @@ -4997,12 +4997,14 @@ static int decode_chan_attrs(struct xdr_stream *xdr,
struct nfs4_channel_attrs *attrs)
{
__be32 *p;
u32 nr_attrs;
u32 nr_attrs, val;

p = xdr_inline_decode(xdr, 28);
if (unlikely(!p))
goto out_overflow;
attrs->headerpadsz = be32_to_cpup(p++);
val = be32_to_cpup(p++); /* headerpadsz */
if (val)
return -EINVAL; /* no support for header padding yet */
attrs->max_rqst_sz = be32_to_cpup(p++);
attrs->max_resp_sz = be32_to_cpup(p++);
attrs->max_resp_sz_cached = be32_to_cpup(p++);
Expand Down
4 changes: 3 additions & 1 deletion fs/nfs/objlayout/objio_osd.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ _dev_list_add(const struct nfs_server *nfss,
de = n;
}

atomic_inc(&de->id_node.ref);
return de;
}

Expand Down Expand Up @@ -1001,6 +1000,9 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio,
if (!pnfs_generic_pg_test(pgio, prev, req))
return false;

if (pgio->pg_lseg == NULL)
return true;

return pgio->pg_count + req->wb_bytes <=
OBJIO_LSEG(pgio->pg_lseg)->max_io_size;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/nfs/objlayout/objlayout.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ objlayout_read_done(struct objlayout_io_state *state, ssize_t status, bool sync)
struct nfs_read_data *rdata;

state->status = status;
dprintk("%s: Begin status=%ld eof=%d\n", __func__, status, eof);
dprintk("%s: Begin status=%zd eof=%d\n", __func__, status, eof);
rdata = state->rpcdata;
rdata->task.tk_status = status;
if (status >= 0) {
Expand Down
3 changes: 2 additions & 1 deletion fs/nfs/pagelist.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ nfs_wait_on_request(struct nfs_page *req)
TASK_UNINTERRUPTIBLE);
}

static bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_page *prev, struct nfs_page *req)
bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_page *prev, struct nfs_page *req)
{
/*
* FIXME: ideally we should be able to coalesce all requests
Expand All @@ -218,6 +218,7 @@ static bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_p

return desc->pg_count + req->wb_bytes <= desc->pg_bsize;
}
EXPORT_SYMBOL_GPL(nfs_generic_pg_test);

/**
* nfs_pageio_init - initialise a page io descriptor
Expand Down
Loading

0 comments on commit 2992c4b

Please sign in to comment.